Porting Guide (test)
Introduction
To minimize the work involved is making test work on any given platform a porting abstraction layer has been written. Porting simply involves implementing the porting abstraction layer; the programme will then compile and work. The porting abstraction layer is implemented as a single header file and three C files in the liblfds700/test//src/ directory, thus;
└───liblfds700 └───test └───src porting_abstraction_layer_operating_system.h : defines, typedefs and includes porting_abstraction_layer_get_linked_list_of_logical_cores.c : populates a liblfds list with one entry per logical core ID porting_abstraction_layer_thread_start.c : implements a function to start a thread porting_abstraction_layer_thread_wait.c : implements a function to wait for a thread to have terminated
Each file uses #ifdefs and compiler defined macros to select the appropriate porting abstraction layer implementation for the local platform.
So, for example, in porting_abstraction_layer_operating_system.h, for MSVC on Windows XP or better with a hosted implementation, we see the following;
#if( defined _MSC_VER && _MSC_VER >= 1310 && NTDDI_VERSION >= NTDDI_WINXP && defined _WIN32 ) [snip porting abstraction layer implementation] #endif
So, to add a new platform, introduce a new #ifdef, which matches the appropriate compiler defined macros for your platform.
The Files
porting_abstraction_layer_operating_system.h
This header file contains includes, typedefs, defines and macros. Includes are and are only those necessary for the porting abstraction layer (i.e. the contents of this file and the three C files).
typedef [type] test_pal_thread_state_t; typedef [type] test_pal_thread_return_t; #define TEST_PAL_CALLING_CONVENTION
porting_abstraction_layer_get_linked_list_of_logical_cores.c
This is the most complex function in the abstraction layer. It is passed a pointer to an allocated struct lfds700_list_asu_state, which is a liblfds provided add-only, singly-linked, unordered list. The function then needs to populate this list with one struct test_pal_logical_processor per logical core, where that struct indicates the logical core ID of that logical core, the purpose of this being to permit the test code to issue one thread per logical core and pin each thread to its core. The function which starts threads (below) as part of its functionality pins threads to cores.
void test_pal_get_logical_core_ids( struct lfds700_list_asu_state *lasus )
porting_abstraction_layer_thread_start.c
This function starts a thread and pins it to the logical core specified by the lp argument.
int test_pal_thread_start( thread_state_t *thread_state, struct test_pal_logical_processor *lp, thread_return_t (CALLING_CONVENTION *thread_function)(void *thread_user_state), void *thread_user_state );
porting_abstraction_layer_thread_wait.c
This function sleeps until the thread specified by thread_state has terminated.
void test_pal_thread_wait( thread_state_t thread_state );