Skip to content

Generalize Thread Local Storage (TLS) support #540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/lexicon.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3090,6 +3090,7 @@ xtimerstartfromisr
xtimerstop
xtimerstopfromisr
xtimertaskhandle
xtlsblock
xtos
xtriggerlevel
xtriggerlevelbytes
Expand Down
55 changes: 53 additions & 2 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,60 @@

/* Required if struct _reent is used. */
#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>

#define configUSE_C_RUNTIME_TLS_SUPPORT 1

#ifndef configTLS_BLOCK_TYPE
#define configTLS_BLOCK_TYPE struct _reent
#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.
* These macros are application specific and (as downloaded) are defined
Expand Down Expand Up @@ -1223,8 +1274,8 @@ typedef struct xSTATIC_TCB
#if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulDummy16;
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 )
struct _reent xDummy17;
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 ) )
configTLS_BLOCK_TYPE xDummy17;
#endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
Expand Down
58 changes: 19 additions & 39 deletions tasks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
#endif

#if ( configUSE_NEWLIB_REENTRANT == 1 )

/* 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;
#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. */
#endif

#if ( configUSE_TASK_NOTIFICATIONS == 1 )
Expand Down Expand Up @@ -964,12 +953,10 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
}
#endif

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

Expand Down Expand Up @@ -2038,15 +2025,13 @@ void vTaskStartScheduler( void )
* starts to run. */
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
* structure specific to the task that will run first.
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
* for additional information. */
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
/* Switch C-Runtime's TLS Block to point to the TLS
* block specific to the task that will run first. */
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
}
#endif /* configUSE_NEWLIB_REENTRANT */
#endif

xNextTaskUnblockTime = portMAX_DELAY;
xSchedulerRunning = pdTRUE;
Expand Down Expand Up @@ -3078,15 +3063,13 @@ void vTaskSwitchContext( void )
}
#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
* structure specific to this task.
* See the third party link http://www.nadler.com/embedded/newlibAndFreeRTOS.html
* for additional information. */
_impure_ptr = &( pxCurrentTCB->xNewLib_reent );
/* Switch C-Runtime's TLS Block to point to the TLS
* Block specific to this task. */
configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
}
#endif /* configUSE_NEWLIB_REENTRANT */
#endif
}
}
/*-----------------------------------------------------------*/
Expand Down Expand Up @@ -3958,15 +3941,12 @@ static void prvCheckTasksWaitingTermination( void )
* want to allocate and clean RAM statically. */
portCLEAN_UP_TCB( pxTCB );

/* Free up the memory allocated by the scheduler for the task. It is up
* 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 )
#if ( ( configUSE_NEWLIB_REENTRANT == 1 ) || ( configUSE_C_RUNTIME_TLS_SUPPORT == 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 ) )
{
Expand Down