Generalize Thread Local Storage (TLS) support (#540)

* Generalize Thread Local Storage (TLS) support

FreeRTOS's Thread Local Storage (TLS) support used variables and
functions from newlib, thereby making the TLS support specific to
newlib. This commit generalizes the TLS support so that it can be used
with other c-runtime libraries also. The default behavior for newlib
support is still kept same for backward compatibility.

The application writer would need to set configUSE_C_RUNTIME_TLS_SUPPORT
to 1 in their FreeRTOSConfig.h and define the following macros to
support TLS for a c-runtime library:

1. configTLS_BLOCK_TYPE - Type used to define the TLS block in TCB.
2. configINIT_TLS_BLOCK( xTLSBlock ) - Allocate and initialize memory
   block for the task's TLS Block.
3. configSET_TLS_BLOCK( xTLSBlock ) - Switch C-Runtime's TLS Block to
   point to xTLSBlock.
4. configDEINIT_TLS_BLOCK( xTLSBlock ) - Free up the memory allocated
   for the task's TLS Block.

The following is an example to support TLS for picolibc:

 #define configUSE_C_RUNTIME_TLS_SUPPORT        1
 #define configTLS_BLOCK_TYPE                   void*
 #define configINIT_TLS_BLOCK( xTLSBlock )      _init_tls( xTLSBlock )
 #define configSET_TLS_BLOCK( xTLSBlock )       _set_tls( xTLSBlock )
 #define configDEINIT_TLS_BLOCK( xTLSBlock )

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
This commit is contained in:
Gaurav-Aggarwal-AWS 2022-08-08 21:23:29 +05:30 committed by GitHub
parent 3b18a07568
commit 95669cc1a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 41 deletions

1
.github/lexicon.txt vendored
View File

@ -3090,6 +3090,7 @@ xtimerstartfromisr
xtimerstop xtimerstop
xtimerstopfromisr xtimerstopfromisr
xtimertaskhandle xtimertaskhandle
xtlsblock
xtos xtos
xtriggerlevel xtriggerlevel
xtriggerlevelbytes xtriggerlevelbytes

View File

@ -71,9 +71,60 @@
/* Required if struct _reent is used. */ /* Required if struct _reent is used. */
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( configUSE_NEWLIB_REENTRANT == 1 )
/* Note Newlib support has been included by popular demand, but is not
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
* responsible for resulting newlib operation. User must be familiar with
* newlib and must provide system-wide implementations of the necessary
* stubs. Be warned that (at the time of writing) the current newlib design
* implements a system-wide malloc() that must be provided with locks.
*
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
* for additional information. */
#include <reent.h> #include <reent.h>
#define configUSE_C_RUNTIME_TLS_SUPPORT 1
#ifndef configTLS_BLOCK_TYPE
#define configTLS_BLOCK_TYPE struct _reent
#endif #endif
#ifndef configINIT_TLS_BLOCK
#define configINIT_TLS_BLOCK( xTLSBlock ) _REENT_INIT_PTR( &( xTLSBlock ) )
#endif
#ifndef configSET_TLS_BLOCK
#define configSET_TLS_BLOCK( xTLSBlock ) _impure_ptr = &( xTLSBlock )
#endif
#ifndef configDEINIT_TLS_BLOCK
#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
#endif
#endif /* if ( configUSE_NEWLIB_REENTRANT == 1 ) */
#ifndef configUSE_C_RUNTIME_TLS_SUPPORT
#define configUSE_C_RUNTIME_TLS_SUPPORT 0
#endif
#if ( ( configUSE_NEWLIB_REENTRANT == 0 ) && ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
#ifndef configTLS_BLOCK_TYPE
#error Missing definition: configTLS_BLOCK_TYPE must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
#endif
#ifndef configINIT_TLS_BLOCK
#error Missing definition: configINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
#endif
#ifndef configSET_TLS_BLOCK
#error Missing definition: configSET_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
#endif
#ifndef configDEINIT_TLS_BLOCK
#error Missing definition: configDEINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
#endif
#endif /* if ( ( configUSE_NEWLIB_REENTRANT == 0 ) && ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) ) */
/* /*
* Check all the required application specific macros have been defined. * Check all the required application specific macros have been defined.
* These macros are application specific and (as downloaded) are defined * These macros are application specific and (as downloaded) are defined
@ -1223,8 +1274,8 @@ typedef struct xSTATIC_TCB
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulDummy16; configRUN_TIME_COUNTER_TYPE ulDummy16;
#endif #endif
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
struct _reent xDummy17; configTLS_BLOCK_TYPE xDummy17;
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];

58
tasks.c
View File

@ -296,19 +296,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */ configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
#endif #endif
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
configTLS_BLOCK_TYPE xTLSBlock; /*< Memory block used as Thread Local Storage (TLS) Block for the task. */
/* Allocate a Newlib reent structure that is specific to this task.
* Note Newlib support has been included by popular demand, but is not
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
* responsible for resulting newlib operation. User must be familiar with
* newlib and must provide system-wide implementations of the necessary
* stubs. Be warned that (at the time of writing) the current newlib design
* implements a system-wide malloc() that must be provided with locks.
*
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
* for additional information. */
struct _reent xNewLib_reent;
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
@ -964,12 +953,10 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
} }
#endif #endif
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
{ {
/* Initialise this task's Newlib reent structure. /* Allocate and initialize memory for the task's TLS Block. */
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock );
* for additional information. */
_REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
} }
#endif #endif
@ -2038,15 +2025,13 @@ void vTaskStartScheduler( void )
* starts to run. */ * starts to run. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
{ {
/* Switch Newlib's _impure_ptr variable to point to the _reent /* Switch C-Runtime's TLS Block to point to the TLS
* structure specific to the task that will run first. * block specific to the task that will run first. */
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
* for additional information. */
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
} }
#endif /* configUSE_NEWLIB_REENTRANT */ #endif
xNextTaskUnblockTime = portMAX_DELAY; xNextTaskUnblockTime = portMAX_DELAY;
xSchedulerRunning = pdTRUE; xSchedulerRunning = pdTRUE;
@ -3078,15 +3063,13 @@ void vTaskSwitchContext( void )
} }
#endif #endif
#if ( configUSE_NEWLIB_REENTRANT == 1 ) #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
{ {
/* Switch Newlib's _impure_ptr variable to point to the _reent /* Switch C-Runtime's TLS Block to point to the TLS
* structure specific to this task. * Block specific to this task. */
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
* for additional information. */
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
} }
#endif /* configUSE_NEWLIB_REENTRANT */ #endif
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -3958,15 +3941,12 @@ static void prvCheckTasksWaitingTermination( void )
* want to allocate and clean RAM statically. */ * want to allocate and clean RAM statically. */
portCLEAN_UP_TCB( pxTCB ); portCLEAN_UP_TCB( pxTCB );
/* Free up the memory allocated by the scheduler for the task. It is up #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
* to the task to free any memory allocated at the application level.
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
* for additional information. */
#if ( configUSE_NEWLIB_REENTRANT == 1 )
{ {
_reclaim_reent( &( pxTCB->xNewLib_reent ) ); /* Free up the memory allocated for the task's TLS Block. */
configDEINIT_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
} }
#endif /* configUSE_NEWLIB_REENTRANT */ #endif
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) ) #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
{ {