void vPortYield( void ) { pthread_t xTaskToSuspend; pthread_t xTaskToResume; if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) { xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); vTaskSwitchContext(); xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); if ( xTaskToSuspend != xTaskToResume ) { /* Remember and switch the critical nesting. */ prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); /* Switch tasks. */ prvResumeThread( xTaskToResume ); prvSuspendThread( xTaskToSuspend ); } else { /* Yielding to self */ (void)pthread_mutex_unlock( &xSingleThreadMutex ); } } }
void vPortStartFirstTask( void ) { /* Initialise the critical nesting count ready for the first task. */ uxCriticalNesting = 0; /* Start the first task. */ vPortEnableInterrupts(); /* Start the first task. */ prvResumeThread( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); }
void vPortSystemTickHandler( int sig ) { pthread_t xTaskToSuspend; pthread_t xTaskToResume; (void)(sig); if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) ) { if ( 0 == pthread_mutex_trylock( &xSingleThreadMutex ) ) { xServicingTick = pdTRUE; xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); /* Tick Increment. */ xTaskIncrementTick(); /* Select Next Task. */ #if ( configUSE_PREEMPTION == 1 ) vTaskSwitchContext(); #endif xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); /* The only thread that can process this tick is the running thread. */ if ( xTaskToSuspend != xTaskToResume ) { /* Remember and switch the critical nesting. */ prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); /* Resume next task. */ prvResumeThread( xTaskToResume ); /* Suspend the current task. */ prvSuspendThread( xTaskToSuspend ); } else { /* Release the lock as we are Resuming. */ (void)pthread_mutex_unlock( &xSingleThreadMutex ); } xServicingTick = pdFALSE; } else { xPendYield = pdTRUE; } } else { xPendYield = pdTRUE; } }
void vPortForciblyEndThread( void *pxTaskToDelete ) { xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; pthread_t xTaskToDelete; pthread_t xTaskToResume; portBASE_TYPE xResult; if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) { xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); if ( xTaskToResume == xTaskToDelete ) { /* This is a suicidal thread, need to select a different task to run. */ vTaskSwitchContext(); xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); } if ( pthread_self() != xTaskToDelete ) { /* Cancelling a thread that is not me. */ if ( xTaskToDelete != ( pthread_t )NULL ) { /* Send a signal to wake the task so that it definitely cancels. */ pthread_testcancel(); xResult = pthread_cancel( xTaskToDelete ); if (xResult) printf("pthread_cancel error!\n"); /* Pthread Clean-up function will note the cancellation. */ } (void)pthread_mutex_unlock( &xSingleThreadMutex ); } else { /* Resume the other thread. */ prvResumeThread( xTaskToResume ); /* Pthread Clean-up function will note the cancellation. */ /* Release the execution. */ uxCriticalNesting = 0; vPortEnableInterrupts(); (void)pthread_mutex_unlock( &xSingleThreadMutex ); /* Commit suicide */ pthread_exit( (void *)1 ); } } }