-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Improve POSIX port functionality #914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d0d2a91
086f95b
f57af3e
79d4181
9cb382d
1d2c5c5
036a8d8
1f763f0
a624921
8cdc1ad
2290f28
c938e61
c9d1304
7a4785d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,6 +60,7 @@ | |
#include <sys/time.h> | ||
#include <sys/times.h> | ||
#include <time.h> | ||
#include <unistd.h> | ||
|
||
#ifdef __APPLE__ | ||
#include <mach/mach_vm.h> | ||
|
@@ -68,6 +69,7 @@ | |
/* Scheduler includes. */ | ||
#include "FreeRTOS.h" | ||
#include "task.h" | ||
#include "list.h" | ||
#include "timers.h" | ||
#include "utils/wait_for_event.h" | ||
/*-----------------------------------------------------------*/ | ||
|
@@ -81,6 +83,7 @@ typedef struct THREAD | |
void * pvParams; | ||
BaseType_t xDying; | ||
struct event * ev; | ||
ListItem_t xThreadListItem; | ||
} Thread_t; | ||
|
||
/* | ||
|
@@ -101,9 +104,11 @@ static sigset_t xAllSignals; | |
static sigset_t xSchedulerOriginalSignalMask; | ||
static pthread_t hMainThread = ( pthread_t ) NULL; | ||
static volatile BaseType_t uxCriticalNesting; | ||
/*-----------------------------------------------------------*/ | ||
|
||
static BaseType_t xSchedulerEnd = pdFALSE; | ||
static pthread_t hTimerTickThread; | ||
static bool xTimerTickThreadShouldRun; | ||
static uint64_t prvStartTimeNs; | ||
static List_t xThreadList; | ||
/*-----------------------------------------------------------*/ | ||
|
||
static void prvSetupSignalsAndSchedulerPolicy( void ); | ||
|
@@ -127,6 +132,7 @@ void prvFatalError( const char * pcCall, | |
fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) ); | ||
abort(); | ||
} | ||
/*-----------------------------------------------------------*/ | ||
|
||
/* | ||
* See header file for description. | ||
|
@@ -163,19 +169,27 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, | |
thread->pvParams = pvParameters; | ||
thread->xDying = pdFALSE; | ||
|
||
/* Ensure ulStackSize is at least PTHREAD_STACK_MIN */ | ||
ulStackSize = (ulStackSize < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : ulStackSize; | ||
|
||
pthread_attr_init( &xThreadAttributes ); | ||
iRet = pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize ); | ||
iRet = pthread_attr_setstacksize( &xThreadAttributes, ulStackSize ); | ||
|
||
if( iRet != 0 ) | ||
{ | ||
fprintf( stderr, "[WARN] pthread_attr_setstack failed with return value: %d. Default stack will be used.\n", iRet ); | ||
fprintf( stderr, "[WARN] Increase the stack size to PTHREAD_STACK_MIN.\n" ); | ||
fprintf( stderr, "[WARN] pthread_attr_setstacksize failed with return value: %d. Default stack size will be used.\n", iRet ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this log message unnecessary now that the stack size is set to be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pthreaad_attr_setstacksize() could still fail and in those cases I thought it was useful to report it to the user. It should be very rare but there are a number of conditions that could result in it failing and given that this is an OS it seemed like we should handle all error conditions in some manner, even if that's a warning printout since the consequences are usually minimal if this does fail. |
||
} | ||
|
||
thread->ev = event_create(); | ||
|
||
vListInitialiseItem( &thread->xThreadListItem ); | ||
listSET_LIST_ITEM_OWNER( &thread->xThreadListItem, thread ); | ||
|
||
vPortEnterCritical(); | ||
|
||
/* Add the new thread in xThreadList. */ | ||
vListInsertEnd( &xThreadList, &thread->xThreadListItem ); | ||
|
||
iRet = pthread_create( &thread->pthread, &xThreadAttributes, | ||
prvWaitForStart, thread ); | ||
|
||
|
@@ -206,6 +220,8 @@ BaseType_t xPortStartScheduler( void ) | |
{ | ||
int iSignal; | ||
sigset_t xSignals; | ||
ListItem_t * pxIterator; | ||
const ListItem_t * pxEndMarker; | ||
|
||
hMainThread = pthread_self(); | ||
|
||
|
@@ -231,15 +247,28 @@ BaseType_t xPortStartScheduler( void ) | |
sigwait( &xSignals, &iSignal ); | ||
} | ||
|
||
/* Cancel the Idle task and free its resources */ | ||
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) | ||
vPortCancelThread( xTaskGetIdleTaskHandle() ); | ||
#endif | ||
/* Cancel all the running thread. */ | ||
pxEndMarker = listGET_END_MARKER( &xThreadList ); | ||
|
||
for( pxIterator = listGET_HEAD_ENTRY( &xThreadList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) ) | ||
{ | ||
Thread_t * pxThread = ( Thread_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); | ||
|
||
pthread_cancel( pxThread->pthread ); | ||
event_signal( pxThread->ev ); | ||
pthread_join( pxThread->pthread, NULL ); | ||
event_delete( pxThread->ev ); | ||
} | ||
|
||
/* | ||
* clear out the variable that is used to end the scheduler, otherwise | ||
* subsequent scheduler restarts will end immediately. | ||
*/ | ||
xSchedulerEnd = pdFALSE; | ||
|
||
#if ( configUSE_TIMERS == 1 ) | ||
/* Cancel the Timer task and free its resources */ | ||
vPortCancelThread( xTimerGetTimerDaemonTaskHandle() ); | ||
#endif /* configUSE_TIMERS */ | ||
/* Reset the pthread_once_t structure. This is required if the port | ||
* starts the scheduler again. */ | ||
hSigSetupThread = PTHREAD_ONCE_INIT; | ||
|
||
/* Restore original signal mask. */ | ||
( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); | ||
|
@@ -250,30 +279,15 @@ 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 ); | ||
/* Stop the timer tick thread. */ | ||
xTimerTickThreadShouldRun = false; | ||
pthread_join( hTimerTickThread, NULL ); | ||
|
||
/* Signal the scheduler to exit its loop. */ | ||
xSchedulerEnd = pdTRUE; | ||
( void ) pthread_kill( hMainThread, SIG_RESUME ); | ||
|
||
xCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); | ||
prvSuspendSelf( xCurrentThread ); | ||
pthread_exit( NULL ); | ||
} | ||
/*-----------------------------------------------------------*/ | ||
|
||
|
@@ -359,45 +373,37 @@ static uint64_t prvGetTimeNs( void ) | |
|
||
return ( uint64_t ) t.tv_sec * ( uint64_t ) 1000000000UL + ( uint64_t ) 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; */ | ||
|
||
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(); | ||
} | ||
|
@@ -454,15 +460,22 @@ void vPortThreadDying( void * pxTaskToDelete, | |
|
||
pxThread->xDying = pdTRUE; | ||
} | ||
/*-----------------------------------------------------------*/ | ||
|
||
void vPortCancelThread( void * pxTaskToDelete ) | ||
{ | ||
Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); | ||
|
||
/* Remove the thread from xThreadList. */ | ||
vPortEnterCritical(); | ||
uxListRemove( &pxThreadToCancel->xThreadListItem ); | ||
vPortExitCritical(); | ||
|
||
/* | ||
* The thread has already been suspended so it can be safely cancelled. | ||
*/ | ||
pthread_cancel( pxThreadToCancel->pthread ); | ||
event_signal( pxThreadToCancel->ev ); | ||
pthread_join( pxThreadToCancel->pthread, NULL ); | ||
event_delete( pxThreadToCancel->ev ); | ||
} | ||
|
@@ -538,6 +551,7 @@ static void prvSuspendSelf( Thread_t * thread ) | |
* - A thread with all signals blocked with pthread_sigmask(). | ||
*/ | ||
event_wait( thread->ev ); | ||
pthread_testcancel(); | ||
} | ||
|
||
/*-----------------------------------------------------------*/ | ||
|
@@ -558,6 +572,9 @@ static void prvSetupSignalsAndSchedulerPolicy( void ) | |
|
||
hMainThread = pthread_self(); | ||
|
||
/* Setup thread list to record all the task which are not deleted. */ | ||
vListInitialise( &xThreadList ); | ||
|
||
/* Initialise common signal masks. */ | ||
sigfillset( &xAllSignals ); | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.