From fb8820cfc2d0b28502afa3dda3541da0db0ea808 Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Wed, 2 Sep 2020 21:55:41 -0700 Subject: [PATCH] Posix port with pthread cond instead of signals --- portable/ThirdParty/GCC/Posix/port.c | 38 ++++++---- .../GCC/Posix/utils/wait_for_event.c | 75 +++++++++++++++++++ .../GCC/Posix/utils/wait_for_event.h | 18 +++++ 3 files changed, 116 insertions(+), 15 deletions(-) create mode 100644 portable/ThirdParty/GCC/Posix/utils/wait_for_event.c create mode 100644 portable/ThirdParty/GCC/Posix/utils/wait_for_event.h diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index 78166081e..adaab0f89 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -65,6 +65,7 @@ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" +#include "utils/wait_for_event.h" /*-----------------------------------------------------------*/ #define SIG_RESUME SIGUSR1 @@ -75,6 +76,7 @@ typedef struct THREAD pdTASK_CODE pxCode; void *pvParams; BaseType_t xDying; + struct event *ev; } Thread_t; /* @@ -104,9 +106,10 @@ static portBASE_TYPE xSchedulerEnd = pdFALSE; static void prvSetupSignalsAndSchedulerPolicy( void ); static void prvSetupTimerInterrupt( void ); static void *prvWaitForStart( void * pvParams ); -static void prvSwitchThread( Thread_t *xThreadToResume, Thread_t *xThreadToSuspend ); -static void prvSuspendSelf( void ); -static void prvResumeThread( pthread_t xThreadId ); +static void prvSwitchThread( Thread_t * xThreadToResume, + Thread_t *xThreadToSuspend ); +static void prvSuspendSelf( Thread_t * thread); +static void prvResumeThread( Thread_t * xThreadId ); static void vPortSystemTickHandler( int sig ); static void vPortStartFirstTask( void ); /*-----------------------------------------------------------*/ @@ -214,6 +217,8 @@ int iRet; pthread_attr_init( &xThreadAttributes ); pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize ); + thread->ev = event_create(); + vPortEnterCritical(); iRet = pthread_create( &thread->pthread, &xThreadAttributes, @@ -234,10 +239,10 @@ void vPortStartFirstTask( void ) Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); /* Start the first task. */ - prvResumeThread( pxFirstThread->pthread ); + prvResumeThread( pxFirstThread ); } /*-----------------------------------------------------------*/ - +#include /* * See header file for description. */ @@ -261,7 +266,8 @@ sigset_t xSignals; while ( !xSchedulerEnd ) { - sigwait( &xSignals, &iSignal ); + //sigwait( &xSignals, &iSignal ); + sleep(1); } /* Restore original signal mask. */ @@ -294,7 +300,7 @@ struct sigaction sigtick; xSchedulerEnd = pdTRUE; (void)pthread_kill( hMainThread, SIG_RESUME ); - prvSuspendSelf(); + //prvSuspendSelf(); } /*-----------------------------------------------------------*/ @@ -473,7 +479,7 @@ static void *prvWaitForStart( void * pvParams ) { Thread_t *pxThread = pvParams; - prvSuspendSelf(); + prvSuspendSelf(pxThread); /* Resumed for the first time, unblocks all signals. */ uxCriticalNesting = 0; @@ -502,19 +508,19 @@ BaseType_t uxSavedCriticalNesting; */ uxSavedCriticalNesting = uxCriticalNesting; - prvResumeThread( pxThreadToResume->pthread ); + prvResumeThread( pxThreadToResume ); if ( pxThreadToSuspend->xDying ) { pthread_exit( NULL ); } - prvSuspendSelf(); + prvSuspendSelf( pxThreadToSuspend ); uxCriticalNesting = uxSavedCriticalNesting; } } /*-----------------------------------------------------------*/ -static void prvSuspendSelf( void ) +static void prvSuspendSelf( Thread_t *thread ) { int iSig; @@ -531,16 +537,18 @@ int iSig; * * - A thread with all signals blocked with pthread_sigmask(). */ - sigwait( &xResumeSignals, &iSig ); + event_wait(thread->ev); + //sigwait( &xResumeSignals, &iSig ); } /*-----------------------------------------------------------*/ -static void prvResumeThread( pthread_t xThreadId ) +static void prvResumeThread( Thread_t *xThreadId ) { - if ( pthread_self() != xThreadId ) + if ( pthread_self() != xThreadId->pthread ) { - pthread_kill( xThreadId, SIG_RESUME ); + //pthread_kill( xThreadId, SIG_RESUME ); + event_signal(xThreadId->ev); } } /*-----------------------------------------------------------*/ diff --git a/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c b/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c new file mode 100644 index 000000000..6d0bfffda --- /dev/null +++ b/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c @@ -0,0 +1,75 @@ +#include +#include +#include + +#include "wait_for_event.h" + +struct event +{ + pthread_mutex_t mutex; + pthread_cond_t cond; + bool event_triggered; +}; + +struct event * event_create() +{ + struct event * ev = malloc( sizeof( struct event ) ); + + ev->event_triggered = false; + pthread_mutex_init( &ev->mutex, NULL ); + pthread_cond_init( &ev->cond, NULL ); + return ev; +} + +void event_delete( struct event * ev ) +{ + pthread_mutex_destroy( &ev->mutex ); + pthread_cond_destroy( &ev->cond ); + free( ev ); +} + +bool event_wait( struct event * ev ) +{ + pthread_mutex_lock( &ev->mutex ); + + while( ev->event_triggered == false ) + { + pthread_cond_wait( &ev->cond, &ev->mutex ); + } + + pthread_mutex_unlock( &ev->mutex ); + return true; +} +bool event_wait_timed( struct event * ev, + time_t ms ) +{ + struct timespec ts; + int ret = 0; + + clock_gettime( CLOCK_REALTIME, &ts ); + //ts.tv_sec += ms; + ts.tv_nsec += (ms * 1000000); + pthread_mutex_lock( &ev->mutex ); + + while( (ev->event_triggered == false) && (ret == 0) ) + { + ret = pthread_cond_timedwait( &ev->cond, &ev->mutex, &ts ); + + if( ( ret == -1 ) && ( errno == ETIMEDOUT ) ) + { + return false; + } + } + + ev->event_triggered = false; + pthread_mutex_unlock( &ev->mutex ); + return true; +} + +void event_signal( struct event * ev ) +{ + pthread_mutex_lock( &ev->mutex ); + ev->event_triggered = true; + pthread_cond_signal( &ev->cond ); + pthread_mutex_unlock( &ev->mutex ); +} diff --git a/portable/ThirdParty/GCC/Posix/utils/wait_for_event.h b/portable/ThirdParty/GCC/Posix/utils/wait_for_event.h new file mode 100644 index 000000000..2693a0d8c --- /dev/null +++ b/portable/ThirdParty/GCC/Posix/utils/wait_for_event.h @@ -0,0 +1,18 @@ +#ifndef _WAIT_FOR_EVENT_H_ +#define _WAIT_FOR_EVENT_H_ + +#include +#include + +struct event; + +struct event * event_create(); +void event_delete( struct event * ); +bool event_wait( struct event * ev ); +bool event_wait_timed( struct event * ev, + time_t ms ); +void event_signal( struct event * ev ); + + + +#endif /* ifndef _WAIT_FOR_EVENT_H_ */