diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index 5dc3d73e2..d312aa48d 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -60,6 +60,7 @@ #include #include #include +#include #ifdef __APPLE__ #include @@ -103,6 +104,9 @@ static pthread_t hMainThread = ( pthread_t ) NULL; static volatile BaseType_t uxCriticalNesting; /*-----------------------------------------------------------*/ +static pthread_t hTimerTickThread; +static bool xTimerTickThreadShouldRun; + static BaseType_t xSchedulerEnd = pdFALSE; /*-----------------------------------------------------------*/ @@ -231,6 +235,10 @@ BaseType_t xPortStartScheduler( void ) sigwait( &xSignals, &iSignal ); } + /* asking timer thread to shut down */ + xTimerTickThreadShouldRun = false; + pthread_join( hTimerTickThread, NULL ); + /* Cancel the Idle task and free its resources */ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) vPortCancelThread( xTaskGetIdleTaskHandle() ); @@ -250,24 +258,8 @@ BaseType_t xPortStartScheduler( void ) void vPortEndScheduler( void ) { - 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. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = 0; - - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = 0; - ( void ) setitimer( ITIMER_REAL, &itimer, NULL ); - - sigtick.sa_flags = 0; - sigtick.sa_handler = SIG_IGN; - sigemptyset( &sigtick.sa_mask ); - sigaction( SIGALRM, &sigtick, NULL ); - /* Signal the scheduler to exit its loop. */ xSchedulerEnd = pdTRUE; ( void ) pthread_kill( hMainThread, SIG_RESUME ); @@ -366,38 +358,31 @@ static uint64_t prvStartTimeNs; * to adjust timing according to full demo requirements */ /* static uint64_t prvTickCount; */ +static void* prvTimerTickHandler(void *arg) +{ + while( xTimerTickThreadShouldRun ) + { + /* + * signal to the active task to cause tick handling or + * preemption (if enabled) + */ + Thread_t * thread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + pthread_kill( thread->pthread, SIGALRM ); + + usleep( portTICK_RATE_MICROSECONDS ); + } + + return NULL; +} + /* * Setup the systick timer to generate the tick interrupts at the required * frequency. */ void prvSetupTimerInterrupt( void ) { - struct itimerval itimer; - int iRet; - - /* Initialise the structure with the current timer information. */ - iRet = getitimer( ITIMER_REAL, &itimer ); - - if( iRet == -1 ) - { - prvFatalError( "getitimer", errno ); - } - - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = portTICK_RATE_MICROSECONDS; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS; - - /* Set-up the timer interrupt. */ - iRet = setitimer( ITIMER_REAL, &itimer, NULL ); - - if( iRet == -1 ) - { - prvFatalError( "setitimer", errno ); - } + xTimerTickThreadShouldRun = true; + pthread_create( &hTimerTickThread, NULL, prvTimerTickHandler, NULL ); prvStartTimeNs = prvGetTimeNs(); }