function libshared_pal_thread_start

From liblfds.org
Jump to navigation Jump to search

Source Files

└───test_and_benchmark
    └───libshared
        ├───inc
        │   └───libshared
        │           libtest_porting_abstraction_layer.h
        └───src
            └───libshared_porting_abstraction_layer
                    libshared_porting_abstraction_layer_thread_start.c

Typedefs

typedef [type] libshared_pal_thread_handle_t;

Opaque Structures

struct libshared_pal_thread_info;

Macros

#define LIBSHARED_PAL_PTI_GET_LOGICAL_PROCESSOR_NUMBER( libshared_pal_thread_info )
#define LIBSHARED_PAL_PTI_GET_WINDOWS_PROCESSOR_GROUP_NUMBER( libshared_pal_thread_info )
#define LIBSHARED_PAL_PTI_GET_NUMA_NODE( libshared_pal_thread_info )
#define LIBSHARED_PAL_PTI_GET_THREAD_FUNCTION( libshared_pal_thread_info )
#define LIBSHARED_PAL_PTI_GET_THREAD_ARGUMENT( libshared_pal_thread_info )

Prototype

int libshared_pal_thread_start( libshared_pal_thread_handle_t *thread_handle,
                                struct libshared_pal_thread_info *pti );

Parameters

libshared_pal_thread_handle_t *thread_handle

A pointer to a libshared_pal_thread_handle_t, which is set to the handle to the created thread.

struct libshared_pal_thread_info *pti

A pointer to an opaque structure, accessed by macros, which contains the logical processor number (and, on Windows 7 and above, the windows processor group number) the thread must be pinned to.

Return Value

Return 1 on success, 0 on failure.

Example

int libshared_pal_thread_start( libshared_pal_thread_handle_t *thread_handle,
                                struct libshared_pal_thread_info *pti )
{
  int
    rv = 0;

  DWORD
    thread_id;

  DWORD_PTR
    affinity_mask,
    result;

  LFDS711_PAL_ASSERT( thread_handle != NULL );
  LFDS711_PAL_ASSERT( pti != NULL );

  *thread_handle = CreateThread( NULL, 0, LIBSHARED_PAL_PTI_GET_THREAD_FUNCTION(*pti), LIBSHARED_PAL_PTI_GET_THREAD_ARGUMENT(*pti), CREATE_SUSPENDED, &thread_id );

  if( *thread_handle != NULL )
  {
    affinity_mask = (DWORD_PTR) (1 << LIBSHARED_PAL_PTI_GET_LOGICAL_PROCESSOR_NUMBER(*pti));
    SetThreadAffinityMask( *thread_handle, affinity_mask );
    ResumeThread( *thread_handle );
    rv = 1;
  }

  return rv;
}

Notes

This function starts a thread and ensures it is pinned to the logical processor specified in the libshared_pal_thread_info argument.

On many systems, it is not possible to in the act of starting a thread specify a logical processor it should be pinned to. Rather, there exist only a function which can be called by a thread to set its affinity - i.e. the thread has to be running, and then has to make that function call itself.

To address this issue, the information necessary to start a thread (the logical processor number, windows processor group, a pointer to the thread function and the argument to be supplied to the thread) are all in the struct libshared_pal_thread_info argument. The intended use is that the abstraction implementation contains a thread function of its own, and it is this thread which initially is started, and it is passed the struct libshared_pal_thread_info as its argument. Then, in this thread, the thread pins itself to the logical processor specified in pti, and then calls the actual thread function, passing in the thread argument, both of which of course are also available from pti.

Note that the NUMA node ID available from pti is only needed by the Linux kernel implementation, where that implementation is incomplete due to the lack of a "wait-until-thread-returns" function, and as such, that member of struct libshared_pal_thread_info is not yet set and so cannot be used. The macro is included here in the documentation to prevent confusion in the minds of those who inspect the header files.

See Also