r6.1.1:abstraction_thread_start
Source Files
/test/src/abstraction_thread_start.c /test/src/abstraction.h
Prototype
int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state );
Parameters
thread_state_t *thread_state
- The address of a thread_state_t into which the thread state will be placed. Thread states are operating systems defined types (such as a HANDLE under Windows, or a pthread_t under pthreads) and these are allocated on the heap or the stack by the user and the address of the variable is passed.
unsigned int cpu
- The CPU number this thread should show affinity to. This will be a value from 0 to one less than the value returned by abstraction_cpu_count. Not all systems can set CPU affinity; as such, this behaviour is desirable but not essential. If your system can set the thread affinity, do so; it makes for a better test. If not, then the test relies on the operating system balancing the threads out over CPUs.
thread_function_t thread_function
- The thread function. The function pointer type will automatically be correct for your platform if thread_return_t is correctly set and if your platform's thread function prototype takes a single void pointer as an argument. If your thread function prototypes takes a different set of arguments, the test program will not in its current form compile on your platform.
void *thread_user_state
- A single void pointer of user state which is passed into the thread function.
Return Value
Returns 1 on successful thread start. Returns 0 on failure.
Notes
This function provides the test program with a way to start a thread. It is assumed that the thread function prototype takes a single void pointer as an argument (this is true for Windows and pthreads). The return value of the thread function is specified by the thread_return_t typedef and the combination of the assumed single void pointer argument and thread_return_t leads to the thread_function_t typedef being correct.
Examples
Under Windows (32-bit and 64-bit), using the Microsoft C compiler, the function CreateThread is used to create threads and this function has following prototype;
HANDLE WINAPI CreateThread( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in SIZE_T dwStackSize, __in LPTHREAD_START_ROUTINE lpStartAddress, __in_opt LPVOID lpParameter, __in DWORD dwCreationFlags, __out_opt LPDWORD lpThreadId );
Furthermore, there is also the function SetThreadAffinityMask which is used to assign CPU affinity to threads, which has the following prototype;
DWORD_PTR WINAPI SetThreadAffinityMask( __in HANDLE hThread, __in DWORD_PTR dwThreadAffinityMask );
As such, the implementation of lfds611_abstraction_thread_state() on user-mode Windows, for all CPUs, using the Microsoft C compiler, looks like this;
#if (defined _WIN32 && defined _MSC_VER && !defined WIN_KERNEL_BUILD) /* TRD : any Windows (user-mode) on any CPU with the Microsoft C compiler _WIN32 indicates 64-bit or 32-bit Windows _MSC_VER indicates Microsoft C compiler !WIN_KERNEL_BUILD indicates Windows user-mode */ int abstraction_thread_start( thread_state_t *thread_state, unsigned int cpu, thread_function_t thread_function, void *thread_user_state ) { int rv = 0; DWORD thread_id; DWORD_PTR affinity_mask, result; assert( thread_state != NULL ); // TRD : cpu can be any value in its range assert( thread_function != NULL ); // TRD : thread_user_state can be NULL affinity_mask = (DWORD_PTR) (1 << cpu); *thread_state = CreateThread( NULL, 0, thread_function, thread_user_state, NO_FLAGS, &thread_id ); result = SetThreadAffinityMask( *thread_state, affinity_mask ); if( *thread_state != NULL and result != 0 ) rv = 1; return( rv ); } #endif