diff options
author | Darian <32921628+Dazza0@users.noreply.github.com> | 2022-06-01 02:11:02 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-01 02:11:02 +0300 |
commit | 34b8e24d7ccdbe25af8ad96dfd3154aeb302a8d6 (patch) | |
tree | 29183cfe6adccf47346302fb7950b914aee29c63 | |
parent | a97741a08d36ac08d913b8bc86abf128df627e85 (diff) |
Add support for newlib dynamic reentrancy (#496)
Previously, newlib's _impure_ptr was updated on every context switch
to point to the current task's _reent structure.
However, this behavior is no longer valid on multi-core systems due
to the fact that multiple cores can switch contexts at the same time,
thus leading to the corruption of the _impure_ptr.
However, Newlib can be compiled with __DYNAMIC_REENT__ enabled which
will cause newlib functions to call __getreent() instead in order to
obtain the required reent struct.
This commit adds dynamic reentrancy support to FreeRTOS:
- Added a configNEWLIB_REENTRANT_IS_DYNAMIC to enable dynamic reentrancy support
- _impure_ptr is no longer updated with reentrancy is dynamic
- Port must provide their own __getreent() that returns the current task's reent struct
-rw-r--r-- | include/FreeRTOS.h | 8 | ||||
-rw-r--r-- | tasks.c | 18 |
2 files changed, 20 insertions, 6 deletions
diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 6aa3b803c..60abd75b6 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -72,6 +72,14 @@ #include <reent.h> #endif +#ifdef configNEWLIB_REENTRANT_IS_DYNAMIC + #if ( configUSE_NEWLIB_REENTRANT != 1 ) + #error configUSE_NEWLIB_REENTRANT must be defined to 1 to enable configNEWLIB_REENTRANT_IS_DYNAMIC + #endif +#else /* configNEWLIB_REENTRANT_IS_DYNAMIC */ + #define configNEWLIB_REENTRANT_IS_DYNAMIC 0 +#endif /* configNEWLIB_REENTRANT_IS_DYNAMIC */ + /* * Check all the required application specific macros have been defined. * These macros are application specific and (as downloaded) are defined @@ -2854,15 +2854,18 @@ void vTaskStartScheduler( void ) * starts to run. */ portDISABLE_INTERRUPTS(); - #if ( configUSE_NEWLIB_REENTRANT == 1 ) + #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) ) { /* 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. */ + * for additional information. + * + * Note: Updating the _impure_ptr is not required when Newlib is compiled with + * __DYNAMIC_REENT__ enabled. The port should provide __getreent() instead. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } - #endif /* configUSE_NEWLIB_REENTRANT */ + #endif /* ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) */ xNextTaskUnblockTime = portMAX_DELAY; xSchedulerRunning = pdTRUE; @@ -3945,15 +3948,18 @@ void vTaskSwitchContext( BaseType_t xCoreID ) } #endif - #if ( configUSE_NEWLIB_REENTRANT == 1 ) + #if ( ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) ) { /* 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. */ + * for additional information. + * + * Note: Updating the _impure_ptr is not required when Newlib is compiled with + * __DYNAMIC_REENT__ enabled. The the port should provide __getreent() instead. */ _impure_ptr = &( pxCurrentTCB->xNewLib_reent ); } - #endif /* configUSE_NEWLIB_REENTRANT */ + #endif /* ( configUSE_NEWLIB_REENTRANT == 1 ) && ( configNEWLIB_REENTRANT_IS_DYNAMIC == 0 ) */ } } portRELEASE_ISR_LOCK(); |