mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 09:07:46 -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. */
|
/* Scheduler includes. */
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "utils/wait_for_event.h"
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#define SIG_RESUME SIGUSR1
|
#define SIG_RESUME SIGUSR1
|
||||||
|
@ -75,6 +76,7 @@ typedef struct THREAD
|
||||||
pdTASK_CODE pxCode;
|
pdTASK_CODE pxCode;
|
||||||
void *pvParams;
|
void *pvParams;
|
||||||
BaseType_t xDying;
|
BaseType_t xDying;
|
||||||
|
struct event *ev;
|
||||||
} Thread_t;
|
} Thread_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -104,9 +106,10 @@ static portBASE_TYPE xSchedulerEnd = pdFALSE;
|
||||||
static void prvSetupSignalsAndSchedulerPolicy( void );
|
static void prvSetupSignalsAndSchedulerPolicy( void );
|
||||||
static void prvSetupTimerInterrupt( 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 prvSwitchThread( Thread_t * xThreadToResume,
|
||||||
static void prvSuspendSelf( void );
|
Thread_t *xThreadToSuspend );
|
||||||
static void prvResumeThread( pthread_t xThreadId );
|
static void prvSuspendSelf( Thread_t * thread);
|
||||||
|
static void prvResumeThread( Thread_t * xThreadId );
|
||||||
static void vPortSystemTickHandler( int sig );
|
static void vPortSystemTickHandler( int sig );
|
||||||
static void vPortStartFirstTask( void );
|
static void vPortStartFirstTask( void );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -214,6 +217,8 @@ int iRet;
|
||||||
pthread_attr_init( &xThreadAttributes );
|
pthread_attr_init( &xThreadAttributes );
|
||||||
pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
|
pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
|
||||||
|
|
||||||
|
thread->ev = event_create();
|
||||||
|
|
||||||
vPortEnterCritical();
|
vPortEnterCritical();
|
||||||
|
|
||||||
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
|
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
|
||||||
|
@ -234,10 +239,10 @@ void vPortStartFirstTask( void )
|
||||||
Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||||
|
|
||||||
/* Start the first task. */
|
/* Start the first task. */
|
||||||
prvResumeThread( pxFirstThread->pthread );
|
prvResumeThread( pxFirstThread );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
#include <unistd.h>
|
||||||
/*
|
/*
|
||||||
* See header file for description.
|
* See header file for description.
|
||||||
*/
|
*/
|
||||||
|
@ -261,7 +266,8 @@ sigset_t xSignals;
|
||||||
|
|
||||||
while ( !xSchedulerEnd )
|
while ( !xSchedulerEnd )
|
||||||
{
|
{
|
||||||
sigwait( &xSignals, &iSignal );
|
//sigwait( &xSignals, &iSignal );
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore original signal mask. */
|
/* Restore original signal mask. */
|
||||||
|
@ -294,7 +300,7 @@ struct sigaction sigtick;
|
||||||
xSchedulerEnd = pdTRUE;
|
xSchedulerEnd = pdTRUE;
|
||||||
(void)pthread_kill( hMainThread, SIG_RESUME );
|
(void)pthread_kill( hMainThread, SIG_RESUME );
|
||||||
|
|
||||||
prvSuspendSelf();
|
//prvSuspendSelf();
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -473,7 +479,7 @@ static void *prvWaitForStart( void * pvParams )
|
||||||
{
|
{
|
||||||
Thread_t *pxThread = pvParams;
|
Thread_t *pxThread = pvParams;
|
||||||
|
|
||||||
prvSuspendSelf();
|
prvSuspendSelf(pxThread);
|
||||||
|
|
||||||
/* Resumed for the first time, unblocks all signals. */
|
/* Resumed for the first time, unblocks all signals. */
|
||||||
uxCriticalNesting = 0;
|
uxCriticalNesting = 0;
|
||||||
|
@ -502,19 +508,19 @@ BaseType_t uxSavedCriticalNesting;
|
||||||
*/
|
*/
|
||||||
uxSavedCriticalNesting = uxCriticalNesting;
|
uxSavedCriticalNesting = uxCriticalNesting;
|
||||||
|
|
||||||
prvResumeThread( pxThreadToResume->pthread );
|
prvResumeThread( pxThreadToResume );
|
||||||
if ( pxThreadToSuspend->xDying )
|
if ( pxThreadToSuspend->xDying )
|
||||||
{
|
{
|
||||||
pthread_exit( NULL );
|
pthread_exit( NULL );
|
||||||
}
|
}
|
||||||
prvSuspendSelf();
|
prvSuspendSelf( pxThreadToSuspend );
|
||||||
|
|
||||||
uxCriticalNesting = uxSavedCriticalNesting;
|
uxCriticalNesting = uxSavedCriticalNesting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void prvSuspendSelf( void )
|
static void prvSuspendSelf( Thread_t *thread )
|
||||||
{
|
{
|
||||||
int iSig;
|
int iSig;
|
||||||
|
|
||||||
|
@ -531,16 +537,18 @@ int iSig;
|
||||||
*
|
*
|
||||||
* - A thread with all signals blocked with pthread_sigmask().
|
* - 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