function porting_abstraction_layer_thread_start
Source Files
└───test └───src └───porting_abstraction_layer_thread_start.c
Prototype
int test_pal_thread_start( test_pal_thread_state_t *thread_state, struct test_pal_logical_processor *lp, test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state), void *thread_user_state );
Parameters
test_pal_thread_state_t *thread_state
- A pointer to a test_pal_thread_state_t, which is set to the thread state for the newly started thread.
struct test_pal_logical_processor *lp
- A pointer to a struct test_pal_logical_processor. which indicates which logical core the new thread should be pinned to.
test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state)
- The thread function.
void *thread_user_state
- This is the void pointer which is passed to the thread function as its argument.
Return Value
The return value is 1 if the thread has been successfully created, 0 otherwise.
Notes
This function starts a thread, using the thread function thread_function, passing it the argument thread_user_state, and pins the thread to the logical processor specified by *lp. Pinning threads can be awkward. An example of this is under Android, where the normal POSIX function for affinity is not supported, such that on that platform only the thread itself can change its own affinity (i.e. it cannot be created with an affinity), and so the implementation actually starts the thread with a 'first-stage' thread function, which sets the thread affinity, and then calls the thread function specified by the thread_function argument.
Example
int test_pal_thread_start( test_pal_thread_state_t *thread_state, struct test_pal_logical_processor *lp, test_pal_thread_return_t (TEST_PAL_CALLING_CONVENTION *thread_function)(void *thread_user_state), void *thread_user_state ) { int rv = 0; DWORD thread_id; DWORD_PTR affinity_mask, result; assert( thread_state != NULL ); assert( lp != NULL ); assert( thread_function != NULL ); // TRD : thread_user_state can be NULL /* TRD : Vista and earlier do not support processor groups as such, there is a single implicit processor group also, there's no support for actually starting a thread in its correct NUMA node / logical processor so we make the best of it; we start suspended, set the affinity, and then resume the thread itself internally is expected to be making allocs from the correct NUMA node */ *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, CREATE_SUSPENDED, &thread_id ); affinity_mask = (DWORD_PTR) (1 << lp->logical_processor_number); SetThreadAffinityMask( *thread_state, affinity_mask ); ResumeThread( *thread_state ); if( *thread_state != NULL ) rv = 1; return( rv ); }