diff options
author | Maximilien Cuony <maximilien@theglu.org> | 2016-05-31 21:58:17 +0200 |
---|---|---|
committer | Maximilien Cuony <maximilien@theglu.org> | 2016-05-31 21:58:17 +0200 |
commit | 9069fc127e4f73041fbd1f66e4506fcf12418315 (patch) | |
tree | 902aa478c6e9d47cde89eaa996b5f7f662070518 /src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX | |
parent | 4803231e214fbd19eab4ba2289583859ee07183f (diff) | |
download | glutte-o-matic-9069fc127e4f73041fbd1f66e4506fcf12418315.tar.gz glutte-o-matic-9069fc127e4f73041fbd1f66e4506fcf12418315.tar.bz2 glutte-o-matic-9069fc127e4f73041fbd1f66e4506fcf12418315.zip |
Simuator - Work in progress
Diffstat (limited to 'src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX')
-rw-r--r-- | src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/port.c | 787 | ||||
-rw-r--r-- | src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/portmacro.h | 128 |
2 files changed, 915 insertions, 0 deletions
diff --git a/src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/port.c b/src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/port.c new file mode 100644 index 0000000..53e030f --- /dev/null +++ b/src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/port.c @@ -0,0 +1,787 @@ +/* + 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 <pthread.h> +#include <sched.h> +#include <signal.h> +#include <errno.h> +#include <sys/time.h> +#include <time.h> +#include <sys/times.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <limits.h> + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +/*-----------------------------------------------------------*/ +#ifndef MAX_NUMBER_OF_TASKS +#define MAX_NUMBER_OF_TASKS ( _POSIX_THREAD_THREADS_MAX ) +#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; + 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_t hMainThread = ( pthread_t )NULL; +/*-----------------------------------------------------------*/ + +static volatile portBASE_TYPE xSentinel = 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 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 ); +/*-----------------------------------------------------------*/ + +/* + * 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. */ + if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) + { + xSentinel = 0; + if ( 0 != pthread_create( &( pxThreads[ lIndexOfLastAddedTask ].hThread ), &xThreadAttributes, prvWaitForStart, (void *)pxThisThreadParams ) ) + { + /* Thread create failed, signal the failure */ + pxTopOfStack = 0; + } + + /* Wait until the task suspends. */ + (void)pthread_mutex_unlock( &xSingleThreadMutex ); + while ( xSentinel == 0 ); + 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. */ + prvResumeThread( prvGetThreadHandle( xTaskGetCurrentTaskHandle() ) ); +} +/*-----------------------------------------------------------*/ + +/* + * 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 ); + + while ( pdTRUE != xSchedulerEnd ) + { + if ( 0 != sigwait( &xSignals, &iSignal ) ) + { + printf( "Main thread spurious signal: %d\n", iSignal ); + } + } + + 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 xResult; +} +/*-----------------------------------------------------------*/ + +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 ); + if (xResult) + printf("pthread_cancel error!\n"); + } + } + + /* 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; + + if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) + { + xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + + vTaskSwitchContext(); + + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + if ( xTaskToSuspend != xTaskToResume ) + { + /* Remember and switch the critical nesting. */ + prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); + uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); + /* Switch tasks. */ + prvResumeThread( xTaskToResume ); + prvSuspendThread( xTaskToSuspend ); + } + else + { + /* Yielding to self */ + (void)pthread_mutex_unlock( &xSingleThreadMutex ); + } + } +} +/*-----------------------------------------------------------*/ + +void 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_PERIOD_MS * 1000; + + /* 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; + + (void)(sig); + if ( ( pdTRUE == xInterruptsEnabled ) && ( pdTRUE != xServicingTick ) ) + { + if ( 0 == pthread_mutex_trylock( &xSingleThreadMutex ) ) + { + xServicingTick = pdTRUE; + + xTaskToSuspend = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + /* Tick Increment. */ + xTaskIncrementTick(); + + /* Select Next Task. */ +#if ( configUSE_PREEMPTION == 1 ) + vTaskSwitchContext(); +#endif + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + + /* The only thread that can process this tick is the running thread. */ + if ( xTaskToSuspend != xTaskToResume ) + { + /* Remember and switch the critical nesting. */ + prvSetTaskCriticalNesting( xTaskToSuspend, uxCriticalNesting ); + uxCriticalNesting = prvGetTaskCriticalNesting( xTaskToResume ); + /* Resume next task. */ + prvResumeThread( xTaskToResume ); + /* Suspend the current task. */ + prvSuspendThread( xTaskToSuspend ); + } + else + { + /* Release the lock as we are Resuming. */ + (void)pthread_mutex_unlock( &xSingleThreadMutex ); + } + xServicingTick = pdFALSE; + } + else + { + xPendYield = pdTRUE; + } + } + else + { + xPendYield = pdTRUE; + } +} +/*-----------------------------------------------------------*/ + +void vPortForciblyEndThread( void *pxTaskToDelete ) +{ +xTaskHandle hTaskToDelete = ( xTaskHandle )pxTaskToDelete; +pthread_t xTaskToDelete; +pthread_t xTaskToResume; +portBASE_TYPE xResult; + + if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) + { + xTaskToDelete = prvGetThreadHandle( hTaskToDelete ); + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + + if ( xTaskToResume == xTaskToDelete ) + { + /* This is a suicidal thread, need to select a different task to run. */ + vTaskSwitchContext(); + xTaskToResume = prvGetThreadHandle( xTaskGetCurrentTaskHandle() ); + } + + if ( pthread_self() != xTaskToDelete ) + { + /* Cancelling a thread that is not me. */ + if ( xTaskToDelete != ( pthread_t )NULL ) + { + /* Send a signal to wake the task so that it definitely cancels. */ + pthread_testcancel(); + xResult = pthread_cancel( xTaskToDelete ); + if (xResult) + printf("pthread_cancel error!\n"); + /* Pthread Clean-up function will note the cancellation. */ + } + (void)pthread_mutex_unlock( &xSingleThreadMutex ); + } + else + { + /* Resume the other thread. */ + prvResumeThread( xTaskToResume ); + /* Pthread Clean-up function will note the cancellation. */ + /* Release the execution. */ + uxCriticalNesting = 0; + vPortEnableInterrupts(); + (void)pthread_mutex_unlock( &xSingleThreadMutex ); + /* Commit suicide */ + pthread_exit( (void *)1 ); + } + } +} +/*-----------------------------------------------------------*/ + +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() ); + + if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) + { + prvSuspendThread( pthread_self() ); + } + + pvCode( pParams ); + + pthread_cleanup_pop( 1 ); + return (void *)NULL; +} +/*-----------------------------------------------------------*/ + +void prvSuspendSignalHandler(int sig) +{ +sigset_t xSignals; + + /* Only interested in the resume signal. */ + sigemptyset( &xSignals ); + sigaddset( &xSignals, SIG_RESUME ); + xSentinel = 1; + + /* Unlock the Single thread mutex to allow the resumed task to continue. */ + if ( 0 != pthread_mutex_unlock( &xSingleThreadMutex ) ) + { + printf( "Releasing someone else's lock.\n" ); + } + + /* Wait on the resume signal. */ + if ( 0 != sigwait( &xSignals, &sig ) ) + { + printf( "SSH: Sw %d\n", 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(); + } +} +/*-----------------------------------------------------------*/ + +void prvSuspendThread( pthread_t xThreadId ) +{ +portBASE_TYPE xResult = pthread_mutex_lock( &xSuspendResumeThreadMutex ); + if ( 0 == xResult ) + { + /* Set-up for the Suspend Signal handler? */ + xSentinel = 0; + xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); + xResult = pthread_kill( xThreadId, SIG_SUSPEND ); + if (xResult) + printf("pthread_kill error!\n"); + while ( ( xSentinel == 0 ) && ( pdTRUE != xServicingTick ) ) + { + sched_yield(); + } + } +} +/*-----------------------------------------------------------*/ + +void prvResumeSignalHandler(int sig) +{ + (void)(sig); + /* Yield the Scheduler to ensure that the yielding thread completes. */ + if ( 0 == pthread_mutex_lock( &xSingleThreadMutex ) ) + { + (void)pthread_mutex_unlock( &xSingleThreadMutex ); + } +} +/*-----------------------------------------------------------*/ + +void prvResumeThread( pthread_t xThreadId ) +{ +portBASE_TYPE xResult; + if ( 0 == pthread_mutex_lock( &xSuspendResumeThreadMutex ) ) + { + if ( pthread_self() != xThreadId ) + { + xResult = pthread_kill( xThreadId, SIG_RESUME ); + if (xResult) + printf("pthread_kill error!\n"); + } + xResult = pthread_mutex_unlock( &xSuspendResumeThreadMutex ); + if (xResult) + printf("pthread_mutex_unlock error!\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; + sigfillset( &sigresume.sa_mask ); + + sigtick.sa_flags = 0; + sigtick.sa_handler = vPortSystemTickHandler; + 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/src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/portmacro.h b/src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/portmacro.h new file mode 100644 index 0000000..a4219cd --- /dev/null +++ b/src/FreeRTOS-Sim-master/Source/portable/GCC/POSIX/portmacro.h @@ -0,0 +1,128 @@ +/*
+ POSIX Simulator
+ Tested with FreeRTOS V8.2.2
+ 1 tab == 4 spaces!
+*/
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/******************************************************************************
+ Defines
+******************************************************************************/
+/* Type definitions. */
+#define portCHAR char
+#define portFLOAT float
+#define portDOUBLE double
+#define portLONG long
+#define portSHORT short
+#define portSTACK_TYPE size_t
+#define portBASE_TYPE long
+#define portPOINTER_SIZE_TYPE size_t
+
+typedef portSTACK_TYPE StackType_t;
+typedef long BaseType_t;
+typedef unsigned long UBaseType_t;
+
+#if( configUSE_16_BIT_TICKS == 1 )
+ typedef uint16_t TickType_t;
+ #define portMAX_DELAY ( TickType_t ) 0xffff
+#else
+ typedef uint32_t TickType_t;
+ #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+
+ /* 32/64-bit tick type on a 32/64-bit architecture, so reads of the tick
+ count do not need to be guarded with a critical section. */
+ #define portTICK_TYPE_IS_ATOMIC 1
+#endif
+
+/* Hardware specifics. */
+#define portSTACK_GROWTH ( -1 )
+#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+#define portINLINE __inline__
+
+#if defined( __x86_64__)
+ #define portBYTE_ALIGNMENT 8
+#else
+ #define portBYTE_ALIGNMENT 4
+#endif
+
+//TODO: check portREMOVE_STATIC_QUALIFIER
+#define portREMOVE_STATIC_QUALIFIER
+
+/*-----------------------------------------------------------*/
+
+/* Scheduler utilities. */
+extern void vPortYieldFromISR( void );
+extern void vPortYield( void );
+#define portYIELD() vPortYield()
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()
+#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
+
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern BaseType_t xPortSetInterruptMask( void );
+extern void vPortClearInterruptMask( portBASE_TYPE xMask );
+
+#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
+
+extern void vPortDisableInterrupts( void );
+extern void vPortEnableInterrupts( void );
+#define portSET_INTERRUPT_MASK() ( vPortDisableInterrupts() )
+#define portCLEAR_INTERRUPT_MASK() ( vPortEnableInterrupts() )
+
+#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
+#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
+
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+#define portENTER_CRITICAL() vPortEnterCritical()
+#define portEXIT_CRITICAL() vPortExitCritical()
+
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
+
+#define portNOP()
+
+#define portOUTPUT_BYTE( a, b )
+
+extern void vPortForciblyEndThread( void *pxTaskToDelete );
+#define traceTASK_DELETE( pxTaskToDelete ) vPortForciblyEndThread( pxTaskToDelete )
+
+extern void vPortAddTaskHandle( void *pxTaskHandle );
+#define traceTASK_CREATE( pxNewTCB ) vPortAddTaskHandle( pxNewTCB )
+
+/* Posix Signal definitions that can be changed or read as appropriate. */
+#define SIG_SUSPEND SIGUSR1
+#define SIG_RESUME SIGUSR2
+
+/* Enable the following hash defines to make use of the real-time tick where time progresses at real-time. */
+#define SIG_TICK SIGALRM
+#define TIMER_TYPE ITIMER_REAL
+/* Enable the following hash defines to make use of the process tick where time progresses only when the process is executing.
+#define SIG_TICK SIGVTALRM
+#define TIMER_TYPE ITIMER_VIRTUAL */
+/* Enable the following hash defines to make use of the profile tick where time progresses when the process or system calls are executing.
+#define SIG_TICK SIGPROF
+#define TIMER_TYPE ITIMER_PROF */
+
+/* Make use of times(man 2) to gather run-time statistics on the tasks. */
+extern void vPortFindTicksPerSecond( void );
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vPortFindTicksPerSecond() /* Nothing to do because the timer is already present. */
+extern unsigned long ulPortGetTimerValue( void );
+#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetTimerValue() /* Query the System time stats for this process. */
+
+#ifdef __cplusplus
+} /* extern C */
+#endif
+
+#endif /* PORTMACRO_H */
|