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
This commit is contained in:
Darian 2022-06-01 07:11:02 +08:00 committed by GitHub
parent a97741a08d
commit 34b8e24d7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 6 deletions

View file

@ -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

18
tasks.c
View file

@ -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();