Skip to content

Commit 389e7bc

Browse files
aineoae86-sysrawalexe
authored andcommitted
Fix SH2A_FPU FPU context cleanup
Keep the per-task FPU context allocation reachable, avoid replacing an existing task tag buffer, and free the allocation from portCLEAN_UP_TCB using the saved buffer end pointer. Signed-off-by: Old-Ding <ai.neo.ae86@gmail.com>
1 parent d72263b commit 389e7bc

2 files changed

Lines changed: 46 additions & 22 deletions

File tree

portable/Renesas/SH2A_FPU/port.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@
4343
* value is for all interrupts to be enabled. */
4444
#define portINITIAL_SR ( 0UL )
4545

46-
/* Dimensions the array into which the floating point context is saved.
47-
* Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4
48-
* bytes big. If this number is changed then the 72 in portasm.src also needs
49-
* changing. */
50-
#define portFLOP_REGISTERS_TO_STORE ( 18 )
51-
#define portFLOP_STORAGE_SIZE ( portFLOP_REGISTERS_TO_STORE * 4 )
52-
5346
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
5447
#error configSUPPORT_DYNAMIC_ALLOCATION must be 1 to use this port.
5548
#endif
@@ -245,26 +238,35 @@ BaseType_t xPortUsesFloatingPoint( TaskHandle_t xTask )
245238
xTask = ( TaskHandle_t ) pxCurrentTCB;
246239
}
247240

248-
/* Allocate a buffer large enough to hold all the flop registers. */
249-
pulFlopBuffer = ( uint32_t * ) pvPortMalloc( portFLOP_STORAGE_SIZE );
250-
251-
if( pulFlopBuffer != NULL )
241+
/* The task tag already owns the FPU buffer for this port. Do not replace
242+
* it, or the original allocation would become unreachable. */
243+
if( xTaskGetApplicationTaskTag( xTask ) != NULL )
252244
{
253-
/* Start with the registers in a benign state. */
254-
memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE );
255-
256-
/* The first thing to get saved in the buffer is the FPSCR value -
257-
* initialise this to the current FPSCR value. */
258-
*pulFlopBuffer = get_fpscr();
259-
260-
/* Use the task tag to point to the flop buffer. Pass pointer to just
261-
* above the buffer because the flop save routine uses a pre-decrement. */
262-
vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) );
263245
xReturn = pdPASS;
264246
}
265247
else
266248
{
267-
xReturn = pdFAIL;
249+
/* Allocate a buffer large enough to hold all the flop registers. */
250+
pulFlopBuffer = ( uint32_t * ) pvPortMalloc( portFLOP_STORAGE_SIZE );
251+
252+
if( pulFlopBuffer != NULL )
253+
{
254+
/* Start with the registers in a benign state. */
255+
memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE );
256+
257+
/* The first thing to get saved in the buffer is the FPSCR value -
258+
* initialise this to the current FPSCR value. */
259+
*pulFlopBuffer = get_fpscr();
260+
261+
/* Use the task tag to point to the flop buffer. Pass pointer to just
262+
* above the buffer because the flop save routine uses a pre-decrement. */
263+
vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) );
264+
xReturn = pdPASS;
265+
}
266+
else
267+
{
268+
xReturn = pdFAIL;
269+
}
268270
}
269271

270272
return xReturn;

portable/Renesas/SH2A_FPU/portmacro.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ typedef unsigned long UBaseType_t;
8484
#define portYIELD_TRAP_NO ( 33 )
8585
#define portKERNEL_INTERRUPT_PRIORITY ( 1 )
8686

87+
/* Dimensions the array into which the floating point context is saved.
88+
* Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4
89+
* bytes big. If this number is changed then the 72 in portasm.src also needs
90+
* changing. */
91+
#define portFLOP_REGISTERS_TO_STORE ( 18 )
92+
#define portFLOP_STORAGE_SIZE ( portFLOP_REGISTERS_TO_STORE * 4 )
93+
8794
void vPortYield( void );
8895
#define portYIELD() vPortYield()
8996

@@ -112,6 +119,21 @@ void vPortRestoreFlopRegisters( void * pulBuffer );
112119
#define traceTASK_SWITCHED_OUT() do { if( pxCurrentTCB->pxTaskTag != NULL ) vPortSaveFlopRegisters( pxCurrentTCB->pxTaskTag ); } while( 0 )
113120
#define traceTASK_SWITCHED_IN() do { if( pxCurrentTCB->pxTaskTag != NULL ) vPortRestoreFlopRegisters( pxCurrentTCB->pxTaskTag ); } while( 0 )
114121

122+
/* pxTaskTag points just above the FPU context buffer because the save routine
123+
* uses a pre-decrement. Recover the allocation base before freeing it. */
124+
#define portCLEAN_UP_TCB( pxTCB ) \
125+
do \
126+
{ \
127+
if( ( pxTCB )->pxTaskTag != NULL ) \
128+
{ \
129+
uint32_t * pulFlopBufferEnd = \
130+
( uint32_t * ) ( pxTCB )->pxTaskTag; \
131+
vPortFree( ( void * ) ( pulFlopBufferEnd - \
132+
portFLOP_REGISTERS_TO_STORE ) ); \
133+
( pxTCB )->pxTaskTag = NULL; \
134+
} \
135+
} while( 0 )
136+
115137
/*
116138
* These macros should be called directly, but through the taskENTER_CRITICAL()
117139
* and taskEXIT_CRITICAL() macros.

0 commit comments

Comments
 (0)