diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_linux.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_linux.c deleted file mode 100644 index 20fa0cb9e..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_linux.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -/*-----------------------------------------------------------*/ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB* debug_task_handle; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - -#ifdef DEBUG_OUTPUT - static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; - #define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - //int xbla; - //#define debug_printf(...) xbla=0 - int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); - } - int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); - } - #define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) - #define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) - #define pthread_kill(thread,signal) ( (debug_printf(" sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) - #define vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -#else - #define debug_printf(...) -#endif - -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - while (hActiveThread!=hRequestedThread && !xVeryFirstTask) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - debug_printf("Seting up very first task (main) - MAIN is ACTIVE TASK\n"); - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - hActiveThread=pthread_self(); - hRequestedThread=hActiveThread; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - hActiveThread=pthread_self(); - debug_printf("ACTIVE THREAD RECLAIMED!\n"); - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex locking failed\n"); - exit(1); - } - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf("main: forwarding signal to %li\n",(long)hRequestedThread); - (void)pthread_kill( hRequestedThread, SIG_RESUME ); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSingleThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - xServicingTick = pdTRUE; - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - debug_printf("does handle tick\n"); - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - if (hActiveThread!=hRequestedThread) { - xServicingTick = pdFALSE; - xPendYield = pdTRUE; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - return; - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - //hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - hRequestedThread = 0; - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - while ( 0 != pthread_mutex_timedlock( &xRunningThreadMutex,&timeout ) ) { - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - } - /* - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex)) { - debug_printf("mutex lock failed!\n"); - exit(1); - } - */ - //if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xServicingTick = pdFALSE; - } - else - { - debug_printf("will NOT handle tick\n"); - 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 ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex lock failed!\n"); - exit(1); - } - } - - 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 ); - /* 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 ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - hActiveThread=pthread_self(); - debug_printf("temporarily made ACTIVE THREAD!\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - debug_printf("ACTIVE THREAD!\n"); -} -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself, sigresume, sigtick; -portLONG lIndex; - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigfillset( &sigsuspendself.sa_mask ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ -pthread_t hThread = ( pthread_t )NULL; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - /* Needs to be reasonably high for accuracy. */ - unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_new-thread-implementation_works-on-linux.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_new-thread-implementation_works-on-linux.c deleted file mode 100755 index 7f38e2a2d..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_new-thread-implementation_works-on-linux.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -static void prvResolveFuckup( void ); -/*-----------------------------------------------------------*/ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB* debug_task_handle; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - -//int xbla; -//#define debug_printf(...) xbla=0 -int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); -} -int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); -} -/* -#define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) -#define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) -#define pthread_kill(thread,signal) ( (debug_printf(" sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) -#define vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -*/ -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -int fuckedUpCount=0; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - if (xGeneralFuckedUpIndicator!=0) { - fuckedUpCount++; - if (fuckedUpCount>10) { - fuckedUpCount=0; - prvResolveFuckup(); - } - } else { - fuckedUpCount=0; - } - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf( "ALERT! Main received SIG_RESUME that was supposed to go elsewhere!"); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSingleThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - sched_yield(); - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - //debug_printf("will handle tick\n"); - xServicingTick = pdTRUE; - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - sched_yield(); - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - //if ( 0 == pthread_mutex_timedlock( &xRunningThreadMutex,&timeout ) ) { - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } else { - debug_printf("Oh dear - tick handler could not acquire lock!\n\n"); - //prvResumeThread( xTaskToSuspend ); - xGeneralFuckedUpIndicator=3; - } - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - xServicingTick = pdFALSE; - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - else - { - debug_printf("will NOT handle tick\n"); - 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 ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - sched_yield(); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("THIS was never meant to happen\n"); - exit(1); - } - } - - 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 ); - /* 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 ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - //debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } else if (sig == SIG_RESUME) { - //debug_printf("received signal %i\n",sig); - /* Make sure the right thread received the signal */ - if (hRequestedThread != pthread_self() ) { - debug_printf( "ALERT! Received SIG_RESUME which is already outdated!\n active thread is %li\n",(long)hRequestedThread); - /* Signal main thread something just went wrong */ - xGeneralFuckedUpIndicator = 1; - /* - if (0 == sigpending(&xPendingSignals)) { - if (sigismember(&xPendingSignals,SIG_SUSPEND)) { - debug_printf( "reason: we slept too long...\n"); - //(void)sigwait(&xPendingSignals,&sig); - // we can safely return - signal is already pending - return; - } - } - debug_printf( "reason: unknown! - whatever ...\n\n"); - */ - //exit(1); - //(void)pthread_kill( xTaskToResume, SIG_RESUME ); - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - //debug_printf("ACTIVE THREAD!\n"); -} -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself, sigresume, sigtick; -portLONG lIndex; - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigfillset( &sigsuspendself.sa_mask ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ -pthread_t hThread = ( pthread_t )NULL; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - /* Needs to be reasonably high for accuracy. */ - unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ -/** - * Scheduler f***d up - we got to fix that - */ -void prvResolveFuckup( void ) -{ - - printf("Scheduler fucked up again - lets try to fix it...\n"); - printf("sending sig_suspend to thread that is supposed to be dead...\n"); - prvSuspendThread(hActiveThread); - printf("acquire running lock..."); - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - printf("sending sig_resume to thread that is supposed to be running...\n"); - prvResumeThread(hRequestedThread); - printf("giving up mutex...\n"); - (void)pthread_mutex_unlock(&xRunningThreadMutex); - } - -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_test-for-macos.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_test-for-macos.c deleted file mode 100644 index 81af9bcec..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_test-for-macos.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -/*-----------------------------------------------------------*/ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB* debug_task_handle; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - -//int xbla; -//#define debug_printf(...) xbla=0 -int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); -} -int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); -} -#define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) -#define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) -#define pthread_kill(thread,signal) ( (debug_printf(" sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) -#define vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - while (hActiveThread!=hRequestedThread && !xVeryFirstTask) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - debug_printf("Seting up very first task (main) - MAIN is ACTIVE TASK\n"); - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - hActiveThread=pthread_self(); - hRequestedThread=hActiveThread; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - hActiveThread=pthread_self(); - debug_printf("ACTIVE THREAD RECLAIMED!\n"); - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex locking failed\n"); - exit(1); - } - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf("main: forwarding signal to %li\n",(long)hRequestedThread); - (void)pthread_kill( hRequestedThread, SIG_RESUME ); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSingleThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { - debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - xServicingTick = pdTRUE; - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - debug_printf("does handle tick\n"); - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - if (hActiveThread!=hRequestedThread) { - xServicingTick = pdFALSE; - xPendYield = pdTRUE; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - return; - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - //hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - hRequestedThread = 0; - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - /*while ( 0 != pthread_mutex_timedlock( &xRunningThreadMutex,&timeout ) ) { - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=10000; - } - */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex)) { - debug_printf("mutex lock failed!\n"); - exit(1); - } - //if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xServicingTick = pdFALSE; - } - else - { - debug_printf("will NOT handle tick\n"); - 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 ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex lock failed!\n"); - exit(1); - } - } - - 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 ); - /* 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 ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - hActiveThread=pthread_self(); - debug_printf("temporarily made ACTIVE THREAD!\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } else if (sig == SIG_RESUME) { - //debug_printf("received signal %i\n",sig); - /* Make sure the right thread received the signal */ - if (hRequestedThread != pthread_self() ) { - debug_printf( "resume_signalhandler: forwarding to %li\n",(long)hRequestedThread); - (void)pthread_kill( hRequestedThread, SIG_RESUME ); - } - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - debug_printf("ACTIVE THREAD!\n"); -} -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself, sigresume, sigtick; -portLONG lIndex; - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigfillset( &sigsuspendself.sa_mask ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ -pthread_t hThread = ( pthread_t )NULL; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - /* Needs to be reasonably high for accuracy. */ - unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_with-debugging-output.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_with-debugging-output.c deleted file mode 100755 index a9679b712..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/port_with-debugging-output.c +++ /dev/null @@ -1,1097 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xRunningThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -static pthread_t hActiveThread = ( pthread_t )NULL; -static pthread_t hRequestedThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xGeneralFuckedUpIndicator = 0; -static volatile portBASE_TYPE xVeryFirstTask = 1; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void prvSetupTimerInterrupt( void ); -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -static void prvResolveFuckup( void ); -/*-----------------------------------------------------------*/ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB* debug_task_handle; -tskTCB* prvGetTaskHandle( pthread_t hThread ) -{ -portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -#define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%s(%li)\t%s\t%i:",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "__unknown__(%li)\t%s\t%i:",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - -//int xbla; -//#define debug_printf(...) xbla=0 -int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); -} -int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); -} -#define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) -#define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) -#define pthread_mutex_trylock(...) ( pthread_mutex_trylock(__VA_ARGS__)==0?((debug_printf(" -:)- pthread_mutex_trylock(%s) success\n",#__VA_ARGS__)|1)?0:0):-1) -#define pthread_kill(thread,signal) ( (debug_printf(" sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) -#define vTaskSwitchContext() ( (debug_printf("SWITCHCONTEXT!\n")|1)?vTaskSwitchContext():vTaskSwitchContext() ) -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); -// if ( 0 == xResult ) -// { - /* Set-up for the Suspend Signal handler? */ - //xSentinel = 0; -//portBASE_TYPE aSentinel=xSentinel; - xResult = pthread_kill( xThreadId, SIG_SUSPEND ); -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// while ( ( aSentinel == xSentinel ) && ( pdTRUE != xServicingTick ) ) -// { -// sched_yield(); -// } -// } -} -/*-----------------------------------------------------------*/ - -void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) -// { - if ( pthread_self() != xThreadId ) - { - xResult = pthread_kill( xThreadId, SIG_RESUME ); - } -// xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); -// } -} -#define prvSuspendThread(thread) debug_printf("calling SuspendThread(%li)\n",(long)thread); prvSuspendThread(thread) -#define prvResumeThread(thread) debug_printf("calling ResumeThread(%li)\n",(long)thread); prvResumeThread(thread) - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - while (hActiveThread!=hRequestedThread && !xVeryFirstTask) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create the new pThread. */ - /* On creation of the very first thread, RunningThreadMutex is not claimed yet - * by the master thread - do that! */ - if (xVeryFirstTask==1) { - debug_printf("Seting up very first task (main) - MAIN is ACTIVE TASK\n"); - if (0 == pthread_mutex_lock( &xRunningThreadMutex)) { - xVeryFirstTask=0; - hActiveThread=pthread_self(); - hRequestedThread=hActiveThread; - } else { - printf("Failed to acquire lock for first task"); - exit(1); - } - - } - - if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) - { - /* Thread create failed, signal the failure */ - pxTopOfStack = 0; - } - - /* Wait until the task suspends. */ - xSentinel=0; - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - while ( xSentinel == 0 ) { - sched_yield(); - } - (void)pthread_mutex_lock( &xRunningThreadMutex ); - hActiveThread=pthread_self(); - debug_printf("ACTIVE THREAD RECLAIMED!\n"); - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex locking failed\n"); - exit(1); - } - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - hRequestedThread=prvGetThreadHandle( xTaskGetCurrentTaskHandle()); - prvResumeThread( hRequestedThread ); - - sched_yield(); -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -int iSignal; -int fuckedUpCount=0; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_TICK ); - - /* Allow other threads to run */ - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - debug_printf( "MAIN thread is entering main signal wait loop!\n"); - - while ( pdTRUE != xSchedulerEnd ) - { - if ( 0 != sigwait( &xSignals, &iSignal ) ) - { - printf( "Main thread spurious signal: %d\n", iSignal ); - } - /** - * Tick handler is called from here - AND ONLY FROM HERE - * (needed for cygwin - but should work on all) - */ - if (iSignal==SIG_TICK) { - if (xGeneralFuckedUpIndicator!=0 && hActiveThread!=hRequestedThread) { - fuckedUpCount++; - if (fuckedUpCount>10) { - fuckedUpCount=0; - prvResolveFuckup(); - } - } else { - fuckedUpCount=0; - } - vPortSystemTickHandler(iSignal); - } - if (iSignal==SIG_RESUME && pdTRUE != xSchedulerEnd) { - debug_printf( "ALERT! Main received SIG_RESUME that was supposed to go elsewhere!"); - } - } - - printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - //xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - //xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - xResult = pthread_mutex_destroy( &xRunningThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSingleThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; - - /** - * Sentinel - do not change context while the running task is not equal the task supposed to run - */ -// if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - while ( 0 != pthread_mutex_trylock ( &xSuspendResumeThreadMutex ) ) { - sched_yield(); - } - - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - while (0 != pthread_mutex_trylock( &xSuspendResumeThreadMutex )) { - sched_yield(); - } - } - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - vTaskSwitchContext(); - - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if ( xTaskToSuspend != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Switch tasks. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); - //prvSuspendThread( xTaskToSuspend ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - prvSuspendSignalHandler(SIG_SUSPEND); - return; - } - else - { - /* Yielding to self */ - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - -/* - * Setup the systick timer to generate the tick interrupts at the required - * frequency. - */ -void prvSetupTimerInterrupt( void ) -{ -struct itimerval itimer, oitimer; -portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - if ( 0 == getitimer( TIMER_TYPE, &itimer ) ) - { - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - /* Set-up the timer interrupt. */ - if ( 0 != setitimer( TIMER_TYPE, &itimer, &oitimer ) ) - { - printf( "Set Timer problem.\n" ); - } - } - else - { - printf( "Get Timer problem.\n" ); - } -} -/*-----------------------------------------------------------*/ - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -struct timespec timeout; - - //debug_printf("received %i\n",sig); - /** - * do not call tick handler if - * - interrupts are disabled - * - tick handler is still running - * - old task switch not yet completed (wrong task running) - */ - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) && ( hRequestedThread == hActiveThread ) ) - { - xServicingTick = pdTRUE; - if ( 0 == pthread_mutex_trylock( &xSuspendResumeThreadMutex ) ) - { - debug_printf("does handle tick\n"); - - /** - * this shouldn't ever happen - but WELL... - * Make sure we don't create outdated resume signals - */ - if (hActiveThread!=hRequestedThread) { - xServicingTick = pdFALSE; - xPendYield = pdTRUE; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - return; - } - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - //hRequestedThread = xTaskToResume; - - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - /* Suspend the current task. */ - hRequestedThread = 0; - prvSuspendThread( xTaskToSuspend ); - //timeout.tv_sec=0; - //timeout.tv_nsec=10000; - //sched_yield(); - while ( 0 != pthread_mutex_lock( &xRunningThreadMutex) ) { - prvSuspendThread( xTaskToSuspend ); - timeout.tv_sec=0; - timeout.tv_nsec=1; - nanosleep(&timeout,0); - } - //if ( 0 == pthread_mutex_lock( &xRunningThreadMutex) ) { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - /* Resume next task. */ - hRequestedThread = xTaskToResume; - prvResumeThread( xTaskToResume ); -if (prvGetThreadHandle(xTaskGetCurrentTaskHandle())!=xTaskToResume) { -debug_printf("\n what the fuck???? someone else did a switchcontext?!?\n"); -} - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - } - else - { - /* Release the lock as we are Resuming. */ - // (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - } - else - { - xPendYield = pdTRUE; - } - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - xServicingTick = pdFALSE; - } - else - { - debug_printf("will NOT handle tick\n"); - 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 ) - { - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) { - /** - * Make sure we don't create outdated resume signals - */ - while (hActiveThread!=hRequestedThread) { - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - sched_yield(); - (void)pthread_mutex_lock( &xSuspendResumeThreadMutex ); - } - /* This is a suicidal thread, need to select a different task to run. */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - hRequestedThread = xTaskToResume; - (void)pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } else { - debug_printf("mutex lock failed!\n"); - exit(1); - } - } - - 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 ); - /* 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 ); - (void)pthread_mutex_unlock( &xRunningThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } -// } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; -sigset_t xSignals; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - if ( 0 == pthread_mutex_lock( &xRunningThreadMutex ) ) - { - xSentinel=1; - hActiveThread=pthread_self(); - debug_printf("temporarily made ACTIVE THREAD!\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - /* set up proc mask */ - pthread_sigmask(SIG_SETMASK,&xSignals,NULL); - - prvSuspendSignalHandler(SIG_SUSPEND); - //prvSuspendThread( pthread_self() ); - } else { - debug_printf("now this is just WRONG!\n"); - exit(1); - } - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xSignals; -//sigset_t xPendingSignals; - - /* Only interested in the resume signal. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - sigaddset( &xSignals, SIG_SUSPEND ); - - /* Unlock the Running thread mutex to allow the resumed task to continue. */ - if ( 0 != pthread_mutex_unlock( &xRunningThreadMutex ) ) - { - printf( "Releasing someone else's lock.\n" ); - } - - debug_printf("SUSPENDING until SIG_RESUME received\n"); - /* Wait on the resume signal. */ - while (hRequestedThread != pthread_self()) { - if ( 0 != sigwait( &xSignals, &sig ) ) - { - //printf( "SSH: Sw %d\n", sig ); - /* tricky one - shouldn't ever happen - trying to resolve situation as graceful as possible */ - debug_printf("ALERT AAAAH PANIC! - sigwait failed.....\n\n\n"); - /* Signal main thread something just went HORRIBLY wrong */ - xGeneralFuckedUpIndicator = 2; - sched_yield(); - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } else if (sig == SIG_RESUME) { - //debug_printf("received signal %i\n",sig); - /* Make sure the right thread received the signal */ - if (hRequestedThread != pthread_self() ) { - debug_printf( "ALERT! Received SIG_RESUME which is already outdated!\n active thread is %li\n",(long)hRequestedThread); - /* Signal main thread something just went wrong */ - xGeneralFuckedUpIndicator = 1; - /* - if (0 == sigpending(&xPendingSignals)) { - if (sigismember(&xPendingSignals,SIG_SUSPEND)) { - debug_printf( "reason: we slept too long...\n"); - //(void)sigwait(&xPendingSignals,&sig); - // we can safely return - signal is already pending - return; - } - } - debug_printf( "reason: unknown! - whatever ...\n\n"); - */ - //exit(1); - //(void)pthread_kill( xTaskToResume, SIG_RESUME ); - //(void)pthread_mutex_lock( &xRunningThreadMutex ); - //(void)pthread_kill( pthread_self(), SIG_SUSPEND ); - //return; - } - } - } - /* Yield the Scheduler to ensure that the yielding thread completes. */ - if ( 0 != pthread_mutex_lock( &xRunningThreadMutex ) ) - { - //(void)pthread_mutex_unlock( &xSingleThreadMutex ); - debug_printf("critical - mutex acquiring of active thread failed!\n"); - exit(1); - } - hActiveThread = pthread_self(); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - if (hRequestedThread==pthread_self()) { - /* doesn't look too bad, does it? */ - xGeneralFuckedUpIndicator = 0; - } - debug_printf("ACTIVE THREAD!\n"); -} -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself, sigresume, sigtick; -portLONG lIndex; - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigfillset( &sigsuspendself.sa_mask ); - - sigresume.sa_flags = 0; - //sigresume.sa_handler = prvResumeSignalHandler; - sigresume.sa_handler = SIG_IGN; - sigfillset( &sigresume.sa_mask ); - - sigtick.sa_flags = 0; - //sigtick.sa_handler = vPortSystemTickHandler; - sigtick.sa_handler = SIG_IGN; - sigfillset( &sigtick.sa_mask ); - - if ( 0 != sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ) - { - printf( "Problem installing SIG_SUSPEND_SELF\n" ); - } - //if ( 0 != sigaction( SIG_RESUME, &sigresume, NULL ) ) - //{ - // printf( "Problem installing SIG_RESUME\n" ); - //} - if ( 0 != sigaction( SIG_TICK, &sigtick, NULL ) ) - { - printf( "Problem installing SIG_TICK\n" ); - } - printf( "Running as PID: %d\n", getpid() ); -} -/*-----------------------------------------------------------*/ - -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ -pthread_t hThread = ( pthread_t )NULL; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - /* Needs to be reasonably high for accuracy. */ - unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ -/** - * Scheduler f***d up - we got to fix that - */ -void prvResolveFuckup( void ) -{ -struct timespec timeout; -pthread_t xTaskToResume; - - (void)pthread_mutex_lock ( &xSuspendResumeThreadMutex); - if (hActiveThread == hRequestedThread) { - debug_printf("emergency handler started - but not needed - returning\n"); - return; - } - printf("\nScheduler fucked up again - lets try to fix it...\n"); - if (hRequestedThread==0) { - printf("\nno supposedly active thread - fixing\n"); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - } else { - xTaskToResume = hRequestedThread; - } - printf("\nsending sig_suspend to thread that is supposed to be dead...\n"); - prvSuspendThread(hActiveThread); - printf("\nacquire running lock...\n"); - //timeout.tv_sec=0; - //timeout.tv_nsec=100; - sched_yield(); - while ( 0 != pthread_mutex_trylock( &xRunningThreadMutex) ) { - prvSuspendThread(hActiveThread); - timeout.tv_sec=0; - timeout.tv_nsec=1; - nanosleep(&timeout,NULL); - } - printf("\nsending sig_resume to thread that is supposed to be running...\n"); - prvResumeThread(xTaskToResume); - printf("\ngiving up mutex...\n"); - (void)pthread_mutex_unlock(&xRunningThreadMutex); - (void)pthread_mutex_unlock ( &xSuspendResumeThreadMutex); - -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/scheduler.txt b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/scheduler.txt deleted file mode 100644 index dc1815cea..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/scheduler.txt +++ /dev/null @@ -1,42 +0,0 @@ -thread initial START: - -master gives up running mutex -master waits for sentinel set -master akquires running mutex - -thread akquires RUNNING_MUTEX -threads sets sentinel -thread suspends itself - - - -thread SUSPEND: - -thread gives up RUNNING_MUTEX -thread waits for sig_resume -thread akquires RUNNING_MUTEX -thread runs - - -thread END: - -if other: -delete the other thread -if self: -thread gives up RUNNING_MUTEX -thread sends sig_resume to new active thread -thread self kills - - -thread YIELD -thread sends sig_resume to new active thread -thread suspends itself - - -time tick yield -tick handler sends SUSPEND to running thread -tick handler akquires RUNNING_MUTEX -tick handler sends sig_resume to new active thread -tock handler gives up RUNNING_MUTEX -tick handler ends - diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/tasks.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/tasks.c deleted file mode 100644 index 9b06c3f89..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/tasks.c +++ /dev/null @@ -1,2323 +0,0 @@ -/* - FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd. - - *************************************************************************** - * * - * If you are: * - * * - * + New to FreeRTOS, * - * + Wanting to learn FreeRTOS or multitasking in general quickly * - * + Looking for basic training, * - * + Wanting to improve your FreeRTOS skills and productivity * - * * - * then take a look at the FreeRTOS eBook * - * * - * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * - * http://www.FreeRTOS.org/Documentation * - * * - * A pdf reference manual is also available. Both are usually delivered * - * to your inbox within 20 minutes to two hours when purchased between 8am * - * and 8pm GMT (although please allow up to 24 hours in case of * - * exceptional circumstances). Thank you for your support! * - * * - *************************************************************************** - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - ***NOTE*** The exception to the GPL is included to allow you to distribute - a combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#include -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "StackMacros.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* - * Macro to define the amount of stack available to the idle task. - */ -#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE - -/* - * Task control block. A task control block (TCB) is allocated to each task, - * and stores the context of the task. - */ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ - #endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - - #if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ - #endif - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ - #endif - - #if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ - #endif - -} tskTCB; - - -/* - * Some kernel aware debuggers require data to be viewed to be global, rather - * than file scope. - */ -#ifdef portREMOVE_STATIC_QUALIFIER - #define static -#endif - -/*lint -e956 */ -PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; - -/* Lists for ready and blocked tasks. --------------------*/ - -PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */ -PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */ - -#if ( INCLUDE_vTaskDelete == 1 ) - - PRIVILEGED_DATA static volatile xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ - PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0; - -#endif - -#if ( INCLUDE_vTaskSuspend == 1 ) - - PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ - -#endif - -/* File private variables. --------------------------------*/ -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0; -PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0; -PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0; - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - PRIVILEGED_DATA static char pcStatsString[ 50 ] ; - PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION; - -#endif - -/* Debugging and trace facilities private variables and macros. ------------*/ - -/* - * The value used to fill the stack of a task when the task is created. This - * is used purely for checking the high water mark for tasks. - */ -#define tskSTACK_FILL_BYTE ( 0xa5 ) - -/* - * Macros used by vListTask to indicate which state a task is in. - */ -#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) -#define tskREADY_CHAR ( ( signed char ) 'R' ) -#define tskDELETED_CHAR ( ( signed char ) 'D' ) -#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) - -/* - * Macros and private variables used by the trace facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) ) - PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer; - PRIVILEGED_DATA static signed char *pcTraceBufferStart; - PRIVILEGED_DATA static signed char *pcTraceBufferEnd; - PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE; - static unsigned portBASE_TYPE uxPreviousTask = 255; - PRIVILEGED_DATA static char pcStatusString[ 50 ]; - -#endif - -/*-----------------------------------------------------------*/ - -/* - * Macro that writes a trace of scheduler activity to a buffer. This trace - * shows which task is running when and is very useful as a debugging tool. - * As this macro is called each context switch it is a good idea to undefine - * it if not using the facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define vWriteTraceToBuffer() \ - { \ - if( xTracing ) \ - { \ - if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ - { \ - if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ - { \ - uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \ - pcTraceBuffer += sizeof( unsigned long ); \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \ - pcTraceBuffer += sizeof( unsigned long ); \ - } \ - else \ - { \ - xTracing = pdFALSE; \ - } \ - } \ - } \ - } - -#else - - #define vWriteTraceToBuffer() - -#endif -/*-----------------------------------------------------------*/ - -/* - * Place the task represented by pxTCB into the appropriate ready queue for - * the task. It is inserted at the end of the list. One quirk of this is - * that if the task being inserted is at the same priority as the currently - * executing task, then it will only be rescheduled after the currently - * executing task has been rescheduled. - */ -#define prvAddTaskToReadyQueue( pxTCB ) \ -{ \ - if( pxTCB->uxPriority > uxTopReadyPriority ) \ - { \ - uxTopReadyPriority = pxTCB->uxPriority; \ - } \ - vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \ -} -/*-----------------------------------------------------------*/ - -/* - * Macro that looks at the list of tasks that are currently delayed to see if - * any require waking. - * - * Tasks are stored in the queue in the order of their wake time - meaning - * once one tasks has been found whose timer has not expired we need not look - * any further down the list. - */ -#define prvCheckDelayedTasks() \ -{ \ -register tskTCB *pxTCB; \ - \ - while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ - { \ - if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ - { \ - break; \ - } \ - vListRemove( &( pxTCB->xGenericListItem ) ); \ - /* Is the task waiting on an event also? */ \ - if( pxTCB->xEventListItem.pvContainer ) \ - { \ - vListRemove( &( pxTCB->xEventListItem ) ); \ - } \ - prvAddTaskToReadyQueue( pxTCB ); \ - } \ -} -/*-----------------------------------------------------------*/ - -/* - * Several functions take an xTaskHandle parameter that can optionally be NULL, - * where NULL is used to indicate that the handle of the currently executing - * task should be used in place of the parameter. This macro simply checks to - * see if the parameter is NULL and returns a pointer to the appropriate TCB. - */ -#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle ) - - -/* File private functions. --------------------------------*/ - -/* - * Utility to ready a TCB for a given task. Mainly just copies the parameters - * into the TCB structure. - */ -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; - -/* - * Utility to ready all the lists used by the scheduler. This is called - * automatically upon the creation of the first task. - */ -static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; - -/* - * The idle task, which as all tasks is implemented as a never ending loop. - * The idle task is automatically created and added to the ready lists upon - * creation of the first user task. - * - * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); - -/* - * Utility to free all memory allocated by the scheduler to hold a TCB, - * including the stack pointed to by the TCB. - * - * This does not free memory allocated by the task itself (i.e. memory - * allocated by calls to pvPortMalloc from within the tasks application code). - */ -#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) - - static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; - -#endif - -/* - * Used only by the idle task. This checks to see if anything has been placed - * in the list of tasks waiting to be deleted. If so the task is cleaned up - * and its TCB deleted. - */ -static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; - -/* - * Allocates memory from the heap for a TCB and associated stack. Checks the - * allocation was successful. - */ -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; - -/* - * Called from vTaskList. vListTasks details all the tasks currently under - * control of the scheduler. The tasks may be in one of a number of lists. - * prvListTaskWithinSingleList accepts a list and details the tasks from - * within just that list. - * - * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM - * NORMAL APPLICATION CODE. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION; - -#endif - -/* - * When a task is created, the stack of the task is filled with a known value. - * This function determines the 'high water mark' of the task stack by - * determining how much of the stack remains at the original preset value. - */ -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - - static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; - -#endif - - -/*lint +e956 */ - - - -/*----------------------------------------------------------- - * TASK CREATION API documented in task.h - *----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) -{ -signed portBASE_TYPE xReturn; -tskTCB * pxNewTCB; - - /* Allocate the memory required by the TCB and stack for the new task, - checking that the allocation was successful. */ - pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); - - if( pxNewTCB != NULL ) - { - portSTACK_TYPE *pxTopOfStack; - - #if( portUSING_MPU_WRAPPERS == 1 ) - /* Should the task be created in privileged mode? */ - portBASE_TYPE xRunPrivileged; - if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 ) - { - xRunPrivileged = pdTRUE; - } - else - { - xRunPrivileged = pdFALSE; - } - uxPriority &= ~portPRIVILEGE_BIT; - #endif /* portUSING_MPU_WRAPPERS == 1 */ - - /* Calculate the top of stack address. This depends on whether the - stack grows from high memory to low (as per the 80x86) or visa versa. - portSTACK_GROWTH is used to make the result positive or negative as - required by the port. */ - #if( portSTACK_GROWTH < 0 ) - { - pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); - pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) ); - } - #else - { - pxTopOfStack = pxNewTCB->pxStack; - - /* If we want to use stack checking on architectures that use - a positive stack growth direction then we also need to store the - other extreme of the stack space. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); - } - #endif - - /* Setup the newly allocated TCB with the initial state of the task. */ - prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); - - /* Initialize the TCB stack to look as if the task was already running, - but had been interrupted by the scheduler. The return address is set - to the start of the task function. Once the stack has been initialised - the top of stack variable is updated. */ - #if( portUSING_MPU_WRAPPERS == 1 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #else - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); - } - #endif - - /* We are going to manipulate the task queues to add this task to a - ready list, so must make sure no interrupts occur. */ - portENTER_CRITICAL(); - { - uxCurrentNumberOfTasks++; - if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) - { - /* As this is the first task it must also be the current task. */ - pxCurrentTCB = pxNewTCB; - - /* This is the first task to be created so do the preliminary - initialisation required. We will not recover if this call - fails, but we will report the failure. */ - prvInitialiseTaskLists(); - } - else - { - /* If the scheduler is not already running, make this task the - current task if it is the highest priority task to be created - so far. */ - if( xSchedulerRunning == pdFALSE ) - { - if( pxCurrentTCB->uxPriority <= uxPriority ) - { - pxCurrentTCB = pxNewTCB; - } - } - } - - /* Remember the top priority to make context switching faster. Use - the priority in pxNewTCB as this has been capped to a valid value. */ - if( pxNewTCB->uxPriority > uxTopUsedPriority ) - { - uxTopUsedPriority = pxNewTCB->uxPriority; - } - - #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; - } - #endif - uxTaskNumber++; - - prvAddTaskToReadyQueue( pxNewTCB ); - - xReturn = pdPASS; - traceTASK_CREATE( pxNewTCB ); - } - portEXIT_CRITICAL(); - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - traceTASK_CREATE_FAILED( pxNewTCB ); - } - - if( xReturn == pdPASS ) - { - if( ( void * ) pxCreatedTask != NULL ) - { - /* Pass the TCB out - in an anonymous way. The calling function/ - task can use this as a handle to delete the task later if - required.*/ - *pxCreatedTask = ( xTaskHandle ) pxNewTCB; - } - - if( xSchedulerRunning != pdFALSE ) - { - /* If the created task is of a higher priority than the current task - then it should run now. */ - if( pxCurrentTCB->uxPriority < uxPriority ) - { - portYIELD_WITHIN_API(); - } - } - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelete == 1 ) - - void vTaskDelete( xTaskHandle pxTaskToDelete ) - { - tskTCB *pxTCB; - - portENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - deleted. */ - if( pxTaskToDelete == pxCurrentTCB ) - { - pxTaskToDelete = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); - - /* Remove task from the ready list and place in the termination list. - This will stop the task from be scheduled. The idle task will check - the termination list and free up any memory allocated by the - scheduler for the TCB and stack. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); - - /* Increment the ucTasksDeleted variable so the idle task knows - there is a task that has been deleted and that it should therefore - check the xTasksWaitingTermination list. */ - ++uxTasksDeleted; - - /* Increment the uxTaskNumberVariable also so kernel aware debuggers - can detect that the task lists need re-generating. */ - uxTaskNumber++; - - traceTASK_DELETE( pxTCB ); - } - portEXIT_CRITICAL(); - - /* Force a reschedule if we have just deleted the current task. */ - if( xSchedulerRunning != pdFALSE ) - { - if( ( void * ) pxTaskToDelete == NULL ) - { - portYIELD_WITHIN_API(); - } - } - } - -#endif - - - - - - -/*----------------------------------------------------------- - * TASK CONTROL API documented in task.h - *----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelayUntil == 1 ) - - void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) - { - portTickType xTimeToWake; - portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; - - vTaskSuspendAll(); - { - /* Generate the tick time at which the task wants to wake. */ - xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; - - if( xTickCount < *pxPreviousWakeTime ) - { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) ) - { - xShouldDelay = pdTRUE; - } - } - else - { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) ) - { - xShouldDelay = pdTRUE; - } - } - - /* Update the wake time ready for the next call. */ - *pxPreviousWakeTime = xTimeToWake; - - if( xShouldDelay ) - { - traceTASK_DELAY_UNTIL(); - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the - overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - } - xAlreadyYielded = xTaskResumeAll(); - - /* Force a reschedule if xTaskResumeAll has not already done so, we may - have put ourselves to sleep. */ - if( !xAlreadyYielded ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelay == 1 ) - - void vTaskDelay( portTickType xTicksToDelay ) - { - portTickType xTimeToWake; - signed portBASE_TYPE xAlreadyYielded = pdFALSE; - - /* A delay time of zero just forces a reschedule. */ - if( xTicksToDelay > ( portTickType ) 0 ) - { - vTaskSuspendAll(); - { - traceTASK_DELAY(); - - /* A task that is removed from the event list while the - scheduler is suspended will not get placed in the ready - list or removed from the blocked list until the scheduler - is resumed. - - This task cannot be in an event list as it is the currently - executing task. */ - - /* Calculate the time to wake - this may overflow but this is - not a problem. */ - xTimeToWake = xTickCount + xTicksToDelay; - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the - overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - xAlreadyYielded = xTaskResumeAll(); - } - - /* Force a reschedule if xTaskResumeAll has not already done so, we may - have put ourselves to sleep. */ - if( !xAlreadyYielded ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_uxTaskPriorityGet == 1 ) - - unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) - { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxReturn; - - portENTER_CRITICAL(); - { - /* If null is passed in here then we are changing the - priority of the calling function. */ - pxTCB = prvGetTCBFromHandle( pxTask ); - uxReturn = pxTCB->uxPriority; - } - portEXIT_CRITICAL(); - - return uxReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskPrioritySet == 1 ) - - void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) - { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE; - - /* Ensure the new priority is valid. */ - if( uxNewPriority >= configMAX_PRIORITIES ) - { - uxNewPriority = configMAX_PRIORITIES - 1; - } - - portENTER_CRITICAL(); - { - if( pxTask == pxCurrentTCB ) - { - pxTask = NULL; - } - - /* If null is passed in here then we are changing the - priority of the calling function. */ - pxTCB = prvGetTCBFromHandle( pxTask ); - - traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); - - #if ( configUSE_MUTEXES == 1 ) - { - uxCurrentPriority = pxTCB->uxBasePriority; - } - #else - { - uxCurrentPriority = pxTCB->uxPriority; - } - #endif - - if( uxCurrentPriority != uxNewPriority ) - { - /* The priority change may have readied a task of higher - priority than the calling task. */ - if( uxNewPriority > uxCurrentPriority ) - { - if( pxTask != NULL ) - { - /* The priority of another task is being raised. If we - were raising the priority of the currently running task - there would be no need to switch as it must have already - been the highest priority task. */ - xYieldRequired = pdTRUE; - } - } - else if( pxTask == NULL ) - { - /* Setting our own priority down means there may now be another - task of higher priority that is ready to execute. */ - xYieldRequired = pdTRUE; - } - - - - #if ( configUSE_MUTEXES == 1 ) - { - /* Only change the priority being used if the task is not - currently using an inherited priority. */ - if( pxTCB->uxBasePriority == pxTCB->uxPriority ) - { - pxTCB->uxPriority = uxNewPriority; - } - - /* The base priority gets set whatever. */ - pxTCB->uxBasePriority = uxNewPriority; - } - #else - { - pxTCB->uxPriority = uxNewPriority; - } - #endif - - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); - - /* If the task is in the blocked or suspended list we need do - nothing more than change it's priority variable. However, if - the task is in a ready list it needs to be removed and placed - in the queue appropriate to its new priority. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) - { - /* The task is currently in its ready list - remove before adding - it to it's new ready list. As we are in a critical section we - can do this even if the scheduler is suspended. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - - if( xYieldRequired == pdTRUE ) - { - portYIELD_WITHIN_API(); - } - } - } - portEXIT_CRITICAL(); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - void vTaskSuspend( xTaskHandle pxTaskToSuspend ) - { - tskTCB *pxTCB; - - portENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - suspended. */ - if( pxTaskToSuspend == pxCurrentTCB ) - { - pxTaskToSuspend = NULL; - } - - /* If null is passed in here then we are suspending ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToSuspend ); - - traceTASK_SUSPEND( pxTCB ); - - /* Remove task from the ready/delayed list and place in the suspended list. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); - } - portEXIT_CRITICAL(); - - /* We may have just suspended the current task. */ - if( ( void * ) pxTaskToSuspend == NULL ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) - { - portBASE_TYPE xReturn = pdFALSE; - const tskTCB * const pxTCB = ( tskTCB * ) xTask; - - /* Is the task we are attempting to resume actually in the - suspended list? */ - if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) - { - /* Has the task already been resumed from within an ISR? */ - if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE ) - { - /* Is it in the suspended list because it is in the - Suspended state? It is possible to be in the suspended - list because it is blocked on a task with no timeout - specified. */ - if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE ) - { - xReturn = pdTRUE; - } - } - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - void vTaskResume( xTaskHandle pxTaskToResume ) - { - tskTCB *pxTCB; - - /* Remove the task from whichever list it is currently in, and place - it in the ready list. */ - pxTCB = ( tskTCB * ) pxTaskToResume; - - /* The parameter cannot be NULL as it is impossible to resume the - currently executing task. */ - if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) - { - portENTER_CRITICAL(); - { - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) - { - traceTASK_RESUME( pxTCB ); - - /* As we are in a critical section we can access the ready - lists even if the scheduler is suspended. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - - /* We may have just resumed a higher priority task. */ - if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - /* This yield may not cause the task just resumed to run, but - will leave the lists in the correct state for the next yield. */ - portYIELD_WITHIN_API(); - } - } - } - portEXIT_CRITICAL(); - } - } - -#endif - -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - - portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) - { - portBASE_TYPE xYieldRequired = pdFALSE; - tskTCB *pxTCB; - - pxTCB = ( tskTCB * ) pxTaskToResume; - - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - else - { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed, at which point a - yield will be performed if necessary. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); - } - } - - return xYieldRequired; - } - -#endif - - - - -/*----------------------------------------------------------- - * PUBLIC SCHEDULER CONTROL documented in task.h - *----------------------------------------------------------*/ - - -void vTaskStartScheduler( void ) -{ -portBASE_TYPE xReturn; - - /* Add the idle task at the lowest priority. */ - xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL ); - - if( xReturn == pdPASS ) - { - /* Interrupts are turned off here, to ensure a tick does not occur - before or during the call to xPortStartScheduler(). The stacks of - the created tasks contain a status word with interrupts switched on - so interrupts will automatically get re-enabled when the first task - starts to run. - - STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE - DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ - portDISABLE_INTERRUPTS(); - - xSchedulerRunning = pdTRUE; - xTickCount = ( portTickType ) 0; - - /* If configGENERATE_RUN_TIME_STATS is defined then the following - macro must be defined to configure the timer/counter used to generate - the run time counter time base. */ - portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); - - /* Setting up the timer tick is hardware specific and thus in the - portable interface. */ - if( xPortStartScheduler() ) - { - /* Should not reach here as if the scheduler is running the - function will not return. */ - } - else - { - /* Should only reach here if a task calls xTaskEndScheduler(). */ - } - } -} -/*-----------------------------------------------------------*/ - -void vTaskEndScheduler( void ) -{ - /* Stop the scheduler interrupts and call the portable scheduler end - routine so the original ISRs can be restored if necessary. The port - layer must ensure interrupts enable bit is left in the correct state. */ - portDISABLE_INTERRUPTS(); - xSchedulerRunning = pdFALSE; - vPortEndScheduler(); -} -/*----------------------------------------------------------*/ - -void vTaskSuspendAll( void ) -{ - /* A critical section is not required as the variable is of type - portBASE_TYPE. */ - ++uxSchedulerSuspended; -} -/*----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskResumeAll( void ) -{ -register tskTCB *pxTCB; -signed portBASE_TYPE xAlreadyYielded = pdFALSE; - - /* It is possible that an ISR caused a task to be removed from an event - list while the scheduler was suspended. If this was the case then the - removed task will have been added to the xPendingReadyList. Once the - scheduler has been resumed it is safe to move all the pending ready - tasks from this list into their appropriate ready list. */ - portENTER_CRITICAL(); - { - --uxSchedulerSuspended; - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 ) - { - portBASE_TYPE xYieldRequired = pdFALSE; - - /* Move any readied tasks from the pending list into the - appropriate ready list. */ - while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - - /* If we have moved a task that has a priority higher than - the current task then we should yield. */ - if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - xYieldRequired = pdTRUE; - } - } - - /* If any ticks occurred while the scheduler was suspended then - they should be processed now. This ensures the tick count does not - slip, and that any delayed tasks are resumed at the correct time. */ - if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 ) - { - while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 ) - { - vTaskIncrementTick(); - --uxMissedTicks; - } - - /* As we have processed some ticks it is appropriate to yield - to ensure the highest priority task that is ready to run is - the task actually running. */ - #if configUSE_PREEMPTION == 1 - { - xYieldRequired = pdTRUE; - } - #endif - } - - if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) ) - { - xAlreadyYielded = pdTRUE; - xMissedYield = pdFALSE; - portYIELD_WITHIN_API(); - } - } - } - } - portEXIT_CRITICAL(); - - return xAlreadyYielded; -} - - - - - - -/*----------------------------------------------------------- - * PUBLIC TASK UTILITIES documented in task.h - *----------------------------------------------------------*/ - - - -portTickType xTaskGetTickCount( void ) -{ -portTickType xTicks; - - /* Critical section required if running on a 16 bit processor. */ - portENTER_CRITICAL(); - { - xTicks = xTickCount; - } - portEXIT_CRITICAL(); - - return xTicks; -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) -{ - /* A critical section is not required because the variables are of type - portBASE_TYPE. */ - return uxCurrentNumberOfTasks; -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskList( signed char *pcWriteBuffer ) - { - unsigned portBASE_TYPE uxQueue; - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - /* Run through all the lists that could potentially contain a TCB and - report the task name, state and stack high water mark. */ - - pcWriteBuffer[ 0 ] = ( signed char ) 0x00; - strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); - - uxQueue = uxTopUsedPriority + 1; - - do - { - uxQueue--; - - if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( !listLIST_IS_EMPTY( pxDelayedTaskList ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); - } - - if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); - } - - #if( INCLUDE_vTaskDelete == 1 ) - { - if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR ); - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR ); - } - } - #endif - } - xTaskResumeAll(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) - { - unsigned portBASE_TYPE uxQueue; - unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - /* Run through all the lists that could potentially contain a TCB, - generating a table of run timer percentages in the provided - buffer. */ - - pcWriteBuffer[ 0 ] = ( signed char ) 0x00; - strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); - - uxQueue = uxTopUsedPriority + 1; - - do - { - uxQueue--; - - if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime ); - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( !listLIST_IS_EMPTY( pxDelayedTaskList ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime ); - } - - if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime ); - } - - #if ( INCLUDE_vTaskDelete == 1 ) - { - if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime ); - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime ); - } - } - #endif - } - xTaskResumeAll(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) - { - portENTER_CRITICAL(); - { - pcTraceBuffer = ( signed char * )pcBuffer; - pcTraceBufferStart = pcBuffer; - pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE ); - xTracing = pdTRUE; - } - portEXIT_CRITICAL(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - unsigned long ulTaskEndTrace( void ) - { - unsigned long ulBufferLength; - - portENTER_CRITICAL(); - xTracing = pdFALSE; - portEXIT_CRITICAL(); - - ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart ); - - return ulBufferLength; - } - -#endif - - - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - * documented in task.h - *----------------------------------------------------------*/ - - -void vTaskIncrementTick( void ) -{ - /* Called by the portable layer each time a tick interrupt occurs. - Increments the tick then checks to see if the new tick value will cause any - tasks to be unblocked. */ - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - ++xTickCount; - if( xTickCount == ( portTickType ) 0 ) - { - xList *pxTemp; - - /* Tick count has overflowed so we need to swap the delay lists. - If there are any items in pxDelayedTaskList here then there is - an error! */ - pxTemp = pxDelayedTaskList; - pxDelayedTaskList = pxOverflowDelayedTaskList; - pxOverflowDelayedTaskList = pxTemp; - xNumOfOverflows++; - } - - /* See if this tick has made a timeout expire. */ - prvCheckDelayedTasks(); - } - else - { - ++uxMissedTicks; - - /* The tick hook gets called at regular intervals, even if the - scheduler is locked. */ - #if ( configUSE_TICK_HOOK == 1 ) - { - extern void vApplicationTickHook( void ); - - vApplicationTickHook(); - } - #endif - } - - #if ( configUSE_TICK_HOOK == 1 ) - { - extern void vApplicationTickHook( void ); - - /* Guard against the tick hook being called when the missed tick - count is being unwound (when the scheduler is being unlocked. */ - if( uxMissedTicks == 0 ) - { - vApplicationTickHook(); - } - } - #endif - - traceTASK_INCREMENT_TICK( xTickCount ); -} -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - - void vTaskCleanUpResources( void ) - { - unsigned short usQueue; - volatile tskTCB *pxTCB; - - usQueue = ( unsigned short ) uxTopUsedPriority + ( unsigned short ) 1; - - /* Remove any TCB's from the ready queues. */ - do - { - usQueue--; - - while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - }while( usQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - /* Remove any TCB's from the delayed queue. */ - while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - - /* Remove any TCB's from the overflow delayed queue. */ - while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - - while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue ) - { - tskTCB *xTCB; - - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - portENTER_CRITICAL(); - xTCB->pxTaskTag = pxTagValue; - portEXIT_CRITICAL(); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) - { - tskTCB *xTCB; - pdTASK_HOOK_CODE xReturn; - - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - portENTER_CRITICAL(); - xReturn = xTCB->pxTaskTag; - portEXIT_CRITICAL(); - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) - { - tskTCB *xTCB; - portBASE_TYPE xReturn; - - /* If xTask is NULL then we are calling our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - if( xTCB->pxTaskTag != NULL ) - { - xReturn = xTCB->pxTaskTag( pvParameter ); - } - else - { - xReturn = pdFAIL; - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -void vTaskSwitchContext( void ) -{ - if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) - { - /* The scheduler is currently suspended - do not allow a context - switch. */ - xMissedYield = pdTRUE; - return; - } - - traceTASK_SWITCHED_OUT(); - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); - - /* Add the amount of time the task has been running to the accumulated - time so far. The time the task started running was stored in - ulTaskSwitchedInTime. Note that there is no overflow protection here - so count values are only valid until the timer overflows. Generally - this will be about 1 hour assuming a 1uS timer increment. */ - pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); - ulTaskSwitchedInTime = ulTempCounter; - } - #endif - - taskFIRST_CHECK_FOR_STACK_OVERFLOW(); - taskSECOND_CHECK_FOR_STACK_OVERFLOW(); - - /* Find the highest priority queue that contains ready tasks. */ - while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) - { - --uxTopReadyPriority; - } - - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the - same priority get an equal share of the processor time. */ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); - - traceTASK_SWITCHED_IN(); - vWriteTraceToBuffer(); -} -/*-----------------------------------------------------------*/ - -void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) -{ -portTickType xTimeToWake; - - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. */ - - /* Place the event list item of the TCB in the appropriate event list. - This is placed in the list in priority order so the highest priority task - is the first to be woken by the event. */ - vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); - - /* We must remove ourselves from the ready list before adding ourselves - to the blocked list as the same list item is used for both lists. We have - exclusive access to the ready lists as the scheduler is locked. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add ourselves to the suspended task list instead of a delayed task - list to ensure we are not woken by a timing event. We will block - indefinitely. */ - vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - } - #else - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - #endif -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) -{ -tskTCB *pxUnblockedTCB; -portBASE_TYPE xReturn; - - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. It can also be called from within an ISR. */ - - /* The event list is sorted in priority order, so we can remove the - first in the list, remove the TCB from the delayed list, and add - it to the ready list. - - If an event is for a queue that is locked then this function will never - get called - the lock count on the queue will get modified instead. This - means we can always expect exclusive access to the event list here. */ - pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); - vListRemove( &( pxUnblockedTCB->xEventListItem ) ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - vListRemove( &( pxUnblockedTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxUnblockedTCB ); - } - else - { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); - } - - if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - /* Return true if the task removed from the event list has - a higher priority than the calling task. This allows - the calling task to know if it should force a context - switch now. */ - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) -{ - pxTimeOut->xOverflowCount = xNumOfOverflows; - pxTimeOut->xTimeOnEntering = xTickCount; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) -{ -portBASE_TYPE xReturn; - - portENTER_CRITICAL(); - { - #if ( INCLUDE_vTaskSuspend == 1 ) - /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is - the maximum block time then the task should block indefinitely, and - therefore never time out. */ - if( *pxTicksToWait == portMAX_DELAY ) - { - xReturn = pdFALSE; - } - else /* We are not blocking indefinitely, perform the checks below. */ - #endif - - if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) ) - { - /* The tick count is greater than the time at which vTaskSetTimeout() - was called, but has also overflowed since vTaskSetTimeOut() was called. - It must have wrapped all the way around and gone past us again. This - passed since vTaskSetTimeout() was called. */ - xReturn = pdTRUE; - } - else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait ) - { - /* Not a genuine timeout. Adjust parameters for time remaining. */ - *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ); - vTaskSetTimeOutState( pxTimeOut ); - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - } - portEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskMissedYield( void ) -{ - xMissedYield = pdTRUE; -} - -/* - * ----------------------------------------------------------- - * The Idle task. - * ---------------------------------------------------------- - * - * The portTASK_FUNCTION() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION( prvIdleTask, pvParameters ) -{ - /* Stop warnings. */ - ( void ) pvParameters; - - for( ;; ) - { - /* See if any tasks have been deleted. */ - prvCheckTasksWaitingTermination(); - - #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - see if any other task has become available. If we are using - preemption we don't need to do this as any task becoming available - will automatically get the processor anyway. */ - taskYIELD(); - } - #endif - - #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) - { - /* When using preemption tasks of equal priority will be - timesliced. If a task that is sharing the idle priority is ready - to run then the idle task should yield before the end of the - timeslice. - - A critical region is not required here as we are just reading from - the list, and an occasional incorrect value will not matter. If - the ready list at the idle priority contains more than one task - then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) - { - taskYIELD(); - } - } - #endif - - #if ( configUSE_IDLE_HOOK == 1 ) - { - extern void vApplicationIdleHook( void ); - - /* Call the user defined function from within the idle task. This - allows the application designer to add background functionality - without the overhead of a separate task. - NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationIdleHook(); - } - #endif - // call nanosleep for smalles sleep time possible - // (depending on kernel settings - around 100 microseconds) - // decreases idle thread CPU load from 100 to practically 0 - struct timespec x; - x.tv_sec=1; - x.tv_nsec=0; - nanosleep(&x,NULL); - } -} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */ - - - - - - - -/*----------------------------------------------------------- - * File private functions documented at the top of the file. - *----------------------------------------------------------*/ - - - -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) -{ - /* Store the function name in the TCB. */ - #if configMAX_TASK_NAME_LEN > 1 - { - /* Don't bring strncpy into the build unnecessarily. */ - strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN ); - } - #endif - pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = '\0'; - - /* This is used as an array index so must ensure it's not too large. First - remove the privilege bit if one is present. */ - if( uxPriority >= configMAX_PRIORITIES ) - { - uxPriority = configMAX_PRIORITIES - 1; - } - - pxTCB->uxPriority = uxPriority; - #if ( configUSE_MUTEXES == 1 ) - { - pxTCB->uxBasePriority = uxPriority; - } - #endif - - vListInitialiseItem( &( pxTCB->xGenericListItem ) ); - vListInitialiseItem( &( pxTCB->xEventListItem ) ); - - /* Set the pxTCB as a link back from the xListItem. This is so we can get - back to the containing TCB from a generic item in a list. */ - listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); - - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); - listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - { - pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0; - } - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - { - pxTCB->pxTaskTag = NULL; - } - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxTCB->ulRunTimeCounter = 0UL; - } - #endif - - #if ( portUSING_MPU_WRAPPERS == 1 ) - { - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); - } - #else - { - ( void ) xRegions; - ( void ) usStackDepth; - } - #endif -} -/*-----------------------------------------------------------*/ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - - void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) - { - tskTCB *pxTCB; - - if( xTaskToModify == pxCurrentTCB ) - { - xTaskToModify = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( xTaskToModify ); - - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); - } - /*-----------------------------------------------------------*/ -#endif - -static void prvInitialiseTaskLists( void ) -{ -unsigned portBASE_TYPE uxPriority; - - for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ ) - { - vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) ); - } - - vListInitialise( ( xList * ) &xDelayedTaskList1 ); - vListInitialise( ( xList * ) &xDelayedTaskList2 ); - vListInitialise( ( xList * ) &xPendingReadyList ); - - #if ( INCLUDE_vTaskDelete == 1 ) - { - vListInitialise( ( xList * ) &xTasksWaitingTermination ); - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - vListInitialise( ( xList * ) &xSuspendedTaskList ); - } - #endif - - /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList - using list2. */ - pxDelayedTaskList = &xDelayedTaskList1; - pxOverflowDelayedTaskList = &xDelayedTaskList2; -} -/*-----------------------------------------------------------*/ - -static void prvCheckTasksWaitingTermination( void ) -{ - #if ( INCLUDE_vTaskDelete == 1 ) - { - portBASE_TYPE xListIsEmpty; - - /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called - too often in the idle task. */ - if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 ) - { - vTaskSuspendAll(); - xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); - xTaskResumeAll(); - - if( !xListIsEmpty ) - { - tskTCB *pxTCB; - - portENTER_CRITICAL(); - { - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) ); - vListRemove( &( pxTCB->xGenericListItem ) ); - --uxCurrentNumberOfTasks; - --uxTasksDeleted; - } - portEXIT_CRITICAL(); - - prvDeleteTCB( pxTCB ); - } - } - } - #endif -} -/*-----------------------------------------------------------*/ - -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) -{ -tskTCB *pxNewTCB; - - /* Allocate space for the TCB. Where the memory comes from depends on - the implementation of the port malloc function. */ - pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); - - if( pxNewTCB != NULL ) - { - /* Allocate space for the stack used by the task being created. - The base of the stack memory stored in the TCB so the task can - be deleted later if required. */ - pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); - - if( pxNewTCB->pxStack == NULL ) - { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; - } - else - { - /* Just to help debugging. */ - memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) ); - } - } - - return pxNewTCB; -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) - { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned short usStackRemaining; - - /* Write the details of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - #if ( portSTACK_GROWTH > 0 ) - { - usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); - } - #else - { - usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); - } - #endif - - sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber ); - strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString ); - - } while( pxNextTCB != pxFirstTCB ); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) - { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned long ulStatsAsPercentage; - - /* Write the run time stats of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - /* Get next TCB in from the list. */ - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - - /* Divide by zero check. */ - if( ulTotalRunTime > 0UL ) - { - /* Has the task run at all? */ - if( pxNextTCB->ulRunTimeCounter == 0 ) - { - /* The task has used no CPU time at all. */ - sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName ); - } - else - { - /* What percentage of the total run time as the task used? - This will always be rounded down to the nearest integer. */ - ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime; - - if( ulStatsAsPercentage > 0UL ) - { - sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); - } - else - { - /* If the percentage is zero here then the task has - consumed less than 1% of the total run time. */ - sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter ); - } - } - - strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString ); - } - - } while( pxNextTCB != pxFirstTCB ); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - - static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) - { - register unsigned short usCount = 0; - - while( *pucStackByte == tskSTACK_FILL_BYTE ) - { - pucStackByte -= portSTACK_GROWTH; - usCount++; - } - - usCount /= sizeof( portSTACK_TYPE ); - - return usCount; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - - unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) - { - tskTCB *pxTCB; - unsigned char *pcEndOfStack; - unsigned portBASE_TYPE uxReturn; - - pxTCB = prvGetTCBFromHandle( xTask ); - - #if portSTACK_GROWTH < 0 - { - pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; - } - #else - { - pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; - } - #endif - - uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack ); - - return uxReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) - - static void prvDeleteTCB( tskTCB *pxTCB ) - { - /* Free up the memory allocated by the scheduler for the task. It is up to - the task to free any memory allocated at the application level. */ - vPortFreeAligned( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - -#endif - - -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) - - xTaskHandle xTaskGetCurrentTaskHandle( void ) - { - xTaskHandle xReturn; - - /* A critical section is not required as this is not called from - an interrupt and the current TCB will always be the same for any - individual execution thread. */ - xReturn = pxCurrentTCB; - - return xReturn; - } - -#endif - -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_xTaskGetSchedulerState == 1 ) - - portBASE_TYPE xTaskGetSchedulerState( void ) - { - portBASE_TYPE xReturn; - - if( xSchedulerRunning == pdFALSE ) - { - xReturn = taskSCHEDULER_NOT_STARTED; - } - else - { - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_MUTEXES == 1 ) - - void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) - { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; - - if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) - { - /* Adjust the mutex holder state to account for its new priority. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); - - /* If the task being modified is in the ready state it will need to - be moved in to a new list. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) ) - { - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Inherit the priority before being moved into the new list. */ - pxTCB->uxPriority = pxCurrentTCB->uxPriority; - prvAddTaskToReadyQueue( pxTCB ); - } - else - { - /* Just inherit the priority. */ - pxTCB->uxPriority = pxCurrentTCB->uxPriority; - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_MUTEXES == 1 ) - - void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) - { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; - - if( pxMutexHolder != NULL ) - { - if( pxTCB->uxPriority != pxTCB->uxBasePriority ) - { - /* We must be the running task to be able to give the mutex back. - Remove ourselves from the ready list we currently appear in. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Disinherit the priority before adding ourselves into the new - ready list. */ - pxTCB->uxPriority = pxTCB->uxBasePriority; - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); - prvAddTaskToReadyQueue( pxTCB ); - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - - void vTaskEnterCritical( void ) - { - portDISABLE_INTERRUPTS(); - - if( xSchedulerRunning != pdFALSE ) - { - pxCurrentTCB->uxCriticalNesting++; - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - -void vTaskExitCritical( void ) -{ - if( xSchedulerRunning != pdFALSE ) - { - if( pxCurrentTCB->uxCriticalNesting > 0 ) - { - pxCurrentTCB->uxCriticalNesting--; - - if( pxCurrentTCB->uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } - } - } -} - -#endif -/*-----------------------------------------------------------*/ - - - - diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_1_sleep.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_1_sleep.c deleted file mode 100644 index b173eb9bc..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_1_sleep.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - sleep(1); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_2_nanosleep.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_2_nanosleep.c deleted file mode 100644 index c01679a18..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_2_nanosleep.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { -struct timespec sleeptime; - - while (1) { - sleeptime.tv_sec=1; - sleeptime.tv_nsec=0; - nanosleep(&sleeptime,NULL); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_3_select.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_3_select.c deleted file mode 100644 index 9fc852774..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_3_select.c +++ /dev/null @@ -1,40 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { -struct timeval sleeptime; - - while (1) { - sleeptime.tv_sec=1; - sleeptime.tv_usec=0; - select(0,NULL,NULL,NULL,&sleeptime); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_4_mutex_lock.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_4_mutex_lock.c deleted file mode 100644 index d5bf3119f..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_4_mutex_lock.c +++ /dev/null @@ -1,41 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include - -static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; - -/** - * actual test program - */ - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - pthread_mutex_lock(&Mutex); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_mutex_lock(&Mutex); - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_5_pselect.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_5_pselect.c deleted file mode 100644 index a3d98b8bd..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_5_pselect.c +++ /dev/null @@ -1,42 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { -sigset_t sigset; -struct timespec sleeptime; - - while (1) { - sleeptime.tv_sec=1; - sleeptime.tv_nsec=0; - sigemptyset(&sigset); - pselect(0,NULL,NULL,NULL,&sleeptime,&sigset); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_6_sched_yield.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_6_sched_yield.c deleted file mode 100644 index 58fc902ea..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_6_sched_yield.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - sched_yield(); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_7_busy_waiting.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_7_busy_waiting.c deleted file mode 100644 index d3a808e61..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_7_busy_waiting.c +++ /dev/null @@ -1,34 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - - while (1) { - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_8_io.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_8_io.c deleted file mode 100644 index 3f21c3238..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/test_case_8_io.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * small test program whether signals between threads work as they should - */ - -#include -#include -#include - -void sighandler(int sig) { - write(2,".",1); - return; -} - -void* threadstart(void* arg) { - char buf[1024]; - - while (1) { - read(1,buf,512); - } -} - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test.c deleted file mode 100644 index 7a230399f..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test.c +++ /dev/null @@ -1,62 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include -#include -#include - -static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; - -void sighandler(int sig) { - printf("signal handler called in thread %li - signal %i\n",(long)pthread_self(),sig); -} - - -void* threadstart(void* arg) { -struct timespec timeout; -struct sigaction action; - printf("thread %li started\n",(long)pthread_self()); - - printf("installing signal handler\n"); - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - printf("getting mutex\n"); - pthread_mutex_lock(&Mutex); - printf("got mutex\n"); - - - while (1) { - timeout.tv_sec=1; - timeout.tv_nsec=0; - nanosleep(&timeout,0); - printf("thread %li still running...\n",(long)pthread_self()); - } - -} - - -int main(char** argc, int argv) { - -pthread_t testthread1; -pthread_t testthread2; -printf("thread test program\n"); -sleep(5); -printf("starting thread 1\n"); -pthread_create(&testthread1,NULL,threadstart,NULL); -sleep(5); -printf("starting thread 2\n"); -pthread_create(&testthread2,NULL,threadstart,NULL); -while (1) { - sleep(5); - printf("sending SIG_USR1 to thread 1\n"); - pthread_kill(testthread1,SIGUSR1); - sleep(5); - printf("sending SIG_USR1 to thread 2\n"); - pthread_kill(testthread2,SIGUSR1); -} -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test2.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test2.c deleted file mode 100644 index d6df0a023..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test2.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include -#include -#include -#include - -static pthread_mutex_t Mutex = PTHREAD_MUTEX_INITIALIZER; - -/** - * printf is not thread safe - this little helper function allow debug output in thread safe context - */ -/* write a string to a filehandle */ -void print_char(int fh, char *c) { - int t=0; - while (c[t]!=0) t++; - write(fh,c,t); -} - -/* create a dezimal string from an integer */ -int int2char(char* x,unsigned long i) { - if (i==0) { - return 0; - } - int k=int2char(&x[0],i/10); - x[k]='0'+(i%10); - x[k+1]=0; - return k+1; -} -/* print a number*/ -void print_number(int fh, long i) { - char buffer[39]; // 39 characters are enough to store a 128 bit integer in dezimal notation (~~3.4* 10^38) - - if (i==0) { - print_char(fh,"0"); - } else { - if (i<0) { - buffer[0]='-'; - int2char(&buffer[1],-i); - } else { - int2char(buffer,i); - } - print_char(fh,buffer); - } -} - -/** - * actual test program - */ - -void sighandler(int sig) { - print_char(2,"signal handler called in thread "); - print_number(2,(long)pthread_self()); - print_char(2," - signal "); - print_number(2,sig); - print_char(2,"\n"); -} - - -void* threadstart(void* arg) { -struct timespec timeout; -int t; - print_char(2,"thread "); - print_number(2,(long)pthread_self()); - print_char(2," started \n"); - - while (1) { - print_char(2,"getting mutex\n"); - pthread_mutex_lock(&Mutex); - print_char(2,"got mutex\n"); - - - for (t=0;t<20;t++) { - timeout.tv_sec=1; - timeout.tv_nsec=0; - nanosleep(&timeout,0); - - print_char(2,"thread "); - print_number(2,(long)pthread_self()); - print_char(2," still running...\n"); - } - pthread_mutex_unlock(&Mutex); - sleep(1); - } -} - - -int main(char** argc, int argv) { - - pthread_t testthread1; - pthread_t testthread2; - struct sigaction action; - print_char(2,"thread test program\n\n"); - - print_char(2,"demonstrate print function\n"); - long t=1; - while (t!=0) { - print_number(2,t); - print_char(2," >> "); - t=(t>0)?t*2:t/2; - } - print_number(2,t); - print_char(2,"\ndone\n\n"); - - print_char(2,"installing signal handler\n"); - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - sleep(5); - print_char(2,"starting thread 1\n"); - pthread_create(&testthread1,NULL,threadstart,NULL); - sleep(5); - print_char(2,"starting thread 2\n"); - pthread_create(&testthread2,NULL,threadstart,NULL); - while (1) { - sleep(5); - print_char(2,"sending SIG_USR1 to thread 1\n"); - pthread_kill(testthread1,SIGUSR1); - sleep(5); - print_char(2,"sending SIG_USR1 to thread 2\n"); - pthread_kill(testthread2,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test3.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test3.c deleted file mode 100644 index 8e8c9dbf0..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/corvuscorax/thread_signal_test3.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * small etst program whether signals between threads work as they should - */ - -#include -#include -#include - - -/** - * actual test program - */ - -void sighandler(int sig) { - return; -} - - -void* threadstart(void* arg) { -struct timespec timeout; -int t; - - while (1) { - timeout.tv_sec=0; - timeout.tv_nsec=1; - nanosleep(&timeout,0); - } -} - - -int main(char** argc, int argv) { - - pthread_t testthread1; - struct sigaction action; - - - action.sa_handler=sighandler; - action.sa_flags=0; - sigfillset( &action.sa_mask ); - sigaction(SIGUSR1,&action,NULL); - - pthread_create(&testthread1,NULL,threadstart,NULL); - while (1) { - pthread_kill(testthread1,SIGUSR1); - } -} diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-pthread_cond.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-pthread_cond.c deleted file mode 100644 index 8eab3b367..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-pthread_cond.c +++ /dev/null @@ -1,1179 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -#ifdef __APPLE__ - #define COND_SIGNALING - #define CHECK_TASK_RESUMES - #define RUNNING_THREAD_MUTEX - #define TICK_SIGNAL -#endif -#ifdef __CYGWIN__ - #define COND_SIGNALING - #define CHECK_TASK_RESUMES -#endif -#ifdef __linux__ - #define COND_SIGNALING -// #define CHECK_TASK_RESUMES - #define RUNNING_THREAD_MUTEX - #define TICK_SIGNAL -#endif - - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - pthread_cond_t * hCond; - pthread_mutex_t * hMutex; - xTaskHandle hTask; - portBASE_TYPE xThreadState; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -#ifdef RUNNING_THREAD_MUTEX -static pthread_mutex_t xRunningThread = PTHREAD_MUTEX_INITIALIZER; -#endif -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSwappingThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xRunning = pdFALSE; -static volatile portBASE_TYPE xSuspended = pdFALSE; -static volatile portBASE_TYPE xStarted = pdFALSE; -static volatile portBASE_TYPE xHandover = 0; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void pauseThread( portBASE_TYPE pauseMode ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -#ifdef COND_SIGNALING -static pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask ); -static pthread_mutex_t * prvGetMutexHandle( xTaskHandle hTask ); -#endif -static xTaskHandle prvGetTaskHandle( pthread_t hThread ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -/*-----------------------------------------------------------*/ - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -#define THREAD_PAUSE_CREATED 0 -#define THREAD_PAUSE_YIELD 1 -#define THREAD_PAUSE_INTERRUPT 2 - -//#define DEBUG_OUTPUT -//#define ERROR_OUTPUT -#ifdef DEBUG_OUTPUT - - static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; - - #define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_error debug_printf - - int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); - } - int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); - } - #define pthread_mutex_trylock(...) ( (debug_printf(" -!- pthread_mutex_trylock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_trylock(__VA_ARGS__):0 ) - #define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) - #define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) - #define pthread_kill(thread,signal) ( (debug_printf("Sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) - #define pthread_cond_signal( hCond ) (debug_printf( "pthread_cond_signals(%li)\r\n", *((long int *) hCond) ) ? 1 : pthread_cond_signal( hCond ) ) - #define pthread_cond_timedwait( hCond, hMutex, it ) (debug_printf( "pthread_cond_timedwait(%li,%li)\r\n", *((long int *) hCond), *((long int *) hMutex )) ? 1 : pthread_cond_timedwait( hCond, hMutex, it ) ) - #define pthread_sigmask( how, set, out ) (debug_printf( "pthread_sigmask( %i, %li )\r\n", how, *((long int*) set) ) ? 1 : pthread_sigmask( how, set, out ) ) - -#else - #ifdef ERROR_OUTPUT - static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; - #define debug_error(...) ( (pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_printf(...) - #else - #define debug_printf(...) - #define debug_error(...) - #endif -#endif - - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - - -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB *debug_task_handle; - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - debug_printf("pxPortInitialiseStack\r\n"); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - debug_printf( "Got index for new task %i\r\n", lIndexOfLastAddedTask ); - -#ifdef COND_SIGNALING - /* Create a condition signal for this thread */ -// pthread_condattr_t condAttr; -// assert( 0 == pthread_condattr_init( &condAttr ) ); - pxThreads[ lIndexOfLastAddedTask ].hCond = ( pthread_cond_t *) malloc( sizeof( pthread_cond_t ) ); - assert( 0 == pthread_cond_init( pxThreads[ lIndexOfLastAddedTask ].hCond , NULL ) ); //&condAttr ) ); - debug_printf("Cond: %li\r\n", *( (long int *) &pxThreads[ lIndexOfLastAddedTask ].hCond) ); - - /* Create a condition mutex for this thread */ -// pthread_mutexattr_t mutexAttr; -// assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); -// assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - pxThreads[ lIndexOfLastAddedTask ].hMutex = ( pthread_mutex_t *) malloc( sizeof( pthread_mutex_t ) ); - assert( 0 == pthread_mutex_init( pxThreads[ lIndexOfLastAddedTask ].hMutex, NULL ) ); //&mutexAttr ) ); - debug_printf("Mutex: %li\r\n", *( (long int *) &pxThreads[ lIndexOfLastAddedTask ].hMutex) ); -#endif - - /* Create a thread and store it's handle number */ - xSentinel = 0; - assert( 0 == pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ); - - /* Wait until the task suspends. */ - while ( xSentinel == 0 ); - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - debug_printf("vPortStartFirstTask\r\n"); - - /* Start the first task. */ - vPortEnableInterrupts(); - xRunning = 1; - - /* Start the first task. */ -#ifdef COND_SIGNALING - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -sigset_t xSignalToBlock; -portLONG lIndex; - - debug_printf( "xPortStartScheduler\r\n" ); - - /* Establish the signals to block before they are needed. */ - sigemptyset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* Unfortunately things are stable if we start ticking during setup. This need to be */ - /* checked careful in startup on hardware */ - usleep(1000000); - -#ifdef TICK_SIGNAL - struct itimerval itimer; - portTickType xMicroSeconds = portTICK_RATE_MICROSECONDS; - - debug_printf("init %li microseconds\n",(long)xMicroSeconds); - /* Initialise the structure with the current timer information. */ - assert ( 0 == getitimer( TIMER_TYPE, &itimer ) ); - - /* Set the interval between timer events. */ - itimer.it_interval.tv_sec = 0; - itimer.it_interval.tv_usec = xMicroSeconds; - - /* Set the current count-down. */ - itimer.it_value.tv_sec = 0; - itimer.it_value.tv_usec = xMicroSeconds; - - struct sigaction sigtick; - sigtick.sa_flags = 0; - sigtick.sa_handler = vPortSystemTickHandler; - sigfillset( &sigtick.sa_mask ); - assert ( 0 == sigaction( SIG_TICK, &sigtick, NULL ) ); - - /* Set-up the timer interrupt. */ - assert ( 0 == setitimer( TIMER_TYPE, &itimer, NULL ) ); - - sigemptyset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - while(1) - { - usleep(1000); - sched_yield(); - } -#else - - struct timespec x; - while( pdTRUE != xSchedulerEnd ) { - x.tv_sec=0; - x.tv_nsec=portTICK_RATE_MICROSECONDS * 1000; - nanosleep(&x,NULL); -// printf("."); fflush(stdout); - vPortSystemTickHandler(SIG_TICK); -// printf("*"); fflush(stdout); - } - -#endif - debug_printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - xResult = pthread_mutex_destroy( &xSwappingThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - - - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSwappingThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -sigset_t xSignals; -int retVal; -tskTCB * oldTask, * newTask; - - /* We must mask the suspend signal here, because otherwise there can be an */ - /* interrupt while in pthread_mutex_lock and that will cause the next thread */ - /* to deadlock when it tries to get this mutex */ - - debug_printf( "Entering\r\n" ); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); - - oldTask = xTaskGetCurrentTaskHandle(); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - retVal = pthread_mutex_trylock( &xSwappingThreadMutex ); - while( retVal != 0 ) { - - assert( retVal == EBUSY ); - - /* If we can't get the mutex, that means an interrupt is running and we */ - /* should keep an eye out if this task should suspend so the interrupt */ - /* routine doesn't stall waiting for this task to pause */ - debug_printf( "Waiting to get swapping mutex from ISR\r\n" ); - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) != pthread_self() ) { - debug_printf( "The current task isn't even us. Pausing now, deal with possible interrupt later.\r\n" ); - pauseThread( THREAD_PAUSE_YIELD ); - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - sched_yield(); - retVal = pthread_mutex_trylock( &xSwappingThreadMutex ); - } - - /* At this point we have the lock, active task shouldn't change */ - if(xTaskToSuspend != pthread_self() ) { - debug_printf( "The current task isn't even us, letting interrupt happen. Watch for swap.\r\n" ); - - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - - pauseThread( THREAD_PAUSE_YIELD ); - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - - assert( xTaskToSuspend == pthread_self() ); // race condition I didn't account for - - xStarted = pdFALSE; - - /* Get new task then release the task switching mutex */ - vTaskSwitchContext(); - newTask = xTaskGetCurrentTaskHandle(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if ( pthread_self() != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - - debug_error( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - -#ifdef COND_SIGNALING - /* Set resume condition for specific thread */ - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif -#ifdef CHECK_TASK_RESUMES - while( xStarted == pdFALSE ) - debug_printf( "Waiting for task to resume\r\n" ); -#endif - - debug_printf( "Detected task resuming. Pausing this task\r\n" ); - - /* Release swapping thread mutex and pause self */ - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - pauseThread( THREAD_PAUSE_YIELD ); - } - else { - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - } - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - debug_printf("\r\n"); - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - debug_printf("\r\n"); - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -tskTCB * oldTask, * newTask; - - debug_printf( "\r\n\r\n" ); - debug_printf( "(xInterruptsEnabled = %i, xServicingTick = %i)\r\n", (int) xInterruptsEnabled != 0, (int) xServicingTick != 0); - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) ) - { -// debug_printf( "Checking for lock ...\r\n" ); - if ( 0 == pthread_mutex_trylock( &xSwappingThreadMutex ) ) - { - debug_printf( "Handling\r\n"); - xServicingTick = pdTRUE; - - oldTask = xTaskGetCurrentTaskHandle(); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - /* Need to set this before updating the task in case it notices before the */ - /* interrupt is set */ - xSuspended = pdFALSE; - xStarted = pdFALSE; - - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - - newTask = xTaskGetCurrentTaskHandle(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - debug_printf( "Want %s running\r\n", newTask->pcTaskName ); - /* 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 ); - - debug_printf( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - - assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0); - -#ifdef CHECK_TASK_RESUMES - /* It shouldn't be possible for a second task swap to happen while waiting for this because */ - /* they can't get the xSwappingThreadMutex */ - while( xSuspended == pdFALSE ) -#endif - { - debug_printf( "Waiting for old task to suspend\r\n" ); - debug_printf( "Sent signal\r\n" ); - sched_yield(); - } - debug_printf( "Suspended\r\n" ); - -#ifdef CHECK_TASK_RESUMES - while( xStarted == pdFALSE) -#endif - { - debug_printf( "Waiting for new task to resume\r\n" ); -#ifdef COND_SIGNALING - // Set resume condition for specific thread - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif - - sched_yield(); - } - - debug_printf( "Swapped From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); } - else - { - // debug_error ("Want %s running \r\n", newTask->pcTaskName ); - } - xServicingTick = pdFALSE; - (void)pthread_mutex_unlock( &xSwappingThreadMutex ); - } - else - { - debug_error( "Pending yield here (portYield has lock - hopefully)\r\n" ); - xPendYield = pdTRUE; - } - - } - else - { - debug_printf( "Pending yield or here\r\n"); - xPendYield = pdTRUE; - } - debug_printf("Exiting\r\n"); -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - - printf("vPortForciblyEndThread\r\n"); - - if ( 0 == pthread_mutex_lock( &xSwappingThreadMutex ) ) - { - 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 ); - /* Pthread Clean-up function will note the cancellation. */ - } - (void)pthread_mutex_unlock( &xSwappingThreadMutex ); - } - else - { - /* Resume the other thread. */ - /* Assert zero - I never fixed this functionality */ - assert( 0 ); - - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); - (void)pthread_mutex_unlock( &xSwappingThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } - } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - /* want to block suspend when not the active thread */ - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - sigaddset( &xSignals, SIG_TICK ); - assert( pthread_sigmask( SIG_SETMASK, &xSignals, NULL ) == 0); - - /* Because the FreeRTOS creates the TCB stack, which in this implementation */ - /* creates a thread, we need to wait until the task handle is added before */ - /* trying to pause. Must set xSentinel high so the creating task knows we're */ - /* here */ - - debug_printf("Thread started, waiting till handle is added\r\n"); - - xSentinel = 1; - - while( prvGetTaskHandle( pthread_self() ) == NULL ){ - sched_yield(); - } - - debug_printf("Handle added, pausing\r\n"); - - /* Want to delay briefly until we have explicit resume signal as otherwise the */ - /* current task variable might be in the wrong state */ - pauseThread( THREAD_PAUSE_CREATED ); - debug_printf("Starting first run\r\n"); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - assert( pthread_sigmask( SIG_SETMASK, &xSignals, NULL ) == 0); - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void pauseThread( portBASE_TYPE pauseMode ) -{ - debug_printf( "Pausing thread %li. Set xSuspended true\r\n", (long int) pthread_self() ); - xSuspended = pdTRUE; - -#ifdef RUNNING_THREAD_MUTEX - if( pauseMode != THREAD_PAUSE_CREATED ) - assert( 0 == pthread_mutex_unlock( &xRunningThread ) ); -#endif - -#ifdef COND_SIGNALING - int xResult; - xTaskHandle hTask = prvGetTaskHandle( pthread_self() ); - pthread_cond_t * hCond = prvGetConditionHandle( hTask ); - pthread_mutex_t * hMutex = prvGetMutexHandle( hTask ); - debug_printf("Cond: %li\r\n", *( (long int *) hCond) ); - debug_printf("Mutex: %li\r\n", *( (long int *) hMutex) ); - - struct timeval tv; - struct timespec ts; - gettimeofday( &tv, NULL ); - ts.tv_sec = tv.tv_sec + 0; -#endif - - while (1) { - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) && xRunning ) - { - - xStarted = pdTRUE; - -#ifdef RUNNING_THREAD_MUTEX - assert( 0 == pthread_mutex_lock( &xRunningThread ) ); -#endif - debug_error("Resuming\r\n"); - return; - } - else { -#ifdef COND_SIGNALING - gettimeofday( &tv, NULL ); - ts.tv_sec = ts.tv_sec + 1; - ts.tv_nsec = 0; - xResult = pthread_cond_timedwait( hCond, hMutex, &ts ); - assert( xResult != EINVAL ); -#else - /* For windows where conditional signaling is buggy */ - /* It would be wonderful to put a nanosleep here, but since its not reentrant safe */ - /* and there may be a sleep in the main code (this can be called from an ISR) we must */ - /* check this */ - if( pauseMode != THREAD_PAUSE_INTERRUPT ) - usleep(1000); - sched_yield(); - -#endif -// debug_error( "Checked my status\r\n" ); - } - - } -} - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xBlockSignals; - - /* This signal is set here instead of pauseThread because it is checked by the tick handler */ - /* which means if there were a swap it should result in a suspend interrupt */ - - debug_error( "Caught signal %i\r\n", sig ); - -#ifdef CHECK_TASK_RESUMES - /* This would seem like a major bug, but can happen because now we send extra suspend signals */ - /* if they aren't caught */ - if( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) { - debug_printf( "Marked as current task, resuming\r\n" ); - return; - } -#endif - - /* Check that we aren't suspending when we should be running. This bug would need tracking down */ -// assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - - /* Block further suspend signals. They need to go to their thread */ - sigemptyset( &xBlockSignals ); - sigaddset( &xBlockSignals, SIG_SUSPEND ); - sigaddset( &xBlockSignals, SIG_TICK ); - assert( pthread_sigmask( SIG_SETMASK, &xBlockSignals, NULL ) == 0); - - while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) - { - debug_printf( "Incorrectly woke up. Repausing\r\n" ); - pauseThread( THREAD_PAUSE_INTERRUPT ); - } - - assert( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); - - /* Old synchronization code, may still be required - while( !xHandover ); - assert( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ); */ - - /* Respond to signals again */ - sigemptyset( &xBlockSignals ); - sigaddset( &xBlockSignals, SIG_TICK ); - assert( 0 == pthread_sigmask( SIG_SETMASK, &xBlockSignals, NULL ) ); - - debug_printf( "Resuming %li from signal %i\r\n", (long int) pthread_self(), sig ); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - debug_printf("Exit\r\n"); -} - -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself; -portLONG lIndex; - - debug_printf("prvSetupSignalAndSchedulerPolicy\r\n"); - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigemptyset( &sigsuspendself.sa_mask ); - - assert ( 0 == sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ); -} - -/*-----------------------------------------------------------*/ -pthread_mutex_t * prvGetMutexHandle( xTaskHandle hTask ) -{ -pthread_mutex_t * hMutex; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hMutex = pxThreads[ lIndex ].hMutex; - break; - } - } - return hMutex; -} - -/*-----------------------------------------------------------*/ -xTaskHandle prvGetTaskHandle( pthread_t hThread ) -{ -xTaskHandle hTask = NULL; -portLONG lIndex; - - /* If not initialized yet */ - if( pxThreads == NULL ) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - hTask = pxThreads[ lIndex ].hTask; - break; - } - } - return hTask; -} - -/*-----------------------------------------------------------*/ -pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask ) -{ -pthread_cond_t * hCond; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - debug_printf( "Found condition on %i task\r\n", lIndex ); - return pxThreads[ lIndex ].hCond; - break; - } - } - printf( "Failed to get handle, pausing then recursing\r\n" ); - usleep(1000); - return prvGetConditionHandle( hTask ); - assert(0); - return hCond; -} - -/*-----------------------------------------------------------*/ -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ - pthread_t hThread = ( pthread_t )NULL; - portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - debug_printf("vPortAddTaskHandle\r\n"); - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } - usleep(10000); -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - - /* Needs to be reasonably high for accuracy. */ - unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-stupidlysimplerversion.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-stupidlysimplerversion.c deleted file mode 100644 index 53d49b094..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port-stupidlysimplerversion.c +++ /dev/null @@ -1,1109 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -#define DB_P(x) // x - - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - pthread_cond_t hCond; - pthread_mutex_t hMutex; - xTaskHandle hTask; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -static pthread_mutex_t xRunningThread = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSingleThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xHandover = 0; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xInterruptsCurrent = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -//static void prvResumeSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void prvSuspendThread( pthread_t xThreadId ); -static void pauseThread(); -//static void prvResumeThread( pthread_t xThreadId ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -static pthread_cond_t prvGetThreadCondition( xTaskHandle hTask ); -static pthread_mutex_t prvGetThreadMutex( xTaskHandle hTask ); -static xTaskHandle prvGetThreadTask( pthread_t hThread ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -/*-----------------------------------------------------------*/ - - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - - - -//#define DEBUG_OUTPUT -#ifdef DEBUG_OUTPUT - - static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; - - #define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_error debug_printf - - int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); - } - int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); - } - #define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) - #define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) - #define pthread_kill(thread,signal) ( (debug_printf("Sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) -#else - #define debug_error(...) ( (pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_printf(...) -#endif - - - - - -//#define debug_printf(...) fprintf( stderr, __VA_ARGS__ ); -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - - -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB *debug_task_handle; -tskTCB * prvGetTaskHandle( pthread_t hThread ) -{ - portLONG lIndex; - - if (pxThreads==NULL) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - return pxThreads[ lIndex ].hTask; - } - } - return NULL; -} - - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - debug_printf("pxPortInitialiseStack\r\n"); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } /*else { - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_TICK ); - pthread_sigmask( SIG_BLOCK, &xSignals, NULL ); - } */ - - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - /* Create a condition signal for this thread */ -/* pthread_condattr_t condAttr; - assert( 0 == pthread_condattr_init(&condAttr) ); - assert( 0 == pthread_cond_init( &( pxThreads[ lIndexOfLastAddedTask ].hCond ), &condAttr ) ); */ - - /* Create a condition mutex for this thread */ -/* pthread_mutexattr_t mutexAttr; - assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); - assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - assert( 0 == pthread_mutex_init( &( pxThreads[ lIndexOfLastAddedTask ].hMutex ), &mutexAttr ) );*/ - - /* Create a thread and store it's handle number */ - xSentinel = 0; - assert( 0 == pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ); - - - - /* Wait until the task suspends. */ - while ( xSentinel == 0 ); - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - debug_printf("vPortStartFirstTask\r\n"); - - /* Start the first task. */ - vPortEnableInterrupts(); - - /* Start the first task. */ - //prvResumeThread( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); - - debug_printf( "Sending resume signal to %li\r\n", (long int) prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); -// pthread_kill( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ), SIG_RESUME ); - // Set resume condition for specific thread - //pthread_cond_t hCond = prvGetThreadCondition( xTaskGetCurrentTaskHandle() ); - //assert( pthread_cond_signal( &hCond ) == 0 ); - -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -sigset_t xSignals; -sigset_t xSignalToBlock; -sigset_t xSignalsBlocked; -portLONG lIndex; - - debug_printf( "xPortStartScheduler\r\n" ); - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); -/* sigaddset( &xSignalToBlock, SIG_RESUME ); - sigaddset( &xSignalToBlock, SIG_TICK ); */ - - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, &xSignalsBlocked ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ -// prvSetupTimerInterrupt(); - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - /* This is the end signal we are looking for. */ - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_RESUME ); - - while( pdTRUE != xSchedulerEnd ) { - struct timespec x; - x.tv_sec=0; - x.tv_nsec=1000000; - nanosleep(&x,NULL); - printf("."); fflush(stdout); - vPortSystemTickHandler(SIG_TICK); - } - - debug_printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - xResult = pthread_mutex_destroy( &xSingleThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - - DB_P("vPortEndScheduler\r\n"); - - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSingleThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - - DB_P("vPortYieldFromISR\r\n"); - - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - DB_P("vPortEnterCritical\r\n"); - - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - DB_P("vPortExitCritical\r\n"); - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -sigset_t xSignals; - - /* We must mask the suspend signal here, because otherwise there can be an */ - /* interrupt while in pthread_mutex_lock and that will cause the next thread */ - /* to deadlock when it tries to get this mutex */ - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); - - assert( pthread_mutex_lock( &xSingleThreadMutex ) == 0); - - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if(xTaskToSuspend != pthread_self() ) { - /* This means between masking the interrupt and getting the lock, there was an interrupt */ - /* and this task should suspend. Release the lock, then unmask interrupts to go ahead and */ - /* service the signal */ - assert( 0 == pthread_mutex_unlock( &xSingleThreadMutex ) ); - debug_printf( "The current task isn't even us, letting interrupt happen\r\n" ); - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - - /* Get new task then release the task switching mutex */ - vTaskSwitchContext(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_mutex_unlock( &xSingleThreadMutex ) == 0); - - if ( pthread_self() != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - - /* pausing self if switching tasks, can now rely on other thread waking itself up */ - pauseThread(); - } - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - DB_P("vPortDisableInterrupts\r\n"); - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - DB_P("vPortEnableInterrupts\r\n"); - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - DB_P("vPortsetInterruptMask\r\n"); - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - DB_P("vPortClearInterruptMask\r\n"); - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -portBASE_TYPE xInterruptValue; -tskTCB * oldTask, * newTask; -int lockResult; - - DB_P("vPortSystemTickHandler"); - xInterruptValue = xInterruptsEnabled; - debug_printf( "\r\n\r\n" ); - debug_printf( "(xInterruptsEnabled = %i, xServicingTick = %i)\r\n", (int) xInterruptValue != 0, (int) xServicingTick != 0); - if ( ( pdTRUE == xInterruptValue ) && ( pdTRUE != xServicingTick ) ) - { - debug_printf( "Checking for lock ...\r\n" ); - lockResult = pthread_mutex_trylock( &xSingleThreadMutex ); -// lockResult = 0; - debug_printf( "Done\r\n" ); - if ( 0 == lockResult) - { - debug_printf( "Handling\r\n"); - xServicingTick = pdTRUE; - oldTask = xTaskGetCurrentTaskHandle(); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - - newTask = xTaskGetCurrentTaskHandle(); - 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 ); - - debug_printf( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - prvSuspendThread( xTaskToSuspend ); /* Suspend the current task. */ - debug_printf( "Swapped From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - } - xServicingTick = pdFALSE; - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - else - { - debug_printf( "Pending yield here (portYield has lock - hopefully)\r\n" ); - xPendYield = pdTRUE; - } - - } - else - { - debug_printf( "Pending yield or here\r\n"); - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - - printf("vPortForciblyEndThread\r\n"); - - 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 ); - /* Pthread Clean-up function will note the cancellation. */ - } - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } - else - { - /* Resume the other thread. */ - //prvResumeThread( xTaskToResume ); - assert( 0 ); - - /* 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 ); - } - } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - xSentinel = 1; // tell creating block to resume - - /* want to block suspend when not the active thread */ - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - assert( pthread_sigmask( SIG_BLOCK, &xSignals, NULL ) == 0); - - debug_printf( "Delaying before the pause to make sure system knows about task\r\n" ); - struct timespec x; - x.tv_sec=0; - x.tv_nsec=10000000; - nanosleep(&x,NULL); - - // wait for resume signal - debug_printf("Pausing newly created thread\r\n"); -// pthread_mutex_lock( &xRunningThread ); -// pauseThread(); - - while (1) { - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ) - { - // assert( 0 == pthread_mutex_lock( &xRunningThread ) ); - break; - } - else { - struct timespec x; - x.tv_sec=0; - x.tv_nsec=100000; - nanosleep(&x,NULL); - sched_yield(); - } - - } - - // no longer want to block any signals - sigemptyset( &xSignals ); - assert( pthread_sigmask( SIG_SETMASK, &xSignals, NULL ) == 0); - debug_printf("Starting first run\r\n"); - - //xHandover = 1; - //assert ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void pauseThread() -{ - debug_printf("\r\n"); - -// assert( 0 == pthread_mutex_unlock( &xRunningThread ) ); - while (1) { - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ) - { -// assert( 0 == pthread_mutex_lock( &xRunningThread ) ); - return; - } - else { - struct timespec x; - x.tv_sec=0; - x.tv_nsec=100000; - nanosleep(&x,NULL); - sched_yield(); - } - - } - xTaskHandle hTask = prvGetThreadTask( pthread_self() ); - pthread_cond_t hCond = prvGetThreadCondition( hTask ); - pthread_mutex_t hMutex = prvGetThreadMutex( hTask ); - // while( !shouldResume ) { - pthread_cond_wait( &hCond, &hMutex ); - assert( 0 == pthread_mutex_lock( &xRunningThread ) ); - // } -} - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xBlockSignals; - - debug_printf( "Caught signal %i\r\n", sig ); - /* Check that we aren't suspending when we should be running. This bug would need tracking down */ - //assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - if( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) return; - - /* Block further suspend signals. They need to go to their thread */ - sigemptyset( &xBlockSignals ); - sigaddset( &xBlockSignals, SIG_SUSPEND ); - assert( pthread_sigmask( SIG_BLOCK, &xBlockSignals, NULL ) == 0); - - /* Unlock the Single thread mutex to allow the resumed task to continue. */ - //assert ( 0 == pthread_mutex_unlock( &xSingleThreadMutex ) ); - - // Set resume condition for specific thread -/* pthread_cond_t hCond = prvGetThreadCondition( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( &hCond ) == 0 ); */ - - pauseThread(); - - while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) - { - debug_printf( "Incorrectly woke up. Repausing\r\n" ); - pauseThread(); - } - - /* Make sure the right thread is resuming */ - assert( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - - /* Old synchronization code, may still be required - while( !xHandover ); - assert( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ); */ - - /* Respond to signals again */ - sigemptyset( &xBlockSignals ); - pthread_sigmask( SIG_SETMASK, &xBlockSignals, NULL ); - - debug_printf( "Resuming %li from signal %i\r\n", (long int) pthread_self(), sig ); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - debug_printf("Exit\r\n"); -} -/*-----------------------------------------------------------*/ - -void prvSuspendThread( pthread_t xThreadId ) -{ - debug_printf( "Suspending %li\r\n", (long int) xThreadId); - /* Set-up for the Suspend Signal handler? */ - xSentinel = 0; - - if( pthread_self() == xThreadId ) { - debug_printf( "Pausing self, no reason to call signal handler\r\n" ); - pauseThread(); - } - else { - debug_printf( "About to kill %li\r\n", (long int) xThreadId ); - assert( pthread_kill( xThreadId, SIG_SUSPEND ) == 0); - debug_printf( "Killed %li\r\n", (long int) xThreadId ); - } - - -// while ( ( xSentinel == 0 ) && ( pdTRUE != xServicingTick ) ) - { -// debug_printf( "sched_yield()\r\n" ); - sched_yield(); - } -} -/*-----------------------------------------------------------*/ - -/*void prvResumeSignalHandler(int sig) -{ - - DB_P("prvResumeSignalHandler\r\n"); - - debug_printf( "prvResumeSignalHandler getLock"); - while(1); - // Yield the Scheduler to ensure that the yielding thread completes. - if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) - { - debug_printf( "prvResumeSignalHandler: unlocking xSingleThreadMutex (%li)\r\n", (long int) pthread_self()); - (void)pthread_mutex_unlock( &xSingleThreadMutex ); - } -}*/ -/*-----------------------------------------------------------*/ - -/*void prvResumeThread( pthread_t xThreadId ) -{ -portBASE_TYPE xResult; - - DB_P("prvResumeThread\r\n"); - debug_printf( "getLock\r\n" ); - if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) - { - debug_printf( "Resuming %li\r\n", (long int) xThreadId ); - if ( pthread_self() != xThreadId ) - { - //xResult = pthread_kill( xThreadId, SIG_RESUME ); - debug_printf( "No longer doing anything. Suspend handler for previous thread should start %li\r\n", (long int) xThreadId ); - } - else { - debug_printf( "Thread attempting to resume itself. This is not expected behavior\r\n" ); - kill( getpid(), SIGKILL ); - } - - xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); - } - else { - debug_printf("Error getting lock to resume thread\r\n"); - kill( getpid(), SIGKILL ); - } - -} */ -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself; -portLONG lIndex; - - debug_printf("prvSetupSignalAndSchedulerPolicy\r\n"); - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigfillset( &sigsuspendself.sa_mask ); - - assert ( 0 == sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ); -} - -/*-----------------------------------------------------------*/ -pthread_mutex_t prvGetThreadMutex( xTaskHandle hTask ) -{ -pthread_mutex_t hMutex; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hMutex = pxThreads[ lIndex ].hMutex; - break; - } - } - return hMutex; -} - -/*-----------------------------------------------------------*/ -xTaskHandle prvGetThreadTask( pthread_t hThread ) -{ -xTaskHandle hTask; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - hTask = pxThreads[ lIndex ].hTask; - break; - } - } - return hTask; -} - -/*-----------------------------------------------------------*/ -pthread_cond_t prvGetThreadCondition( xTaskHandle hTask ) -{ -pthread_cond_t hCond; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hCond = pxThreads[ lIndex ].hCond; - break; - } - } - return hCond; -} - -/*-----------------------------------------------------------*/ -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ - pthread_t hThread = ( pthread_t )NULL; - portLONG lIndex; - - DB_P("prvGetThreadHandle\r\n"); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - - DB_P("prvGetFreeThreadState\r\n"); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - DB_P("prvSetTaskCriticalNesting\r\n"); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - - DB_P("prvGetTaskCriticalNesting\r\n"); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - - DB_P("prvDeleteThread\r\n"); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - debug_printf("vPortAddTaskHandle\r\n"); - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - DB_P("vPortFindTicksPerSecond\r\n"); - - /* Needs to be reasonably high for accuracy. */ - //unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - //printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - - DB_P("ulPortGetTimerValue\r\n"); - - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port.c deleted file mode 100644 index 128434fe3..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/port.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - Copyright (C) 2009 William Davy - william.davy@wittenstein.co.uk - Contributed to FreeRTOS.org V5.3.0. - - This file is part of the FreeRTOS.org distribution. - - FreeRTOS.org is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License (version 2) as published - by the Free Software Foundation and modified by the FreeRTOS exception. - - FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along - with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 - Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - A special exception to the GPL is included to allow you to distribute a - combined work that includes FreeRTOS.org without being obliged to provide - the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details. - - - *************************************************************************** - * * - * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * - * * - * This is a concise, step by step, 'hands on' guide that describes both * - * general multitasking concepts and FreeRTOS specifics. It presents and * - * explains numerous examples that are written using the FreeRTOS API. * - * Full source code for all the examples is provided in an accompanying * - * .zip file. * - * * - *************************************************************************** - - 1 tab == 4 spaces! - - Please ensure to read the configuration and relevant port sections of the - online documentation. - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - -/*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the Posix port. - *----------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" -/*-----------------------------------------------------------*/ - -#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) -/*-----------------------------------------------------------*/ - -#ifndef __CYGWIN__ - #define COND_SIGNALING - #define CHECK_TASK_RESUMES - #define RUNNING_THREAD_MUTEX -#endif - -/* Parameters to pass to the newly created pthread. */ -typedef struct XPARAMS -{ - pdTASK_CODE pxCode; - void *pvParams; -} xParams; - -/* Each task maintains its own interrupt status in the critical nesting variable. */ -typedef struct THREAD_SUSPENSIONS -{ - pthread_t hThread; - pthread_cond_t * hCond; - pthread_mutex_t * hMutex; - xTaskHandle hTask; - portBASE_TYPE xThreadState; - unsigned portBASE_TYPE uxCriticalNesting; -} xThreadState; -/*-----------------------------------------------------------*/ - -static xThreadState *pxThreads; -static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT; -static pthread_attr_t xThreadAttributes; -#ifdef RUNNING_THREAD_MUTEX -static pthread_mutex_t xRunningThread = PTHREAD_MUTEX_INITIALIZER; -#endif -static pthread_mutex_t xSuspendResumeThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t xSwappingThreadMutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_t hMainThread = ( pthread_t )NULL; -/*-----------------------------------------------------------*/ - -static volatile portBASE_TYPE xSentinel = 0; -static volatile portBASE_TYPE xRunning = pdFALSE; -static volatile portBASE_TYPE xSuspended = pdFALSE; -static volatile portBASE_TYPE xStarted = pdFALSE; -static volatile portBASE_TYPE xHandover = 0; -static volatile portBASE_TYPE xSchedulerEnd = pdFALSE; -static volatile portBASE_TYPE xInterruptsEnabled = pdTRUE; -static volatile portBASE_TYPE xServicingTick = pdFALSE; -static volatile portBASE_TYPE xPendYield = pdFALSE; -static volatile portLONG lIndexOfLastAddedTask = 0; -static volatile unsigned portBASE_TYPE uxCriticalNesting; -/*-----------------------------------------------------------*/ - -/* - * Setup the timer to generate the tick interrupts. - */ -static void *prvWaitForStart( void * pvParams ); -static void prvSuspendSignalHandler(int sig); -static void prvSetupSignalsAndSchedulerPolicy( void ); -static void pauseThread( portBASE_TYPE pauseMode ); -static pthread_t prvGetThreadHandle( xTaskHandle hTask ); -#ifdef COND_SIGNALING -static pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask ); -static pthread_mutex_t * prvGetMutexHandle( xTaskHandle hTask ); -#endif -static xTaskHandle prvGetTaskHandle( pthread_t hThread ); -static portLONG prvGetFreeThreadState( void ); -static void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ); -static unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ); -static void prvDeleteThread( void *xThreadId ); -/*-----------------------------------------------------------*/ - -/* - * Exception handlers. - */ -void vPortYield( void ); -void vPortSystemTickHandler( int sig ); - -#define THREAD_PAUSE_CREATED 0 -#define THREAD_PAUSE_YIELD 1 -#define THREAD_PAUSE_INTERRUPT 2 - -//#define DEBUG_OUTPUT -//#define ERROR_OUTPUT -#ifdef DEBUG_OUTPUT - - static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; - - #define debug_printf(...) ( (real_pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?real_pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_error debug_printf - - int real_pthread_mutex_lock(pthread_mutex_t* mutex) { - return pthread_mutex_lock(mutex); - } - int real_pthread_mutex_unlock(pthread_mutex_t* mutex) { - return pthread_mutex_unlock(mutex); - } - #define pthread_mutex_lock(...) ( (debug_printf(" -!- pthread_mutex_lock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_lock(__VA_ARGS__):0 ) - #define pthread_mutex_unlock(...) ( (debug_printf(" -=- pthread_mutex_unlock(%s)\n",#__VA_ARGS__)|1)?pthread_mutex_unlock(__VA_ARGS__):0 ) - #define pthread_kill(thread,signal) ( (debug_printf("Sending signal %i to thread %li!\n",(int)signal,(long)thread)|1)?pthread_kill(thread,signal):0 ) - #define pthread_cond_signal( hCond ) (debug_printf( "pthread_cond_signals(%li)\r\n", *((long int *) hCond) ) ? 1 : pthread_cond_signal( hCond ) ) - #define pthread_cond_timedwait( hCond, hMutex, it ) (debug_printf( "pthread_cond_timedwait(%li,%li)\r\n", *((long int *) hCond), *((long int *) hMutex )) ? 1 : pthread_cond_timedwait( hCond, hMutex, it ) ) - #define pthread_sigmask( how, set, out ) (debug_printf( "pthread_sigmask( %i, %li )\r\n", how, *((long int*) set) ) ? 1 : pthread_sigmask( how, set, out ) ) - -#else - #ifdef ERROR_OUTPUT - static pthread_mutex_t xPrintfMutex = PTHREAD_MUTEX_INITIALIZER; - #define debug_error(...) ( (pthread_mutex_lock( &xPrintfMutex )|1)?( \ - ( \ - (NULL != (debug_task_handle = prvGetTaskHandle(pthread_self())) )? \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ",debug_task_handle->pcTaskName,(long)pthread_self(),__func__,__LINE__)): \ - (fprintf( stderr, "%20s(%li)\t%20s\t%i: ","__unknown__",(long)pthread_self(),__func__,__LINE__)) \ - |1)?( \ - ((fprintf( stderr, __VA_ARGS__ )|1)?pthread_mutex_unlock( &xPrintfMutex ):0) \ - ):0 ):0 ) - - #define debug_printf(...) - #else - #define debug_printf(...) - #define debug_error(...) - #endif -#endif - - -/* - * Start first task is a separate function so it can be tested in isolation. - */ -void vPortStartFirstTask( void ); -/*-----------------------------------------------------------*/ - - -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ -#endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - -#if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ -#endif - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; -#endif - -#if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ -#endif - -#if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ -#endif - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; -#endif - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ -#endif - -} tskTCB; - -tskTCB *debug_task_handle; - -/* - * See header file for description. - */ -portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) -{ -/* Should actually keep this struct on the stack. */ -xParams *pxThisThreadParams = pvPortMalloc( sizeof( xParams ) ); - - debug_printf("pxPortInitialiseStack\r\n"); - - (void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy ); - - if ( (pthread_t)NULL == hMainThread ) - { - hMainThread = pthread_self(); - } - - /* No need to join the threads. */ - pthread_attr_init( &xThreadAttributes ); - pthread_attr_setdetachstate( &xThreadAttributes, PTHREAD_CREATE_DETACHED ); - - /* Add the task parameters. */ - pxThisThreadParams->pxCode = pxCode; - pxThisThreadParams->pvParams = pvParameters; - - vPortEnterCritical(); - - lIndexOfLastAddedTask = prvGetFreeThreadState(); - - debug_printf( "Got index for new task %i\r\n", lIndexOfLastAddedTask ); - -#ifdef COND_SIGNALING - /* Create a condition signal for this thread */ -// pthread_condattr_t condAttr; -// assert( 0 == pthread_condattr_init( &condAttr ) ); - pxThreads[ lIndexOfLastAddedTask ].hCond = ( pthread_cond_t *) malloc( sizeof( pthread_cond_t ) ); - assert( 0 == pthread_cond_init( pxThreads[ lIndexOfLastAddedTask ].hCond , NULL ) ); //&condAttr ) ); - debug_printf("Cond: %li\r\n", *( (long int *) &pxThreads[ lIndexOfLastAddedTask ].hCond) ); - - /* Create a condition mutex for this thread */ -// pthread_mutexattr_t mutexAttr; -// assert( 0 == pthread_mutexattr_init( &mutexAttr ) ); -// assert( 0 == pthread_mutexattr_settype( &mutexAttr, PTHREAD_MUTEX_ERRORCHECK ) ); - pxThreads[ lIndexOfLastAddedTask ].hMutex = ( pthread_mutex_t *) malloc( sizeof( pthread_mutex_t ) ); - assert( 0 == pthread_mutex_init( pxThreads[ lIndexOfLastAddedTask ].hMutex, NULL ) ); //&mutexAttr ) ); - debug_printf("Mutex: %li\r\n", *( (long int *) &pxThreads[ lIndexOfLastAddedTask ].hMutex) ); -#endif - - /* Create a thread and store it's handle number */ - xSentinel = 0; - assert( 0 == pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ); - - /* Wait until the task suspends. */ - while ( xSentinel == 0 ); - vPortExitCritical(); - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -void vPortStartFirstTask( void ) -{ - /* Initialise the critical nesting count ready for the first task. */ - uxCriticalNesting = 0; - - debug_printf("vPortStartFirstTask\r\n"); - - /* Start the first task. */ - vPortEnableInterrupts(); - xRunning = 1; - - /* Start the first task. */ -#ifdef COND_SIGNALING - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif -} -/*-----------------------------------------------------------*/ - -/* - * See header file for description. - */ -portBASE_TYPE xPortStartScheduler( void ) -{ -portBASE_TYPE xResult; -sigset_t xSignalToBlock; -portLONG lIndex; - - debug_printf( "xPortStartScheduler\r\n" ); - - /* Establish the signals to block before they are needed. */ - sigfillset( &xSignalToBlock ); - sigaddset( &xSignalToBlock, SIG_SUSPEND ); - - /* Block until the end */ - (void)pthread_sigmask( SIG_SETMASK, &xSignalToBlock, NULL ); - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - /* Start the first task. Will not return unless all threads are killed. */ - vPortStartFirstTask(); - - struct timespec x; - usleep(1000000); - while( pdTRUE != xSchedulerEnd ) { - x.tv_sec=0; - x.tv_nsec=portTICK_RATE_MICROSECONDS * 1000; - nanosleep(&x,NULL); - //printf("."); fflush(stdout); - vPortSystemTickHandler(SIG_TICK); - } - - debug_printf( "Cleaning Up, Exiting.\n" ); - /* Cleanup the mutexes */ - xResult = pthread_mutex_destroy( &xSuspendResumeThreadMutex ); - xResult = pthread_mutex_destroy( &xSwappingThreadMutex ); - vPortFree( (void *)pxThreads ); - - /* Should not get here! */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) -{ -portBASE_TYPE xNumberOfThreads; -portBASE_TYPE xResult; - - - for ( xNumberOfThreads = 0; xNumberOfThreads < MAX_NUMBER_OF_TASKS; xNumberOfThreads++ ) - { - if ( ( pthread_t )NULL != pxThreads[ xNumberOfThreads ].hThread ) - { - /* Kill all of the threads, they are in the detached state. */ - xResult = pthread_cancel( pxThreads[ xNumberOfThreads ].hThread ); - } - } - - /* Signal the scheduler to exit its loop. */ - xSchedulerEnd = pdTRUE; - (void)pthread_kill( hMainThread, SIG_RESUME ); -} -/*-----------------------------------------------------------*/ - -void vPortYieldFromISR( void ) -{ - /* Calling Yield from a Interrupt/Signal handler often doesn't work because the - * xSwappingThreadMutex is already owned by an original call to Yield. Therefore, - * simply indicate that a yield is required soon. - */ - - xPendYield = pdTRUE; -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) -{ - vPortDisableInterrupts(); - uxCriticalNesting++; -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) -{ - /* Check for unmatched exits. */ - if ( uxCriticalNesting > 0 ) - { - uxCriticalNesting--; - } - - /* If we have reached 0 then re-enable the interrupts. */ - if( uxCriticalNesting == 0 ) - { - /* Have we missed ticks? This is the equivalent of pending an interrupt. */ - if ( pdTRUE == xPendYield ) - { - xPendYield = pdFALSE; - vPortYield(); - } - vPortEnableInterrupts(); - } -} -/*-----------------------------------------------------------*/ - -void vPortYield( void ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -sigset_t xSignals; -tskTCB * oldTask, * newTask; - - /* We must mask the suspend signal here, because otherwise there can be an */ - /* interrupt while in pthread_mutex_lock and that will cause the next thread */ - /* to deadlock when it tries to get this mutex */ - - debug_printf( "Entering\r\n" ); - - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); - - assert( pthread_mutex_lock( &xSwappingThreadMutex ) == 0); - - oldTask = xTaskGetCurrentTaskHandle(); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - if(xTaskToSuspend != pthread_self() ) { - /* This means between masking the interrupt and getting the lock, there was an interrupt */ - /* and this task should suspend. Release the lock, then unmask interrupts to go ahead and */ - /* service the signal */ - - assert( 0 == pthread_mutex_unlock( &xSwappingThreadMutex ) ); - debug_printf( "The current task isn't even us, letting interrupt happen. Watch for swap.\r\n" ); - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); - return; - } - - xStarted = pdFALSE; - - /* Get new task then release the task switching mutex */ - vTaskSwitchContext(); - newTask = xTaskGetCurrentTaskHandle(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - if ( pthread_self() != xTaskToResume ) - { - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - - debug_error( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - -#ifdef COND_SIGNALING - /* Set resume condition for specific thread */ - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif -#ifdef CHECK_TASK_RESUMES - while( xStarted == pdFALSE ) - debug_printf( "Waiting for task to resume\r\n" ); -#endif - - debug_printf( "Detected task resuming. Pausing this task\r\n" ); - - /* Release swapping thread mutex and pause self */ - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - pauseThread( THREAD_PAUSE_YIELD ); - } - else { - assert( pthread_mutex_unlock( &xSwappingThreadMutex ) == 0); - } - - /* Now we are resuming, want to be able to catch this interrupt again */ - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL); -} -/*-----------------------------------------------------------*/ - -void vPortDisableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdFALSE; -} -/*-----------------------------------------------------------*/ - -void vPortEnableInterrupts( void ) -{ - //debug_printf("\r\n"); - xInterruptsEnabled = pdTRUE; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xPortSetInterruptMask( void ) -{ -portBASE_TYPE xReturn = xInterruptsEnabled; - debug_printf("\r\n"); - xInterruptsEnabled = pdFALSE; - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vPortClearInterruptMask( portBASE_TYPE xMask ) -{ - debug_printf("\r\n"); - xInterruptsEnabled = xMask; -} -/*-----------------------------------------------------------*/ - - -void vPortSystemTickHandler( int sig ) -{ -pthread_t xTaskToSuspend; -pthread_t xTaskToResume; -tskTCB * oldTask, * newTask; - - debug_printf( "\r\n\r\n" ); - debug_printf( "(xInterruptsEnabled = %i, xServicingTick = %i)\r\n", (int) xInterruptsEnabled != 0, (int) xServicingTick != 0); - if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) ) - { -// debug_printf( "Checking for lock ...\r\n" ); - if ( 0 == pthread_mutex_trylock( &xSwappingThreadMutex ) ) - { - debug_printf( "Handling\r\n"); - xServicingTick = pdTRUE; - - oldTask = xTaskGetCurrentTaskHandle(); - xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - /* Tick Increment. */ - vTaskIncrementTick(); - - /* Select Next Task. */ -#if ( configUSE_PREEMPTION == 1 ) - vTaskSwitchContext(); -#endif - - newTask = xTaskGetCurrentTaskHandle(); - xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); - - debug_printf( "Want %s running\r\n", newTask->pcTaskName ); - /* The only thread that can process this tick is the running thread. */ - if ( xTaskToSuspend != xTaskToResume ) - { - xSuspended = pdFALSE; - xStarted = pdFALSE; - - /* Remember and switch the critical nesting. */ - prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); - uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); - - debug_printf( "Swapping From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); - -#ifdef CHECK_TASK_RESUMES - /* It shouldn't be possible for a second task swap to happen while waiting for this because */ - /* they can't get the xSwappingThreadMutex */ - while( xSuspended == pdFALSE ) -#endif - { - assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0); - sched_yield(); - } - -#ifdef CHECK_TASK_RESUMES - while( xStarted == pdFALSE) -#endif - { - -#ifdef COND_SIGNALING - // Set resume condition for specific thread - pthread_cond_t * hCond = prvGetConditionHandle( xTaskGetCurrentTaskHandle() ); - assert( pthread_cond_signal( hCond ) == 0 ); -#endif - assert( pthread_kill( xTaskToSuspend, SIG_SUSPEND ) == 0); - - sched_yield(); - } - - debug_printf( "Swapped From %li(%s) to %li(%s)\r\n", (long int) xTaskToSuspend, oldTask->pcTaskName, (long int) xTaskToResume, newTask->pcTaskName); } - else - { - // debug_error ("Want %s running \r\n", newTask->pcTaskName ); - } - xServicingTick = pdFALSE; - (void)pthread_mutex_unlock( &xSwappingThreadMutex ); - } - else - { - debug_error( "Pending yield here (portYield has lock - hopefully)\r\n" ); - xPendYield = pdTRUE; - } - - } - else - { - debug_printf( "Pending yield or here\r\n"); - xPendYield = pdTRUE; - } -} -/*-----------------------------------------------------------*/ - -void vPortForciblyEndThread( void *pxTaskToDelete ) -{ -xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; -pthread_t xTaskToDelete; -pthread_t xTaskToResume; -portBASE_TYPE xResult; - - printf("vPortForciblyEndThread\r\n"); - - if ( 0 == pthread_mutex_lock( &xSwappingThreadMutex ) ) - { - 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 ); - /* Pthread Clean-up function will note the cancellation. */ - } - (void)pthread_mutex_unlock( &xSwappingThreadMutex ); - } - else - { - /* Resume the other thread. */ - /* Assert zero - I never fixed this functionality */ - assert( 0 ); - - /* Pthread Clean-up function will note the cancellation. */ - /* Release the execution. */ - uxCriticalNesting = 0; - vPortEnableInterrupts(); - (void)pthread_mutex_unlock( &xSwappingThreadMutex ); - /* Commit suicide */ - pthread_exit( (void *)1 ); - } - } -} -/*-----------------------------------------------------------*/ - -void *prvWaitForStart( void * pvParams ) -{ -xParams * pxParams = ( xParams * )pvParams; -pdTASK_CODE pvCode = pxParams->pxCode; -void * pParams = pxParams->pvParams; - vPortFree( pvParams ); - - pthread_cleanup_push( prvDeleteThread, (void *)pthread_self() ); - - /* want to block suspend when not the active thread */ - sigset_t xSignals; - sigemptyset( &xSignals ); - sigaddset( &xSignals, SIG_SUSPEND ); - assert( pthread_sigmask( SIG_BLOCK, &xSignals, NULL ) == 0); - - /* Because the FreeRTOS creates the TCB stack, which in this implementation */ - /* creates a thread, we need to wait until the task handle is added before */ - /* trying to pause. Must set xSentinel high so the creating task knows we're */ - /* here */ - - debug_printf("Thread started, waiting till handle is added\r\n"); - - xSentinel = 1; - - while( prvGetTaskHandle( pthread_self() ) == NULL ){ - sched_yield(); - } - - debug_printf("Handle added, pausing\r\n"); - - /* Want to delay briefly until we have explicit resume signal as otherwise the */ - /* current task variable might be in the wrong state */ - pauseThread( THREAD_PAUSE_CREATED ); - debug_printf("Starting first run\r\n"); - - sigemptyset( &xSignals ); - assert( pthread_sigmask( SIG_SETMASK, &xSignals, NULL ) == 0); - - pvCode( pParams ); - - pthread_cleanup_pop( 1 ); - return (void *)NULL; -} -/*-----------------------------------------------------------*/ - -void pauseThread( portBASE_TYPE pauseMode ) -{ - debug_printf( "Pausing thread %li. Set xSuspended false\r\n", (long int) pthread_self() ); - -#ifdef RUNNING_THREAD_MUTEX - if( pauseMode != THREAD_PAUSE_CREATED ) - assert( 0 == pthread_mutex_unlock( &xRunningThread ) ); -#endif - -#ifdef COND_SIGNALING - int xResult; - xTaskHandle hTask = prvGetTaskHandle( pthread_self() ); - pthread_cond_t * hCond = prvGetConditionHandle( hTask ); - pthread_mutex_t * hMutex = prvGetMutexHandle( hTask ); - debug_printf("Cond: %li\r\n", *( (long int *) hCond) ); - debug_printf("Mutex: %li\r\n", *( (long int *) hMutex) ); - - struct timeval tv; - struct timespec ts; - gettimeofday( &tv, NULL ); - ts.tv_sec = tv.tv_sec + 0; -#endif - - xSuspended = pdTRUE; - - while (1) { - if( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) && xRunning ) - { - - xStarted = pdTRUE; - -#ifdef RUNNING_THREAD_MUTEX - assert( 0 == pthread_mutex_lock( &xRunningThread ) ); -#endif - debug_error("Resuming\r\n"); - return; - } - else { -#ifdef COND_SIGNALING - gettimeofday( &tv, NULL ); - ts.tv_sec = ts.tv_sec + 1; - ts.tv_nsec = 0; - xResult = pthread_cond_timedwait( hCond, hMutex, &ts ); - assert( xResult != EINVAL ); -#else - /* For windows where conditional signaling is buggy */ - /* It would be wonderful to put a nanosleep here, but since its not reentrant safe */ - /* and there may be a sleep in the main code (this can be called from an ISR) we must */ - /* check this */ - if( pauseMode != THREAD_PAUSE_INTERRUPT ) - usleep(100); - sched_yield(); - -#endif -// debug_error( "Checked my status\r\n" ); - } - - } -} - -void prvSuspendSignalHandler(int sig) -{ -sigset_t xBlockSignals; - - /* This signal is set here instead of pauseThread because it is checked by the tick handler */ - /* which means if there were a swap it should result in a suspend interrupt */ - - debug_error( "Caught signal %i\r\n", sig ); - /* Check that we aren't suspending when we should be running. This bug would need tracking down */ - //assert( pthread_self() != prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - if( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) - { - debug_printf( "Suspend ISR called while this thread still marked active. Reflects buggy behavior in scheduler\r\n" ); - return; - } - - /* Block further suspend signals. They need to go to their thread */ - sigemptyset( &xBlockSignals ); - sigaddset( &xBlockSignals, SIG_SUSPEND ); - assert( pthread_sigmask( SIG_BLOCK, &xBlockSignals, NULL ) == 0); - - pauseThread( THREAD_PAUSE_INTERRUPT ); - -// assert( pthread_self() == prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); - while( pthread_self() != prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ) - { - debug_printf( "Incorrectly woke up. Repausing\r\n" ); - pauseThread( THREAD_PAUSE_INTERRUPT ); - } - - /* Make sure the right thread is resuming */ - assert( pthread_self() == prvGetThreadHandle(xTaskGetCurrentTaskHandle() ) ); - - /* Old synchronization code, may still be required - while( !xHandover ); - assert( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ); */ - - /* Respond to signals again */ - sigemptyset( &xBlockSignals ); - pthread_sigmask( SIG_SETMASK, &xBlockSignals, NULL ); - - debug_printf( "Resuming %li from signal %i\r\n", (long int) pthread_self(), sig ); - - /* Will resume here when the SIG_RESUME signal is received. */ - /* Need to set the interrupts based on the task's critical nesting. */ - if ( uxCriticalNesting == 0 ) - { - vPortEnableInterrupts(); - } - else - { - vPortDisableInterrupts(); - } - debug_printf("Exit\r\n"); -} - -/*-----------------------------------------------------------*/ - -void prvSetupSignalsAndSchedulerPolicy( void ) -{ -/* The following code would allow for configuring the scheduling of this task as a Real-time task. - * The process would then need to be run with higher privileges for it to take affect. -int iPolicy; -int iResult; -int iSchedulerPriority; - iResult = pthread_getschedparam( pthread_self(), &iPolicy, &iSchedulerPriority ); - iResult = pthread_attr_setschedpolicy( &xThreadAttributes, SCHED_FIFO ); - iPolicy = SCHED_FIFO; - iResult = pthread_setschedparam( pthread_self(), iPolicy, &iSchedulerPriority ); */ - -struct sigaction sigsuspendself; -portLONG lIndex; - - debug_printf("prvSetupSignalAndSchedulerPolicy\r\n"); - - pxThreads = ( xThreadState *)pvPortMalloc( sizeof( xThreadState ) * MAX_NUMBER_OF_TASKS ); - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = ( xTaskHandle )NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - - sigsuspendself.sa_flags = 0; - sigsuspendself.sa_handler = prvSuspendSignalHandler; - sigfillset( &sigsuspendself.sa_mask ); - - assert ( 0 == sigaction( SIG_SUSPEND, &sigsuspendself, NULL ) ); -} - -/*-----------------------------------------------------------*/ -pthread_mutex_t * prvGetMutexHandle( xTaskHandle hTask ) -{ -pthread_mutex_t * hMutex; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hMutex = pxThreads[ lIndex ].hMutex; - break; - } - } - return hMutex; -} - -/*-----------------------------------------------------------*/ -xTaskHandle prvGetTaskHandle( pthread_t hThread ) -{ -xTaskHandle hTask = NULL; -portLONG lIndex; - - /* If not initialized yet */ - if( pxThreads == NULL ) return NULL; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == hThread ) - { - hTask = pxThreads[ lIndex ].hTask; - break; - } - } - return hTask; -} - -/*-----------------------------------------------------------*/ -pthread_cond_t * prvGetConditionHandle( xTaskHandle hTask ) -{ -pthread_cond_t * hCond; -portLONG lIndex; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - debug_printf( "Found condition on %i task\r\n", lIndex ); - return pxThreads[ lIndex ].hCond; - break; - } - } - printf( "Failed to get handle, pausing then recursing\r\n" ); - usleep(1000); - return prvGetConditionHandle( hTask ); - assert(0); - return hCond; -} - -/*-----------------------------------------------------------*/ -pthread_t prvGetThreadHandle( xTaskHandle hTask ) -{ - pthread_t hThread = ( pthread_t )NULL; - portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hTask == hTask ) - { - hThread = pxThreads[ lIndex ].hThread; - break; - } - } - return hThread; -} -/*-----------------------------------------------------------*/ - -portLONG prvGetFreeThreadState( void ) -{ -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )NULL ) - { - break; - } - } - - if ( MAX_NUMBER_OF_TASKS == lIndex ) - { - printf( "No more free threads, please increase the maximum.\n" ); - lIndex = 0; - vPortEndScheduler(); - } - - return lIndex; -} -/*-----------------------------------------------------------*/ - -void prvSetTaskCriticalNesting( pthread_t xThreadId, unsigned portBASE_TYPE uxNesting ) -{ -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - pxThreads[ lIndex ].uxCriticalNesting = uxNesting; - break; - } - } -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE prvGetTaskCriticalNesting( pthread_t xThreadId ) -{ -unsigned portBASE_TYPE uxNesting = 0; -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == xThreadId ) - { - uxNesting = pxThreads[ lIndex ].uxCriticalNesting; - break; - } - } - return uxNesting; -} -/*-----------------------------------------------------------*/ - -void prvDeleteThread( void *xThreadId ) -{ -portLONG lIndex; - - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == ( pthread_t )xThreadId ) - { - pxThreads[ lIndex ].hThread = (pthread_t)NULL; - pxThreads[ lIndex ].hTask = (xTaskHandle)NULL; - if ( pxThreads[ lIndex ].uxCriticalNesting > 0 ) - { - uxCriticalNesting = 0; - vPortEnableInterrupts(); - } - pxThreads[ lIndex ].uxCriticalNesting = 0; - break; - } - } -} -/*-----------------------------------------------------------*/ - -void vPortAddTaskHandle( void *pxTaskHandle ) -{ -portLONG lIndex; - - debug_printf("vPortAddTaskHandle\r\n"); - - pxThreads[ lIndexOfLastAddedTask ].hTask = ( xTaskHandle )pxTaskHandle; - for ( lIndex = 0; lIndex < MAX_NUMBER_OF_TASKS; lIndex++ ) - { - if ( pxThreads[ lIndex ].hThread == pxThreads[ lIndexOfLastAddedTask ].hThread ) - { - if ( pxThreads[ lIndex ].hTask != pxThreads[ lIndexOfLastAddedTask ].hTask ) - { - pxThreads[ lIndex ].hThread = ( pthread_t )NULL; - pxThreads[ lIndex ].hTask = NULL; - pxThreads[ lIndex ].uxCriticalNesting = 0; - } - } - } - usleep(10000); -} -/*-----------------------------------------------------------*/ - -void vPortFindTicksPerSecond( void ) -{ - - /* Needs to be reasonably high for accuracy. */ - unsigned long ulTicksPerSecond = sysconf(_SC_CLK_TCK); - printf( "Timer Resolution for Run TimeStats is %ld ticks per second.\n", ulTicksPerSecond ); -} -/*-----------------------------------------------------------*/ - -unsigned long ulPortGetTimerValue( void ) -{ -struct tms xTimes; - - unsigned long ulTotalTime = times( &xTimes ); - /* Return the application code times. - * The timer only increases when the application code is actually running - * which means that the total execution times should add up to 100%. - */ - return ( unsigned long ) xTimes.tms_utime; - - /* Should check ulTotalTime for being clock_t max minus 1. */ - (void)ulTotalTime; -} -/*-----------------------------------------------------------*/ diff --git a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/tasks.c b/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/tasks.c deleted file mode 100644 index 20f9ab309..000000000 --- a/flight/PiOS.posix/posix/Libraries/FreeRTOS/Source/portable/GCC/Posix/peabody124/tasks.c +++ /dev/null @@ -1,2332 +0,0 @@ -/* - FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd. - - *************************************************************************** - * * - * If you are: * - * * - * + New to FreeRTOS, * - * + Wanting to learn FreeRTOS or multitasking in general quickly * - * + Looking for basic training, * - * + Wanting to improve your FreeRTOS skills and productivity * - * * - * then take a look at the FreeRTOS eBook * - * * - * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * - * http://www.FreeRTOS.org/Documentation * - * * - * A pdf reference manual is also available. Both are usually delivered * - * to your inbox within 20 minutes to two hours when purchased between 8am * - * and 8pm GMT (although please allow up to 24 hours in case of * - * exceptional circumstances). Thank you for your support! * - * * - *************************************************************************** - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation AND MODIFIED BY the FreeRTOS exception. - ***NOTE*** The exception to the GPL is included to allow you to distribute - a combined work that includes FreeRTOS without being obliged to provide the - source code for proprietary components outside of the FreeRTOS kernel. - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. You should have received a copy of the GNU General Public - License and the FreeRTOS license exception along with FreeRTOS; if not it - can be viewed here: http://www.freertos.org/a00114.html and also obtained - by writing to Richard Barry, contact details for whom are available on the - FreeRTOS WEB site. - - 1 tab == 4 spaces! - - http://www.FreeRTOS.org - Documentation, latest information, license and - contact details. - - http://www.SafeRTOS.com - A version that is certified for use in safety - critical systems. - - http://www.OpenRTOS.com - Commercial support, development, porting, - licensing and training services. -*/ - - -#include -#include -#include -#include -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "StackMacros.h" - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* - * Macro to define the amount of stack available to the idle task. - */ -#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE - -/* - * Task control block. A task control block (TCB) is allocated to each task, - * and stores the context of the task. - */ -typedef struct tskTaskControlBlock -{ - volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */ - - #if ( portUSING_MPU_WRAPPERS == 1 ) - xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */ - #endif - - xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */ - xListItem xEventListItem; /*< List item used to place the TCB in event lists. */ - unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */ - portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */ - signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ - - #if ( portSTACK_GROWTH > 0 ) - portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */ - #endif - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - unsigned portBASE_TYPE uxCriticalNesting; - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */ - #endif - - #if ( configUSE_MUTEXES == 1 ) - unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */ - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - pdTASK_HOOK_CODE pxTaskTag; - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */ - #endif - -} tskTCB; - - -/* - * Some kernel aware debuggers require data to be viewed to be global, rather - * than file scope. - */ -#ifdef portREMOVE_STATIC_QUALIFIER - #define static -#endif - -/*lint -e956 */ -PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL; - -/* Lists for ready and blocked tasks. --------------------*/ - -PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */ -PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */ -PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */ -PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */ - -#if ( INCLUDE_vTaskDelete == 1 ) - - PRIVILEGED_DATA static volatile xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */ - PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0; - -#endif - -#if ( INCLUDE_vTaskSuspend == 1 ) - - PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */ - -#endif - -/* File private variables. --------------------------------*/ -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0; -PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY; -PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0; -PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE; -PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0; -PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0; - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - PRIVILEGED_DATA static char pcStatsString[ 50 ] ; - PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */ - static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION; - -#endif - -/* Debugging and trace facilities private variables and macros. ------------*/ - -/* - * The value used to fill the stack of a task when the task is created. This - * is used purely for checking the high water mark for tasks. - */ -#define tskSTACK_FILL_BYTE ( 0xa5 ) - -/* - * Macros used by vListTask to indicate which state a task is in. - */ -#define tskBLOCKED_CHAR ( ( signed char ) 'B' ) -#define tskREADY_CHAR ( ( signed char ) 'R' ) -#define tskDELETED_CHAR ( ( signed char ) 'D' ) -#define tskSUSPENDED_CHAR ( ( signed char ) 'S' ) - -/* - * Macros and private variables used by the trace facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) ) - PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer; - PRIVILEGED_DATA static signed char *pcTraceBufferStart; - PRIVILEGED_DATA static signed char *pcTraceBufferEnd; - PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE; - static unsigned portBASE_TYPE uxPreviousTask = 255; - PRIVILEGED_DATA static char pcStatusString[ 50 ]; - -#endif - -/*-----------------------------------------------------------*/ - -/* - * Macro that writes a trace of scheduler activity to a buffer. This trace - * shows which task is running when and is very useful as a debugging tool. - * As this macro is called each context switch it is a good idea to undefine - * it if not using the facility. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - #define vWriteTraceToBuffer() \ - { \ - if( xTracing ) \ - { \ - if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \ - { \ - if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \ - { \ - uxPreviousTask = pxCurrentTCB->uxTCBNumber; \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \ - pcTraceBuffer += sizeof( unsigned long ); \ - *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \ - pcTraceBuffer += sizeof( unsigned long ); \ - } \ - else \ - { \ - xTracing = pdFALSE; \ - } \ - } \ - } \ - } - -#else - - #define vWriteTraceToBuffer() - -#endif -/*-----------------------------------------------------------*/ - -/* - * Place the task represented by pxTCB into the appropriate ready queue for - * the task. It is inserted at the end of the list. One quirk of this is - * that if the task being inserted is at the same priority as the currently - * executing task, then it will only be rescheduled after the currently - * executing task has been rescheduled. - */ -#define prvAddTaskToReadyQueue( pxTCB ) \ -{ \ - if( pxTCB->uxPriority > uxTopReadyPriority ) \ - { \ - uxTopReadyPriority = pxTCB->uxPriority; \ - } \ - vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \ -} -/*-----------------------------------------------------------*/ - -/* - * Macro that looks at the list of tasks that are currently delayed to see if - * any require waking. - * - * Tasks are stored in the queue in the order of their wake time - meaning - * once one tasks has been found whose timer has not expired we need not look - * any further down the list. - */ -#define prvCheckDelayedTasks() \ -{ \ -register tskTCB *pxTCB; \ - \ - while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \ - { \ - if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \ - { \ - break; \ - } \ - vListRemove( &( pxTCB->xGenericListItem ) ); \ - /* Is the task waiting on an event also? */ \ - if( pxTCB->xEventListItem.pvContainer ) \ - { \ - vListRemove( &( pxTCB->xEventListItem ) ); \ - } \ - prvAddTaskToReadyQueue( pxTCB ); \ - } \ -} -/*-----------------------------------------------------------*/ - -/* - * Several functions take an xTaskHandle parameter that can optionally be NULL, - * where NULL is used to indicate that the handle of the currently executing - * task should be used in place of the parameter. This macro simply checks to - * see if the parameter is NULL and returns a pointer to the appropriate TCB. - */ -#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle ) - - -/* File private functions. --------------------------------*/ - -/* - * Utility to ready a TCB for a given task. Mainly just copies the parameters - * into the TCB structure. - */ -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION; - -/* - * Utility to ready all the lists used by the scheduler. This is called - * automatically upon the creation of the first task. - */ -static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION; - -/* - * The idle task, which as all tasks is implemented as a never ending loop. - * The idle task is automatically created and added to the ready lists upon - * creation of the first user task. - * - * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ); - -/* - * Utility to free all memory allocated by the scheduler to hold a TCB, - * including the stack pointed to by the TCB. - * - * This does not free memory allocated by the task itself (i.e. memory - * allocated by calls to pvPortMalloc from within the tasks application code). - */ -#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) - - static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION; - -#endif - -/* - * Used only by the idle task. This checks to see if anything has been placed - * in the list of tasks waiting to be deleted. If so the task is cleaned up - * and its TCB deleted. - */ -static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION; - -/* - * Allocates memory from the heap for a TCB and associated stack. Checks the - * allocation was successful. - */ -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION; - -/* - * Called from vTaskList. vListTasks details all the tasks currently under - * control of the scheduler. The tasks may be in one of a number of lists. - * prvListTaskWithinSingleList accepts a list and details the tasks from - * within just that list. - * - * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM - * NORMAL APPLICATION CODE. - */ -#if ( configUSE_TRACE_FACILITY == 1 ) - - static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION; - -#endif - -/* - * When a task is created, the stack of the task is filled with a known value. - * This function determines the 'high water mark' of the task stack by - * determining how much of the stack remains at the original preset value. - */ -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - - static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION; - -#endif - - -/*lint +e956 */ - - - -/*----------------------------------------------------------- - * TASK CREATION API documented in task.h - *----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions ) -{ -signed portBASE_TYPE xReturn; -tskTCB * pxNewTCB; - - /* Allocate the memory required by the TCB and stack for the new task, - checking that the allocation was successful. */ - pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer ); - - if( pxNewTCB != NULL ) - { - portSTACK_TYPE *pxTopOfStack; - - #if( portUSING_MPU_WRAPPERS == 1 ) - /* Should the task be created in privileged mode? */ - portBASE_TYPE xRunPrivileged; - if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 ) - { - xRunPrivileged = pdTRUE; - } - else - { - xRunPrivileged = pdFALSE; - } - uxPriority &= ~portPRIVILEGE_BIT; - #endif /* portUSING_MPU_WRAPPERS == 1 */ - - /* Calculate the top of stack address. This depends on whether the - stack grows from high memory to low (as per the 80x86) or visa versa. - portSTACK_GROWTH is used to make the result positive or negative as - required by the port. */ - #if( portSTACK_GROWTH < 0 ) - { - pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); - pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) ); - } - #else - { - pxTopOfStack = pxNewTCB->pxStack; - - /* If we want to use stack checking on architectures that use - a positive stack growth direction then we also need to store the - other extreme of the stack space. */ - pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 ); - } - #endif - - /* Setup the newly allocated TCB with the initial state of the task. */ - prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth ); - - /* Initialize the TCB stack to look as if the task was already running, - but had been interrupted by the scheduler. The return address is set - to the start of the task function. Once the stack has been initialised - the top of stack variable is updated. */ - #if( portUSING_MPU_WRAPPERS == 1 ) - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged ); - } - #else - { - pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters ); - } - #endif - - /* We are going to manipulate the task queues to add this task to a - ready list, so must make sure no interrupts occur. */ - portENTER_CRITICAL(); - { - uxCurrentNumberOfTasks++; - if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 ) - { - /* As this is the first task it must also be the current task. */ - pxCurrentTCB = pxNewTCB; - - /* This is the first task to be created so do the preliminary - initialisation required. We will not recover if this call - fails, but we will report the failure. */ - prvInitialiseTaskLists(); - } - else - { - /* If the scheduler is not already running, make this task the - current task if it is the highest priority task to be created - so far. */ - if( xSchedulerRunning == pdFALSE ) - { - if( pxCurrentTCB->uxPriority <= uxPriority ) - { - pxCurrentTCB = pxNewTCB; - } - } - } - - /* Remember the top priority to make context switching faster. Use - the priority in pxNewTCB as this has been capped to a valid value. */ - if( pxNewTCB->uxPriority > uxTopUsedPriority ) - { - uxTopUsedPriority = pxNewTCB->uxPriority; - } - - #if ( configUSE_TRACE_FACILITY == 1 ) - { - /* Add a counter into the TCB for tracing only. */ - pxNewTCB->uxTCBNumber = uxTaskNumber; - } - #endif - uxTaskNumber++; - - prvAddTaskToReadyQueue( pxNewTCB ); - - xReturn = pdPASS; - traceTASK_CREATE( pxNewTCB ); - } - portEXIT_CRITICAL(); - } - else - { - xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; - traceTASK_CREATE_FAILED( pxNewTCB ); - } - - if( xReturn == pdPASS ) - { - if( ( void * ) pxCreatedTask != NULL ) - { - /* Pass the TCB out - in an anonymous way. The calling function/ - task can use this as a handle to delete the task later if - required.*/ - *pxCreatedTask = ( xTaskHandle ) pxNewTCB; - } - - if( xSchedulerRunning != pdFALSE ) - { - /* If the created task is of a higher priority than the current task - then it should run now. */ - if( pxCurrentTCB->uxPriority < uxPriority ) - { - portYIELD_WITHIN_API(); - } - } - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelete == 1 ) - - void vTaskDelete( xTaskHandle pxTaskToDelete ) - { - tskTCB *pxTCB; - - portENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - deleted. */ - if( pxTaskToDelete == pxCurrentTCB ) - { - pxTaskToDelete = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToDelete ); - - /* Remove task from the ready list and place in the termination list. - This will stop the task from be scheduled. The idle task will check - the termination list and free up any memory allocated by the - scheduler for the TCB and stack. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) ); - - /* Increment the ucTasksDeleted variable so the idle task knows - there is a task that has been deleted and that it should therefore - check the xTasksWaitingTermination list. */ - ++uxTasksDeleted; - - /* Increment the uxTaskNumberVariable also so kernel aware debuggers - can detect that the task lists need re-generating. */ - uxTaskNumber++; - - traceTASK_DELETE( pxTCB ); - } - portEXIT_CRITICAL(); - - /* Force a reschedule if we have just deleted the current task. */ - if( xSchedulerRunning != pdFALSE ) - { - if( ( void * ) pxTaskToDelete == NULL ) - { - portYIELD_WITHIN_API(); - } - } - } - -#endif - - - - - - -/*----------------------------------------------------------- - * TASK CONTROL API documented in task.h - *----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelayUntil == 1 ) - - void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement ) - { - portTickType xTimeToWake; - portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE; - - vTaskSuspendAll(); - { - /* Generate the tick time at which the task wants to wake. */ - xTimeToWake = *pxPreviousWakeTime + xTimeIncrement; - - if( xTickCount < *pxPreviousWakeTime ) - { - /* The tick count has overflowed since this function was - lasted called. In this case the only time we should ever - actually delay is if the wake time has also overflowed, - and the wake time is greater than the tick time. When this - is the case it is as if neither time had overflowed. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) ) - { - xShouldDelay = pdTRUE; - } - } - else - { - /* The tick time has not overflowed. In this case we will - delay if either the wake time has overflowed, and/or the - tick time is less than the wake time. */ - if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) ) - { - xShouldDelay = pdTRUE; - } - } - - /* Update the wake time ready for the next call. */ - *pxPreviousWakeTime = xTimeToWake; - - if( xShouldDelay ) - { - traceTASK_DELAY_UNTIL(); - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the - overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - } - xAlreadyYielded = xTaskResumeAll(); - - /* Force a reschedule if xTaskResumeAll has not already done so, we may - have put ourselves to sleep. */ - if( !xAlreadyYielded ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskDelay == 1 ) - - void vTaskDelay( portTickType xTicksToDelay ) - { - portTickType xTimeToWake; - signed portBASE_TYPE xAlreadyYielded = pdFALSE; - - /* A delay time of zero just forces a reschedule. */ - if( xTicksToDelay > ( portTickType ) 0 ) - { - vTaskSuspendAll(); - { - traceTASK_DELAY(); - - /* A task that is removed from the event list while the - scheduler is suspended will not get placed in the ready - list or removed from the blocked list until the scheduler - is resumed. - - This task cannot be in an event list as it is the currently - executing task. */ - - /* Calculate the time to wake - this may overflow but this is - not a problem. */ - xTimeToWake = xTickCount + xTicksToDelay; - - /* We must remove ourselves from the ready list before adding - ourselves to the blocked list as the same list item is used for - both lists. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - /* The list item will be inserted in wake time order. */ - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the - overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the - current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - xAlreadyYielded = xTaskResumeAll(); - } - - /* Force a reschedule if xTaskResumeAll has not already done so, we may - have put ourselves to sleep. */ - if( !xAlreadyYielded ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_uxTaskPriorityGet == 1 ) - - unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ) - { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxReturn; - - portENTER_CRITICAL(); - { - /* If null is passed in here then we are changing the - priority of the calling function. */ - pxTCB = prvGetTCBFromHandle( pxTask ); - uxReturn = pxTCB->uxPriority; - } - portEXIT_CRITICAL(); - - return uxReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskPrioritySet == 1 ) - - void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority ) - { - tskTCB *pxTCB; - unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE; - - /* Ensure the new priority is valid. */ - if( uxNewPriority >= configMAX_PRIORITIES ) - { - uxNewPriority = configMAX_PRIORITIES - 1; - } - - portENTER_CRITICAL(); - { - if( pxTask == pxCurrentTCB ) - { - pxTask = NULL; - } - - /* If null is passed in here then we are changing the - priority of the calling function. */ - pxTCB = prvGetTCBFromHandle( pxTask ); - - traceTASK_PRIORITY_SET( pxTask, uxNewPriority ); - - #if ( configUSE_MUTEXES == 1 ) - { - uxCurrentPriority = pxTCB->uxBasePriority; - } - #else - { - uxCurrentPriority = pxTCB->uxPriority; - } - #endif - - if( uxCurrentPriority != uxNewPriority ) - { - /* The priority change may have readied a task of higher - priority than the calling task. */ - if( uxNewPriority > uxCurrentPriority ) - { - if( pxTask != NULL ) - { - /* The priority of another task is being raised. If we - were raising the priority of the currently running task - there would be no need to switch as it must have already - been the highest priority task. */ - xYieldRequired = pdTRUE; - } - } - else if( pxTask == NULL ) - { - /* Setting our own priority down means there may now be another - task of higher priority that is ready to execute. */ - xYieldRequired = pdTRUE; - } - - - - #if ( configUSE_MUTEXES == 1 ) - { - /* Only change the priority being used if the task is not - currently using an inherited priority. */ - if( pxTCB->uxBasePriority == pxTCB->uxPriority ) - { - pxTCB->uxPriority = uxNewPriority; - } - - /* The base priority gets set whatever. */ - pxTCB->uxBasePriority = uxNewPriority; - } - #else - { - pxTCB->uxPriority = uxNewPriority; - } - #endif - - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); - - /* If the task is in the blocked or suspended list we need do - nothing more than change it's priority variable. However, if - the task is in a ready list it needs to be removed and placed - in the queue appropriate to its new priority. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) ) - { - /* The task is currently in its ready list - remove before adding - it to it's new ready list. As we are in a critical section we - can do this even if the scheduler is suspended. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - - if( xYieldRequired == pdTRUE ) - { - portYIELD_WITHIN_API(); - } - } - } - portEXIT_CRITICAL(); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - void vTaskSuspend( xTaskHandle pxTaskToSuspend ) - { - tskTCB *pxTCB; - - portENTER_CRITICAL(); - { - /* Ensure a yield is performed if the current task is being - suspended. */ - if( pxTaskToSuspend == pxCurrentTCB ) - { - pxTaskToSuspend = NULL; - } - - /* If null is passed in here then we are suspending ourselves. */ - pxTCB = prvGetTCBFromHandle( pxTaskToSuspend ); - - traceTASK_SUSPEND( pxTCB ); - - /* Remove task from the ready/delayed list and place in the suspended list. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Is the task waiting on an event also? */ - if( pxTCB->xEventListItem.pvContainer ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - } - - vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ); - } - portEXIT_CRITICAL(); - - /* We may have just suspended the current task. */ - if( ( void * ) pxTaskToSuspend == NULL ) - { - portYIELD_WITHIN_API(); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask ) - { - portBASE_TYPE xReturn = pdFALSE; - const tskTCB * const pxTCB = ( tskTCB * ) xTask; - - /* Is the task we are attempting to resume actually in the - suspended list? */ - if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE ) - { - /* Has the task already been resumed from within an ISR? */ - if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE ) - { - /* Is it in the suspended list because it is in the - Suspended state? It is possible to be in the suspended - list because it is blocked on a task with no timeout - specified. */ - if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE ) - { - xReturn = pdTRUE; - } - } - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_vTaskSuspend == 1 ) - - void vTaskResume( xTaskHandle pxTaskToResume ) - { - tskTCB *pxTCB; - - /* Remove the task from whichever list it is currently in, and place - it in the ready list. */ - pxTCB = ( tskTCB * ) pxTaskToResume; - - /* The parameter cannot be NULL as it is impossible to resume the - currently executing task. */ - if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) ) - { - portENTER_CRITICAL(); - { - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) - { - traceTASK_RESUME( pxTCB ); - - /* As we are in a critical section we can access the ready - lists even if the scheduler is suspended. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - - /* We may have just resumed a higher priority task. */ - if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - /* This yield may not cause the task just resumed to run, but - will leave the lists in the correct state for the next yield. */ - portYIELD_WITHIN_API(); - } - } - } - portEXIT_CRITICAL(); - } - } - -#endif - -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - - portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume ) - { - portBASE_TYPE xYieldRequired = pdFALSE; - tskTCB *pxTCB; - - pxTCB = ( tskTCB * ) pxTaskToResume; - - if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE ) - { - traceTASK_RESUME_FROM_ISR( pxTCB ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - } - else - { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed, at which point a - yield will be performed if necessary. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) ); - } - } - - return xYieldRequired; - } - -#endif - - - - -/*----------------------------------------------------------- - * PUBLIC SCHEDULER CONTROL documented in task.h - *----------------------------------------------------------*/ - - -void vTaskStartScheduler( void ) -{ -portBASE_TYPE xReturn; - - /* Add the idle task at the lowest priority. */ - xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL ); - - if( xReturn == pdPASS ) - { - /* Interrupts are turned off here, to ensure a tick does not occur - before or during the call to xPortStartScheduler(). The stacks of - the created tasks contain a status word with interrupts switched on - so interrupts will automatically get re-enabled when the first task - starts to run. - - STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE - DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */ - portDISABLE_INTERRUPTS(); - - xSchedulerRunning = pdTRUE; - xTickCount = ( portTickType ) 0; - - /* If configGENERATE_RUN_TIME_STATS is defined then the following - macro must be defined to configure the timer/counter used to generate - the run time counter time base. */ - portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); - - /* Setting up the timer tick is hardware specific and thus in the - portable interface. */ - if( xPortStartScheduler() ) - { - /* Should not reach here as if the scheduler is running the - function will not return. */ - } - else - { - /* Should only reach here if a task calls xTaskEndScheduler(). */ - } - } -} -/*-----------------------------------------------------------*/ - -void vTaskEndScheduler( void ) -{ - /* Stop the scheduler interrupts and call the portable scheduler end - routine so the original ISRs can be restored if necessary. The port - layer must ensure interrupts enable bit is left in the correct state. */ - portDISABLE_INTERRUPTS(); - xSchedulerRunning = pdFALSE; - vPortEndScheduler(); -} -/*----------------------------------------------------------*/ - -void vTaskSuspendAll( void ) -{ - /* A critical section is not required as the variable is of type - portBASE_TYPE. */ - ++uxSchedulerSuspended; -} -/*----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskResumeAll( void ) -{ -register tskTCB *pxTCB; -signed portBASE_TYPE xAlreadyYielded = pdFALSE; - - /* It is possible that an ISR caused a task to be removed from an event - list while the scheduler was suspended. If this was the case then the - removed task will have been added to the xPendingReadyList. Once the - scheduler has been resumed it is safe to move all the pending ready - tasks from this list into their appropriate ready list. */ - portENTER_CRITICAL(); - { - --uxSchedulerSuspended; - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 ) - { - portBASE_TYPE xYieldRequired = pdFALSE; - - /* Move any readied tasks from the pending list into the - appropriate ready list. */ - while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL ) - { - vListRemove( &( pxTCB->xEventListItem ) ); - vListRemove( &( pxTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxTCB ); - - /* If we have moved a task that has a priority higher than - the current task then we should yield. */ - if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - xYieldRequired = pdTRUE; - } - } - - /* If any ticks occurred while the scheduler was suspended then - they should be processed now. This ensures the tick count does not - slip, and that any delayed tasks are resumed at the correct time. */ - if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 ) - { - while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 ) - { - vTaskIncrementTick(); - --uxMissedTicks; - } - - /* As we have processed some ticks it is appropriate to yield - to ensure the highest priority task that is ready to run is - the task actually running. */ - #if configUSE_PREEMPTION == 1 - { - xYieldRequired = pdTRUE; - } - #endif - } - - if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) ) - { - xAlreadyYielded = pdTRUE; - xMissedYield = pdFALSE; - portYIELD_WITHIN_API(); - } - } - } - } - portEXIT_CRITICAL(); - - return xAlreadyYielded; -} - - - - - - -/*----------------------------------------------------------- - * PUBLIC TASK UTILITIES documented in task.h - *----------------------------------------------------------*/ - - - -portTickType xTaskGetTickCount( void ) -{ -portTickType xTicks; - - /* Critical section required if running on a 16 bit processor. */ - portENTER_CRITICAL(); - { - xTicks = xTickCount; - } - portEXIT_CRITICAL(); - - return xTicks; -} -/*-----------------------------------------------------------*/ - -unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void ) -{ - /* A critical section is not required because the variables are of type - portBASE_TYPE. */ - return uxCurrentNumberOfTasks; -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskList( signed char *pcWriteBuffer ) - { - unsigned portBASE_TYPE uxQueue; - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - /* Run through all the lists that could potentially contain a TCB and - report the task name, state and stack high water mark. */ - - pcWriteBuffer[ 0 ] = ( signed char ) 0x00; - strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); - - uxQueue = uxTopUsedPriority + 1; - - do - { - uxQueue--; - - if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR ); - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( !listLIST_IS_EMPTY( pxDelayedTaskList ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR ); - } - - if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR ); - } - - #if( INCLUDE_vTaskDelete == 1 ) - { - if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR ); - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) - { - prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR ); - } - } - #endif - } - xTaskResumeAll(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - void vTaskGetRunTimeStats( signed char *pcWriteBuffer ) - { - unsigned portBASE_TYPE uxQueue; - unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); - - /* This is a VERY costly function that should be used for debug only. - It leaves interrupts disabled for a LONG time. */ - - vTaskSuspendAll(); - { - /* Run through all the lists that could potentially contain a TCB, - generating a table of run timer percentages in the provided - buffer. */ - - pcWriteBuffer[ 0 ] = ( signed char ) 0x00; - strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" ); - - uxQueue = uxTopUsedPriority + 1; - - do - { - uxQueue--; - - if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime ); - } - }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - if( !listLIST_IS_EMPTY( pxDelayedTaskList ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime ); - } - - if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime ); - } - - #if ( INCLUDE_vTaskDelete == 1 ) - { - if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime ); - } - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) - { - prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime ); - } - } - #endif - } - xTaskResumeAll(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize ) - { - portENTER_CRITICAL(); - { - pcTraceBuffer = ( signed char * )pcBuffer; - pcTraceBufferStart = pcBuffer; - pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE ); - xTracing = pdTRUE; - } - portEXIT_CRITICAL(); - } - -#endif -/*----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - unsigned long ulTaskEndTrace( void ) - { - unsigned long ulBufferLength; - - portENTER_CRITICAL(); - xTracing = pdFALSE; - portEXIT_CRITICAL(); - - ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart ); - - return ulBufferLength; - } - -#endif - - - -/*----------------------------------------------------------- - * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES - * documented in task.h - *----------------------------------------------------------*/ - - -void vTaskIncrementTick( void ) -{ - /* Called by the portable layer each time a tick interrupt occurs. - Increments the tick then checks to see if the new tick value will cause any - tasks to be unblocked. */ - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - ++xTickCount; - if( xTickCount == ( portTickType ) 0 ) - { - xList *pxTemp; - - /* Tick count has overflowed so we need to swap the delay lists. - If there are any items in pxDelayedTaskList here then there is - an error! */ - pxTemp = pxDelayedTaskList; - pxDelayedTaskList = pxOverflowDelayedTaskList; - pxOverflowDelayedTaskList = pxTemp; - xNumOfOverflows++; - } - - /* See if this tick has made a timeout expire. */ - prvCheckDelayedTasks(); - } - else - { - ++uxMissedTicks; - - /* The tick hook gets called at regular intervals, even if the - scheduler is locked. */ - #if ( configUSE_TICK_HOOK == 1 ) - { - extern void vApplicationTickHook( void ); - - vApplicationTickHook(); - } - #endif - } - - #if ( configUSE_TICK_HOOK == 1 ) - { - extern void vApplicationTickHook( void ); - - /* Guard against the tick hook being called when the missed tick - count is being unwound (when the scheduler is being unlocked. */ - if( uxMissedTicks == 0 ) - { - vApplicationTickHook(); - } - } - #endif - - traceTASK_INCREMENT_TICK( xTickCount ); -} -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) - - void vTaskCleanUpResources( void ) - { - unsigned short usQueue; - volatile tskTCB *pxTCB; - - usQueue = ( unsigned short ) uxTopUsedPriority + ( unsigned short ) 1; - - /* Remove any TCB's from the ready queues. */ - do - { - usQueue--; - - while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - }while( usQueue > ( unsigned short ) tskIDLE_PRIORITY ); - - /* Remove any TCB's from the delayed queue. */ - while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - - /* Remove any TCB's from the overflow delayed queue. */ - while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - - while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) ) - { - listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList ); - vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ); - - prvDeleteTCB( ( tskTCB * ) pxTCB ); - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue ) - { - tskTCB *xTCB; - - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - portENTER_CRITICAL(); - xTCB->pxTaskTag = pxTagValue; - portEXIT_CRITICAL(); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask ) - { - tskTCB *xTCB; - pdTASK_HOOK_CODE xReturn; - - /* If xTask is NULL then we are setting our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - /* Save the hook function in the TCB. A critical section is required as - the value can be accessed from an interrupt. */ - portENTER_CRITICAL(); - xReturn = xTCB->pxTaskTag; - portEXIT_CRITICAL(); - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_APPLICATION_TASK_TAG == 1 ) - - portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter ) - { - tskTCB *xTCB; - portBASE_TYPE xReturn; - - /* If xTask is NULL then we are calling our own task hook. */ - if( xTask == NULL ) - { - xTCB = ( tskTCB * ) pxCurrentTCB; - } - else - { - xTCB = ( tskTCB * ) xTask; - } - - if( xTCB->pxTaskTag != NULL ) - { - xReturn = xTCB->pxTaskTag( pvParameter ); - } - else - { - xReturn = pdFAIL; - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -void vTaskSwitchContext( void ) -{ - if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE ) - { - /* The scheduler is currently suspended - do not allow a context - switch. */ - xMissedYield = pdTRUE; - return; - } - - traceTASK_SWITCHED_OUT(); - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE(); - - /* Add the amount of time the task has been running to the accumulated - time so far. The time the task started running was stored in - ulTaskSwitchedInTime. Note that there is no overflow protection here - so count values are only valid until the timer overflows. Generally - this will be about 1 hour assuming a 1uS timer increment. */ - pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime ); - ulTaskSwitchedInTime = ulTempCounter; - } - #endif - - taskFIRST_CHECK_FOR_STACK_OVERFLOW(); - taskSECOND_CHECK_FOR_STACK_OVERFLOW(); - - /* Find the highest priority queue that contains ready tasks. */ - while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) - { - --uxTopReadyPriority; - } - - /* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the tasks of the - same priority get an equal share of the processor time. */ - listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); - - traceTASK_SWITCHED_IN(); - vWriteTraceToBuffer(); -} -/*-----------------------------------------------------------*/ - -void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait ) -{ -portTickType xTimeToWake; - - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. */ - - /* Place the event list item of the TCB in the appropriate event list. - This is placed in the list in priority order so the highest priority task - is the first to be woken by the event. */ - vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) ); - - /* We must remove ourselves from the ready list before adding ourselves - to the blocked list as the same list item is used for both lists. We have - exclusive access to the ready lists as the scheduler is locked. */ - vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - if( xTicksToWait == portMAX_DELAY ) - { - /* Add ourselves to the suspended task list instead of a delayed task - list to ensure we are not woken by a timing event. We will block - indefinitely. */ - vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - } - #else - { - /* Calculate the time at which the task should be woken if the event does - not occur. This may overflow but this doesn't matter. */ - xTimeToWake = xTickCount + xTicksToWait; - - listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake ); - - if( xTimeToWake < xTickCount ) - { - /* Wake time has overflowed. Place this item in the overflow list. */ - vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - else - { - /* The wake time has not overflowed, so we can use the current block list. */ - vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ); - } - } - #endif -} -/*-----------------------------------------------------------*/ - -signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList ) -{ -tskTCB *pxUnblockedTCB; -portBASE_TYPE xReturn; - - /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE - SCHEDULER SUSPENDED. It can also be called from within an ISR. */ - - /* The event list is sorted in priority order, so we can remove the - first in the list, remove the TCB from the delayed list, and add - it to the ready list. - - If an event is for a queue that is locked then this function will never - get called - the lock count on the queue will get modified instead. This - means we can always expect exclusive access to the event list here. */ - pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); - vListRemove( &( pxUnblockedTCB->xEventListItem ) ); - - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - vListRemove( &( pxUnblockedTCB->xGenericListItem ) ); - prvAddTaskToReadyQueue( pxUnblockedTCB ); - } - else - { - /* We cannot access the delayed or ready lists, so will hold this - task pending until the scheduler is resumed. */ - vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) ); - } - - if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority ) - { - /* Return true if the task removed from the event list has - a higher priority than the calling task. This allows - the calling task to know if it should force a context - switch now. */ - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut ) -{ - pxTimeOut->xOverflowCount = xNumOfOverflows; - pxTimeOut->xTimeOnEntering = xTickCount; -} -/*-----------------------------------------------------------*/ - -portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait ) -{ -portBASE_TYPE xReturn; - - portENTER_CRITICAL(); - { - #if ( INCLUDE_vTaskSuspend == 1 ) - /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is - the maximum block time then the task should block indefinitely, and - therefore never time out. */ - if( *pxTicksToWait == portMAX_DELAY ) - { - xReturn = pdFALSE; - } - else /* We are not blocking indefinitely, perform the checks below. */ - #endif - - if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) ) - { - /* The tick count is greater than the time at which vTaskSetTimeout() - was called, but has also overflowed since vTaskSetTimeOut() was called. - It must have wrapped all the way around and gone past us again. This - passed since vTaskSetTimeout() was called. */ - xReturn = pdTRUE; - } - else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait ) - { - /* Not a genuine timeout. Adjust parameters for time remaining. */ - *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ); - vTaskSetTimeOutState( pxTimeOut ); - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - } - portEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -void vTaskMissedYield( void ) -{ - xMissedYield = pdTRUE; -} - -/* - * ----------------------------------------------------------- - * The Idle task. - * ---------------------------------------------------------- - * - * The portTASK_FUNCTION() macro is used to allow port/compiler specific - * language extensions. The equivalent prototype for this function is: - * - * void prvIdleTask( void *pvParameters ); - * - */ -static portTASK_FUNCTION( prvIdleTask, pvParameters ) -{ - /* Stop warnings. */ - ( void ) pvParameters; - - for( ;; ) - { - /* See if any tasks have been deleted. */ - prvCheckTasksWaitingTermination(); - - #if ( configUSE_PREEMPTION == 0 ) - { - /* If we are not using preemption we keep forcing a task switch to - see if any other task has become available. If we are using - preemption we don't need to do this as any task becoming available - will automatically get the processor anyway. */ - taskYIELD(); - } - #endif - - #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) - { - /* When using preemption tasks of equal priority will be - timesliced. If a task that is sharing the idle priority is ready - to run then the idle task should yield before the end of the - timeslice. - - A critical region is not required here as we are just reading from - the list, and an occasional incorrect value will not matter. If - the ready list at the idle priority contains more than one task - then a task other than the idle task is ready to execute. */ - if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 ) - { - taskYIELD(); - } - } - #endif - - #if ( configUSE_IDLE_HOOK == 1 ) - { - extern void vApplicationIdleHook( void ); - - /* Call the user defined function from within the idle task. This - allows the application designer to add background functionality - without the overhead of a separate task. - NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, - CALL A FUNCTION THAT MIGHT BLOCK. */ - vApplicationIdleHook(); - } - #endif - // call nanosleep for smalles sleep time possible - // (depending on kernel settings - around 100 microseconds) - // decreases idle thread CPU load from 100 to practically 0 -#ifndef __CYGWIN__ - sigset_t xSignals; - sigfillset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); - struct timespec x; - x.tv_sec=0; - x.tv_nsec=10000; - nanosleep(&x,NULL); - sigemptyset( &xSignals ); - pthread_sigmask( SIG_SETMASK, &xSignals, NULL ); -#endif - } -} /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */ - - - - - - - -/*----------------------------------------------------------- - * File private functions documented at the top of the file. - *----------------------------------------------------------*/ - - - -static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) -{ - /* Store the function name in the TCB. */ - #if configMAX_TASK_NAME_LEN > 1 - { - /* Don't bring strncpy into the build unnecessarily. */ - strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN ); - } - #endif - pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = '\0'; - - /* This is used as an array index so must ensure it's not too large. First - remove the privilege bit if one is present. */ - if( uxPriority >= configMAX_PRIORITIES ) - { - uxPriority = configMAX_PRIORITIES - 1; - } - - pxTCB->uxPriority = uxPriority; - #if ( configUSE_MUTEXES == 1 ) - { - pxTCB->uxBasePriority = uxPriority; - } - #endif - - vListInitialiseItem( &( pxTCB->xGenericListItem ) ); - vListInitialiseItem( &( pxTCB->xEventListItem ) ); - - /* Set the pxTCB as a link back from the xListItem. This is so we can get - back to the containing TCB from a generic item in a list. */ - listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB ); - - /* Event lists are always in priority order. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority ); - listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB ); - - #if ( portCRITICAL_NESTING_IN_TCB == 1 ) - { - pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0; - } - #endif - - #if ( configUSE_APPLICATION_TASK_TAG == 1 ) - { - pxTCB->pxTaskTag = NULL; - } - #endif - - #if ( configGENERATE_RUN_TIME_STATS == 1 ) - { - pxTCB->ulRunTimeCounter = 0UL; - } - #endif - - #if ( portUSING_MPU_WRAPPERS == 1 ) - { - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth ); - } - #else - { - ( void ) xRegions; - ( void ) usStackDepth; - } - #endif -} -/*-----------------------------------------------------------*/ - -#if ( portUSING_MPU_WRAPPERS == 1 ) - - void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions ) - { - tskTCB *pxTCB; - - if( xTaskToModify == pxCurrentTCB ) - { - xTaskToModify = NULL; - } - - /* If null is passed in here then we are deleting ourselves. */ - pxTCB = prvGetTCBFromHandle( xTaskToModify ); - - vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 ); - } - /*-----------------------------------------------------------*/ -#endif - -static void prvInitialiseTaskLists( void ) -{ -unsigned portBASE_TYPE uxPriority; - - for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ ) - { - vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) ); - } - - vListInitialise( ( xList * ) &xDelayedTaskList1 ); - vListInitialise( ( xList * ) &xDelayedTaskList2 ); - vListInitialise( ( xList * ) &xPendingReadyList ); - - #if ( INCLUDE_vTaskDelete == 1 ) - { - vListInitialise( ( xList * ) &xTasksWaitingTermination ); - } - #endif - - #if ( INCLUDE_vTaskSuspend == 1 ) - { - vListInitialise( ( xList * ) &xSuspendedTaskList ); - } - #endif - - /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList - using list2. */ - pxDelayedTaskList = &xDelayedTaskList1; - pxOverflowDelayedTaskList = &xDelayedTaskList2; -} -/*-----------------------------------------------------------*/ - -static void prvCheckTasksWaitingTermination( void ) -{ - #if ( INCLUDE_vTaskDelete == 1 ) - { - portBASE_TYPE xListIsEmpty; - - /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called - too often in the idle task. */ - if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 ) - { - vTaskSuspendAll(); - xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination ); - xTaskResumeAll(); - - if( !xListIsEmpty ) - { - tskTCB *pxTCB; - - portENTER_CRITICAL(); - { - pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) ); - vListRemove( &( pxTCB->xGenericListItem ) ); - --uxCurrentNumberOfTasks; - --uxTasksDeleted; - } - portEXIT_CRITICAL(); - - prvDeleteTCB( pxTCB ); - } - } - } - #endif -} -/*-----------------------------------------------------------*/ - -static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) -{ -tskTCB *pxNewTCB; - - /* Allocate space for the TCB. Where the memory comes from depends on - the implementation of the port malloc function. */ - pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) ); - - if( pxNewTCB != NULL ) - { - /* Allocate space for the stack used by the task being created. - The base of the stack memory stored in the TCB so the task can - be deleted later if required. */ - pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); - - if( pxNewTCB->pxStack == NULL ) - { - /* Could not allocate the stack. Delete the allocated TCB. */ - vPortFree( pxNewTCB ); - pxNewTCB = NULL; - } - else - { - /* Just to help debugging. */ - memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) ); - } - } - - return pxNewTCB; -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) - { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned short usStackRemaining; - - /* Write the details of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - #if ( portSTACK_GROWTH > 0 ) - { - usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack ); - } - #else - { - usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack ); - } - #endif - - sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber ); - strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString ); - - } while( pxNextTCB != pxFirstTCB ); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configGENERATE_RUN_TIME_STATS == 1 ) - - static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) - { - volatile tskTCB *pxNextTCB, *pxFirstTCB; - unsigned long ulStatsAsPercentage; - - /* Write the run time stats of all the TCB's in pxList into the buffer. */ - listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); - do - { - /* Get next TCB in from the list. */ - listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); - - /* Divide by zero check. */ - if( ulTotalRunTime > 0UL ) - { - /* Has the task run at all? */ - if( pxNextTCB->ulRunTimeCounter == 0 ) - { - /* The task has used no CPU time at all. */ - sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName ); - } - else - { - /* What percentage of the total run time as the task used? - This will always be rounded down to the nearest integer. */ - ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime; - - if( ulStatsAsPercentage > 0UL ) - { - sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); - } - else - { - /* If the percentage is zero here then the task has - consumed less than 1% of the total run time. */ - sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter ); - } - } - - strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString ); - } - - } while( pxNextTCB != pxFirstTCB ); - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) - - static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) - { - register unsigned short usCount = 0; - - while( *pucStackByte == tskSTACK_FILL_BYTE ) - { - pucStackByte -= portSTACK_GROWTH; - usCount++; - } - - usCount /= sizeof( portSTACK_TYPE ); - - return usCount; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) - - unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask ) - { - tskTCB *pxTCB; - unsigned char *pcEndOfStack; - unsigned portBASE_TYPE uxReturn; - - pxTCB = prvGetTCBFromHandle( xTask ); - - #if portSTACK_GROWTH < 0 - { - pcEndOfStack = ( unsigned char * ) pxTCB->pxStack; - } - #else - { - pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack; - } - #endif - - uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack ); - - return uxReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) ) - - static void prvDeleteTCB( tskTCB *pxTCB ) - { - /* Free up the memory allocated by the scheduler for the task. It is up to - the task to free any memory allocated at the application level. */ - vPortFreeAligned( pxTCB->pxStack ); - vPortFree( pxTCB ); - } - -#endif - - -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) - - xTaskHandle xTaskGetCurrentTaskHandle( void ) - { - xTaskHandle xReturn; - - /* A critical section is not required as this is not called from - an interrupt and the current TCB will always be the same for any - individual execution thread. */ - xReturn = pxCurrentTCB; - - return xReturn; - } - -#endif - -/*-----------------------------------------------------------*/ - -#if ( INCLUDE_xTaskGetSchedulerState == 1 ) - - portBASE_TYPE xTaskGetSchedulerState( void ) - { - portBASE_TYPE xReturn; - - if( xSchedulerRunning == pdFALSE ) - { - xReturn = taskSCHEDULER_NOT_STARTED; - } - else - { - if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE ) - { - xReturn = taskSCHEDULER_RUNNING; - } - else - { - xReturn = taskSCHEDULER_SUSPENDED; - } - } - - return xReturn; - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_MUTEXES == 1 ) - - void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder ) - { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; - - if( pxTCB->uxPriority < pxCurrentTCB->uxPriority ) - { - /* Adjust the mutex holder state to account for its new priority. */ - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); - - /* If the task being modified is in the ready state it will need to - be moved in to a new list. */ - if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) ) - { - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Inherit the priority before being moved into the new list. */ - pxTCB->uxPriority = pxCurrentTCB->uxPriority; - prvAddTaskToReadyQueue( pxTCB ); - } - else - { - /* Just inherit the priority. */ - pxTCB->uxPriority = pxCurrentTCB->uxPriority; - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_MUTEXES == 1 ) - - void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder ) - { - tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder; - - if( pxMutexHolder != NULL ) - { - if( pxTCB->uxPriority != pxTCB->uxBasePriority ) - { - /* We must be the running task to be able to give the mutex back. - Remove ourselves from the ready list we currently appear in. */ - vListRemove( &( pxTCB->xGenericListItem ) ); - - /* Disinherit the priority before adding ourselves into the new - ready list. */ - pxTCB->uxPriority = pxTCB->uxBasePriority; - listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); - prvAddTaskToReadyQueue( pxTCB ); - } - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - - void vTaskEnterCritical( void ) - { - portDISABLE_INTERRUPTS(); - - if( xSchedulerRunning != pdFALSE ) - { - pxCurrentTCB->uxCriticalNesting++; - } - } - -#endif -/*-----------------------------------------------------------*/ - -#if ( portCRITICAL_NESTING_IN_TCB == 1 ) - -void vTaskExitCritical( void ) -{ - if( xSchedulerRunning != pdFALSE ) - { - if( pxCurrentTCB->uxCriticalNesting > 0 ) - { - pxCurrentTCB->uxCriticalNesting--; - - if( pxCurrentTCB->uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } - } - } -} - -#endif -/*-----------------------------------------------------------*/ - - - -