Skip to content

Commit 95669cc

Browse files
authored
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 <[email protected]>
1 parent 3b18a07 commit 95669cc

File tree

3 files changed

+73
-41
lines changed

3 files changed

+73
-41
lines changed

.github/lexicon.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,6 +3090,7 @@ xtimerstartfromisr
30903090
xtimerstop
30913091
xtimerstopfromisr
30923092
xtimertaskhandle
3093+
xtlsblock
30933094
xtos
30943095
xtriggerlevel
30953096
xtriggerlevelbytes

include/FreeRTOS.h

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,60 @@
7171

7272
/* Required if struct _reent is used. */
7373
#if ( configUSE_NEWLIB_REENTRANT == 1 )
74+
75+
/* Note Newlib support has been included by popular demand, but is not
76+
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
77+
* responsible for resulting newlib operation. User must be familiar with
78+
* newlib and must provide system-wide implementations of the necessary
79+
* stubs. Be warned that (at the time of writing) the current newlib design
80+
* implements a system-wide malloc() that must be provided with locks.
81+
*
82+
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
83+
* for additional information. */
7484
#include <reent.h>
85+
86+
#define configUSE_C_RUNTIME_TLS_SUPPORT 1
87+
88+
#ifndef configTLS_BLOCK_TYPE
89+
#define configTLS_BLOCK_TYPE struct _reent
90+
#endif
91+
92+
#ifndef configINIT_TLS_BLOCK
93+
#define configINIT_TLS_BLOCK( xTLSBlock ) _REENT_INIT_PTR( &( xTLSBlock ) )
94+
#endif
95+
96+
#ifndef configSET_TLS_BLOCK
97+
#define configSET_TLS_BLOCK( xTLSBlock ) _impure_ptr = &( xTLSBlock )
98+
#endif
99+
100+
#ifndef configDEINIT_TLS_BLOCK
101+
#define configDEINIT_TLS_BLOCK( xTLSBlock ) _reclaim_reent( &( xTLSBlock ) )
102+
#endif
103+
#endif /* if ( configUSE_NEWLIB_REENTRANT == 1 ) */
104+
105+
#ifndef configUSE_C_RUNTIME_TLS_SUPPORT
106+
#define configUSE_C_RUNTIME_TLS_SUPPORT 0
75107
#endif
76108

109+
#if ( ( configUSE_NEWLIB_REENTRANT == 0 ) && ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
110+
111+
#ifndef configTLS_BLOCK_TYPE
112+
#error Missing definition: configTLS_BLOCK_TYPE must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
113+
#endif
114+
115+
#ifndef configINIT_TLS_BLOCK
116+
#error Missing definition: configINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
117+
#endif
118+
119+
#ifndef configSET_TLS_BLOCK
120+
#error Missing definition: configSET_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
121+
#endif
122+
123+
#ifndef configDEINIT_TLS_BLOCK
124+
#error Missing definition: configDEINIT_TLS_BLOCK must be defined in FreeRTOSConfig.h when configUSE_C_RUNTIME_TLS_SUPPORT is set to 1.
125+
#endif
126+
#endif /* if ( ( configUSE_NEWLIB_REENTRANT == 0 ) && ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) ) */
127+
77128
/*
78129
* Check all the required application specific macros have been defined.
79130
* These macros are application specific and (as downloaded) are defined
@@ -1223,8 +1274,8 @@ typedef struct xSTATIC_TCB
12231274
#if ( configGENERATE_RUN_TIME_STATS == 1 )
12241275
configRUN_TIME_COUNTER_TYPE ulDummy16;
12251276
#endif
1226-
#if ( configUSE_NEWLIB_REENTRANT == 1 )
1227-
struct _reent xDummy17;
1277+
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
1278+
configTLS_BLOCK_TYPE xDummy17;
12281279
#endif
12291280
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
12301281
uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];

tasks.c

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -296,19 +296,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to
296296
configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
297297
#endif
298298

299-
#if ( configUSE_NEWLIB_REENTRANT == 1 )
300-
301-
/* Allocate a Newlib reent structure that is specific to this task.
302-
* Note Newlib support has been included by popular demand, but is not
303-
* used by the FreeRTOS maintainers themselves. FreeRTOS is not
304-
* responsible for resulting newlib operation. User must be familiar with
305-
* newlib and must provide system-wide implementations of the necessary
306-
* stubs. Be warned that (at the time of writing) the current newlib design
307-
* implements a system-wide malloc() that must be provided with locks.
308-
*
309-
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
310-
* for additional information. */
311-
struct _reent xNewLib_reent;
299+
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
300+
configTLS_BLOCK_TYPE xTLSBlock; /*< Memory block used as Thread Local Storage (TLS) Block for the task. */
312301
#endif
313302

314303
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
@@ -964,12 +953,10 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
964953
}
965954
#endif
966955

967-
#if ( configUSE_NEWLIB_REENTRANT == 1 )
956+
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
968957
{
969-
/* Initialise this task's Newlib reent structure.
970-
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
971-
* for additional information. */
972-
_REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
958+
/* Allocate and initialize memory for the task's TLS Block. */
959+
configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock );
973960
}
974961
#endif
975962

@@ -2038,15 +2025,13 @@ void vTaskStartScheduler( void )
20382025
* starts to run. */
20392026
portDISABLE_INTERRUPTS();
20402027

2041-
#if ( configUSE_NEWLIB_REENTRANT == 1 )
2028+
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
20422029
{
2043-
/* Switch Newlib's _impure_ptr variable to point to the _reent
2044-
* structure specific to the task that will run first.
2045-
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
2046-
* for additional information. */
2047-
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
2030+
/* Switch C-Runtime's TLS Block to point to the TLS
2031+
* block specific to the task that will run first. */
2032+
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
20482033
}
2049-
#endif /* configUSE_NEWLIB_REENTRANT */
2034+
#endif
20502035

20512036
xNextTaskUnblockTime = portMAX_DELAY;
20522037
xSchedulerRunning = pdTRUE;
@@ -3078,15 +3063,13 @@ void vTaskSwitchContext( void )
30783063
}
30793064
#endif
30803065

3081-
#if ( configUSE_NEWLIB_REENTRANT == 1 )
3066+
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
30823067
{
3083-
/* Switch Newlib's _impure_ptr variable to point to the _reent
3084-
* structure specific to this task.
3085-
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
3086-
* for additional information. */
3087-
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
3068+
/* Switch C-Runtime's TLS Block to point to the TLS
3069+
* Block specific to this task. */
3070+
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
30883071
}
3089-
#endif /* configUSE_NEWLIB_REENTRANT */
3072+
#endif
30903073
}
30913074
}
30923075
/*-----------------------------------------------------------*/
@@ -3958,15 +3941,12 @@ static void prvCheckTasksWaitingTermination( void )
39583941
* want to allocate and clean RAM statically. */
39593942
portCLEAN_UP_TCB( pxTCB );
39603943

3961-
/* Free up the memory allocated by the scheduler for the task. It is up
3962-
* to the task to free any memory allocated at the application level.
3963-
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
3964-
* for additional information. */
3965-
#if ( configUSE_NEWLIB_REENTRANT == 1 )
3944+
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
39663945
{
3967-
_reclaim_reent( &( pxTCB->xNewLib_reent ) );
3946+
/* Free up the memory allocated for the task's TLS Block. */
3947+
configDEINIT_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
39683948
}
3969-
#endif /* configUSE_NEWLIB_REENTRANT */
3949+
#endif
39703950

39713951
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
39723952
{

0 commit comments

Comments
 (0)