mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 00:57:44 -04:00
Posix port with pthread cond instead of signals
This commit is contained in:
parent
82fdc1c3ee
commit
fb8820cfc2
3 changed files with 116 additions and 15 deletions
38
portable/ThirdParty/GCC/Posix/port.c
vendored
38
portable/ThirdParty/GCC/Posix/port.c
vendored
|
@ -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 <unistd.h>
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
75
portable/ThirdParty/GCC/Posix/utils/wait_for_event.c
vendored
Normal file
75
portable/ThirdParty/GCC/Posix/utils/wait_for_event.c
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#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 );
|
||||
}
|
18
portable/ThirdParty/GCC/Posix/utils/wait_for_event.h
vendored
Normal file
18
portable/ThirdParty/GCC/Posix/utils/wait_for_event.h
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef _WAIT_FOR_EVENT_H_
|
||||
#define _WAIT_FOR_EVENT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
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_ */
|
Loading…
Add table
Add a link
Reference in a new issue