diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index 5cb70a514..a9347d338 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -27,28 +27,29 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - * - * Each task has a pthread which eases use of standard debuggers - * (allowing backtraces of tasks etc). Threads for tasks that are not - * running are blocked in sigwait(). - * - * Task switch is done by resuming the thread for the next task by - * signaling the condition variable and then waiting on a condition variable - * with the current thread. - * - * The timer interrupt uses SIGALRM and care is taken to ensure that - * the signal handler runs only on the thread for the current task. - * - * Use of part of the standard C library requires care as some - * functions can take pthread mutexes internally which can result in - * deadlocks as the FreeRTOS kernel can switch tasks while they're - * holding a pthread mutex. - * - * stdio (printf() and friends) should be called from a single task - * only or serialized with a FreeRTOS primitive such as a binary - * semaphore or mutex. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the Posix port. +* +* Each task has a pthread which eases use of standard debuggers +* (allowing backtraces of tasks etc). Threads for tasks that are not +* running are blocked in sigwait(). +* +* Task switch is done by resuming the thread for the next task by +* signaling the condition variable and then waiting on a condition variable +* with the current thread. +* +* The timer interrupt uses SIGALRM and care is taken to ensure that +* the signal handler runs only on the thread for the current task. +* +* Use of part of the standard C library requires care as some +* functions can take pthread mutexes internally which can result in +* deadlocks as the FreeRTOS kernel can switch tasks while they're +* holding a pthread mutex. +* +* stdio (printf() and friends) should be called from a single task +* only or serialized with a FreeRTOS primitive such as a binary +* semaphore or mutex. +*----------------------------------------------------------*/ +#include "portmacro.h" #include #include @@ -67,26 +68,26 @@ #include "utils/wait_for_event.h" /*-----------------------------------------------------------*/ -#define SIG_RESUME SIGUSR1 +#define SIG_RESUME SIGUSR1 typedef struct THREAD { pthread_t pthread; pdTASK_CODE pxCode; - void *pvParams; + void * pvParams; BaseType_t xDying; - struct event *ev; + struct event * ev; } Thread_t; /* * The additional per-thread data is stored at the beginning of the * task's stack. */ -static inline Thread_t *prvGetThreadFromTask(TaskHandle_t xTask) +static inline Thread_t * prvGetThreadFromTask( TaskHandle_t xTask ) { -StackType_t *pxTopOfStack = *(StackType_t **)xTask; + StackType_t * pxTopOfStack = *( StackType_t ** ) xTask; - return (Thread_t *)(pxTopOfStack + 1); + return ( Thread_t * ) ( pxTopOfStack + 1 ); } /*-----------------------------------------------------------*/ @@ -95,7 +96,7 @@ static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; static sigset_t xResumeSignals; static sigset_t xAllSignals; static sigset_t xSchedulerOriginalSignalMask; -static pthread_t hMainThread = ( pthread_t )NULL; +static pthread_t hMainThread = ( pthread_t ) NULL; static volatile portBASE_TYPE uxCriticalNesting; /*-----------------------------------------------------------*/ @@ -104,17 +105,18 @@ static portBASE_TYPE xSchedulerEnd = pdFALSE; static void prvSetupSignalsAndSchedulerPolicy( void ); static void prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); +static void * prvWaitForStart( void * pvParams ); static void prvSwitchThread( Thread_t * xThreadToResume, - Thread_t *xThreadToSuspend ); -static void prvSuspendSelf( Thread_t * thread); + Thread_t * xThreadToSuspend ); +static void prvSuspendSelf( Thread_t * thread ); static void prvResumeThread( Thread_t * xThreadId ); static void vPortSystemTickHandler( int sig ); static void vPortStartFirstTask( void ); static void prvPortYieldFromISR( void ); /*-----------------------------------------------------------*/ -static void prvFatalError( const char *pcCall, int iErrno ) +static void prvFatalError( const char * pcCall, + int iErrno ) { fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) ); abort(); @@ -123,23 +125,24 @@ static void prvFatalError( const char *pcCall, int iErrno ) /* * See header file for description. */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, - portSTACK_TYPE *pxEndOfStack, - pdTASK_CODE pxCode, void *pvParameters ) +portSTACK_TYPE * pxPortInitialiseStack( portSTACK_TYPE * pxTopOfStack, + portSTACK_TYPE * pxEndOfStack, + pdTASK_CODE pxCode, + void * pvParameters ) { -Thread_t *thread; -pthread_attr_t xThreadAttributes; -size_t ulStackSize; -int iRet; + Thread_t * thread; + pthread_attr_t xThreadAttributes; + size_t ulStackSize; + int iRet; - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); + ( void ) pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); /* * Store the additional thread data at the start of the stack. */ - thread = (Thread_t *)(pxTopOfStack + 1) - 1; - pxTopOfStack = (portSTACK_TYPE *)thread - 1; - ulStackSize = (pxTopOfStack + 1 - pxEndOfStack) * sizeof(*pxTopOfStack); + thread = ( Thread_t * ) ( pxTopOfStack + 1 ) - 1; + pxTopOfStack = ( portSTACK_TYPE * ) thread - 1; + ulStackSize = ( pxTopOfStack + 1 - pxEndOfStack ) * sizeof( *pxTopOfStack ); thread->pxCode = pxCode; thread->pvParams = pvParameters; @@ -154,7 +157,8 @@ int iRet; iRet = pthread_create( &thread->pthread, &xThreadAttributes, prvWaitForStart, thread ); - if ( iRet ) + + if( iRet != 0 ) { prvFatalError( "pthread_create", iRet ); } @@ -167,7 +171,7 @@ int iRet; void vPortStartFirstTask( void ) { -Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + Thread_t * pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); /* Start the first task. */ prvResumeThread( pxFirstThread ); @@ -179,13 +183,13 @@ Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); */ portBASE_TYPE xPortStartScheduler( void ) { -int iSignal; -sigset_t xSignals; + int iSignal; + sigset_t xSignals; hMainThread = pthread_self(); /* Start the timer that generates the tick ISR(SIGALRM). - Interrupts are disabled here already. */ + * Interrupts are disabled here already. */ prvSetupTimerInterrupt(); /* Start the first task. */ @@ -195,23 +199,23 @@ sigset_t xSignals; sigemptyset( &xSignals ); sigaddset( &xSignals, SIG_RESUME ); - while ( !xSchedulerEnd ) + while( xSchedulerEnd != pdTRUE ) { sigwait( &xSignals, &iSignal ); } /* Cancel the Idle task and free its resources */ -#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - vPortCancelThread( xTaskGetIdleTaskHandle() ); -#endif + #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) + vPortCancelThread( xTaskGetIdleTaskHandle() ); + #endif -#if ( configUSE_TIMERS == 1 ) - /* Cancel the Timer task and free its resources */ - vPortCancelThread( xTimerGetTimerDaemonTaskHandle() ); -#endif /* configUSE_TIMERS */ + #if ( configUSE_TIMERS == 1 ) + /* Cancel the Timer task and free its resources */ + vPortCancelThread( xTimerGetTimerDaemonTaskHandle() ); + #endif /* configUSE_TIMERS */ /* Restore original signal mask. */ - (void)pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); + ( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); return 0; } @@ -219,9 +223,9 @@ sigset_t xSignals; void vPortEndScheduler( void ) { -struct itimerval itimer; -struct sigaction sigtick; -Thread_t *xCurrentThread; + struct itimerval itimer; + struct sigaction sigtick; + Thread_t * xCurrentThread; /* Stop the timer and ignore any pending SIGALRMs that would end * up running on the main thread when it is resumed. */ @@ -230,7 +234,7 @@ Thread_t *xCurrentThread; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = 0; - (void)setitimer( ITIMER_REAL, &itimer, NULL ); + ( void ) setitimer( ITIMER_REAL, &itimer, NULL ); sigtick.sa_flags = 0; sigtick.sa_handler = SIG_IGN; @@ -239,19 +243,20 @@ Thread_t *xCurrentThread; /* Signal the scheduler to exit its loop. */ xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); + ( void ) pthread_kill( hMainThread, SIG_RESUME ); xCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); - prvSuspendSelf(xCurrentThread); + prvSuspendSelf( xCurrentThread ); } /*-----------------------------------------------------------*/ void vPortEnterCritical( void ) { - if ( uxCriticalNesting == 0 ) + if( uxCriticalNesting == 0 ) { vPortDisableInterrupts(); } + uxCriticalNesting++; } /*-----------------------------------------------------------*/ @@ -270,8 +275,8 @@ void vPortExitCritical( void ) static void prvPortYieldFromISR( void ) { -Thread_t *xThreadToSuspend; -Thread_t *xThreadToResume; + Thread_t * xThreadToSuspend; + Thread_t * xThreadToResume; xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); @@ -308,7 +313,7 @@ void vPortEnableInterrupts( void ) portBASE_TYPE xPortSetInterruptMask( void ) { /* Interrupts are always disabled inside ISRs (signals - handlers). */ + * handlers). */ return pdTRUE; } /*-----------------------------------------------------------*/ @@ -318,16 +323,17 @@ void vPortClearInterruptMask( portBASE_TYPE xMask ) } /*-----------------------------------------------------------*/ -static uint64_t prvGetTimeNs(void) +static uint64_t prvGetTimeNs( void ) { -struct timespec t; + struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); + clock_gettime( CLOCK_MONOTONIC, &t ); - return t.tv_sec * 1000000000ull + t.tv_nsec; + return t.tv_sec * 1000000000ULL + t.tv_nsec; } static uint64_t prvStartTimeNs; + /* commented as part of the code below in vPortSystemTickHandler, * to adjust timing according to full demo requirements */ /* static uint64_t prvTickCount; */ @@ -338,12 +344,13 @@ static uint64_t prvStartTimeNs; */ void prvSetupTimerInterrupt( void ) { -struct itimerval itimer; -int iRet; + struct itimerval itimer; + int iRet; /* Initialise the structure with the current timer information. */ iRet = getitimer( ITIMER_REAL, &itimer ); - if ( iRet ) + + if( iRet == -1 ) { prvFatalError( "getitimer", errno ); } @@ -358,7 +365,8 @@ int iRet; /* Set-up the timer interrupt. */ iRet = setitimer( ITIMER_REAL, &itimer, NULL ); - if ( iRet ) + + if( iRet == -1 ) { prvFatalError( "setitimer", errno ); } @@ -369,51 +377,55 @@ int iRet; static void vPortSystemTickHandler( int sig ) { -Thread_t *pxThreadToSuspend; -Thread_t *pxThreadToResume; + Thread_t * pxThreadToSuspend; + Thread_t * pxThreadToResume; + /* uint64_t xExpectedTicks; */ uxCriticalNesting++; /* Signals are blocked in this signal handler. */ -#if ( configUSE_PREEMPTION == 1 ) - pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); -#endif + #if ( configUSE_PREEMPTION == 1 ) + pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + #endif /* Tick Increment, accounting for any lost signals or drift in * the timer. */ + /* * Comment code to adjust timing according to full demo requirements * xExpectedTicks = (prvGetTimeNs() - prvStartTimeNs) * / (portTICK_RATE_MICROSECONDS * 1000); * do { */ - xTaskIncrementTick(); + xTaskIncrementTick(); + /* prvTickCount++; * } while (prvTickCount < xExpectedTicks); -*/ + */ -#if ( configUSE_PREEMPTION == 1 ) - /* Select Next Task. */ - vTaskSwitchContext(); + #if ( configUSE_PREEMPTION == 1 ) + /* Select Next Task. */ + vTaskSwitchContext(); - pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); - prvSwitchThread(pxThreadToResume, pxThreadToSuspend); -#endif + prvSwitchThread( pxThreadToResume, pxThreadToSuspend ); + #endif uxCriticalNesting--; } /*-----------------------------------------------------------*/ -void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield ) +void vPortThreadDying( void * pxTaskToDelete, + volatile BaseType_t * pxPendYield ) { -Thread_t *pxThread = prvGetThreadFromTask( pxTaskToDelete ); + Thread_t * pxThread = prvGetThreadFromTask( pxTaskToDelete ); pxThread->xDying = pdTRUE; } -void vPortCancelThread( void *pxTaskToDelete ) +void vPortCancelThread( void * pxTaskToDelete ) { -Thread_t *pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); + Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); /* * The thread has already been suspended so it can be safely cancelled. @@ -424,11 +436,11 @@ Thread_t *pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); } /*-----------------------------------------------------------*/ -static void *prvWaitForStart( void * pvParams ) +static void * prvWaitForStart( void * pvParams ) { -Thread_t *pxThread = pvParams; + Thread_t * pxThread = pvParams; - prvSuspendSelf(pxThread); + prvSuspendSelf( pxThread ); /* Resumed for the first time, unblocks all signals. */ uxCriticalNesting = 0; @@ -438,22 +450,22 @@ Thread_t *pxThread = pvParams; pxThread->pxCode( pxThread->pvParams ); /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). Artificially force an assert() - * to be triggered if configASSERT() is defined, so application writers can - * catch the error. */ + * its caller as there is nothing to return to. If a task wants to exit it + * should instead call vTaskDelete( NULL ). Artificially force an assert() + * to be triggered if configASSERT() is defined, so application writers can + * catch the error. */ configASSERT( pdFALSE ); return NULL; } /*-----------------------------------------------------------*/ -static void prvSwitchThread( Thread_t *pxThreadToResume, - Thread_t *pxThreadToSuspend ) +static void prvSwitchThread( Thread_t * pxThreadToResume, + Thread_t * pxThreadToSuspend ) { -BaseType_t uxSavedCriticalNesting; + BaseType_t uxSavedCriticalNesting; - if ( pxThreadToSuspend != pxThreadToResume ) + if( pxThreadToSuspend != pxThreadToResume ) { /* * Switch tasks. @@ -465,10 +477,12 @@ BaseType_t uxSavedCriticalNesting; uxSavedCriticalNesting = uxCriticalNesting; prvResumeThread( pxThreadToResume ); - if ( pxThreadToSuspend->xDying ) + + if( pxThreadToSuspend->xDying == pdTRUE ) { pthread_exit( NULL ); } + prvSuspendSelf( pxThreadToSuspend ); uxCriticalNesting = uxSavedCriticalNesting; @@ -476,7 +490,7 @@ BaseType_t uxSavedCriticalNesting; } /*-----------------------------------------------------------*/ -static void prvSuspendSelf( Thread_t *thread ) +static void prvSuspendSelf( Thread_t * thread ) { /* * Suspend this thread by waiting for a pthread_cond_signal event. @@ -490,25 +504,25 @@ static void prvSuspendSelf( Thread_t *thread ) * - From a signal handler that has all signals masked. * * - A thread with all signals blocked with pthread_sigmask(). - */ - event_wait(thread->ev); + */ + event_wait( thread->ev ); } /*-----------------------------------------------------------*/ -static void prvResumeThread( Thread_t *xThreadId ) +static void prvResumeThread( Thread_t * xThreadId ) { - if ( pthread_self() != xThreadId->pthread ) + if( pthread_self() != xThreadId->pthread ) { - event_signal(xThreadId->ev); + event_signal( xThreadId->ev ); } } /*-----------------------------------------------------------*/ static void prvSetupSignalsAndSchedulerPolicy( void ) { -struct sigaction sigresume, sigtick; -int iRet; + struct sigaction sigresume, sigtick; + int iRet; hMainThread = pthread_self(); @@ -516,6 +530,7 @@ int iRet; sigemptyset( &xResumeSignals ); sigaddset( &xResumeSignals, SIG_RESUME ); sigfillset( &xAllSignals ); + /* Don't block SIGINT so this can be used to break into GDB while * in a critical section. */ sigdelset( &xAllSignals, SIGINT ); @@ -527,11 +542,12 @@ int iRet; * When a thread is resumed for the first time, all signals * will be unblocked. */ - (void)pthread_sigmask( SIG_SETMASK, &xAllSignals, - &xSchedulerOriginalSignalMask ); + ( void ) pthread_sigmask( SIG_SETMASK, + &xAllSignals, + &xSchedulerOriginalSignalMask ); /* SIG_RESUME is only used with sigwait() so doesn't need a - handler. */ + * handler. */ sigresume.sa_flags = 0; sigresume.sa_handler = SIG_IGN; sigfillset( &sigresume.sa_mask ); @@ -541,13 +557,15 @@ int iRet; sigfillset( &sigtick.sa_mask ); iRet = sigaction( SIG_RESUME, &sigresume, NULL ); - if ( iRet ) + + if( iRet == -1 ) { prvFatalError( "sigaction", errno ); } iRet = sigaction( SIGALRM, &sigtick, NULL ); - if ( iRet ) + + if( iRet == -1 ) { prvFatalError( "sigaction", errno ); } @@ -556,7 +574,7 @@ int iRet; unsigned long ulPortGetRunTime( void ) { -struct tms xTimes; + struct tms xTimes; times( &xTimes );