diff --git a/FreeRTOS/Demo/Posix_GCC/FreeRTOSConfig.h b/FreeRTOS/Demo/Posix_GCC/FreeRTOSConfig.h index 911b92e8..4f1eceaa 100644 --- a/FreeRTOS/Demo/Posix_GCC/FreeRTOSConfig.h +++ b/FreeRTOS/Demo/Posix_GCC/FreeRTOSConfig.h @@ -43,7 +43,7 @@ #define configUSE_TICK_HOOK 1 #define configUSE_DAEMON_TASK_STARTUP_HOOK 1 #define configTICK_RATE_HZ ( 1000 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ -#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 70 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 200 ) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 65 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 12 ) #define configUSE_TRACE_FACILITY 1 diff --git a/FreeRTOS/Demo/Posix_GCC/main.c b/FreeRTOS/Demo/Posix_GCC/main.c index 33229ce9..652c40af 100644 --- a/FreeRTOS/Demo/Posix_GCC/main.c +++ b/FreeRTOS/Demo/Posix_GCC/main.c @@ -68,6 +68,7 @@ #define BLINKY_DEMO 0 #define FULL_DEMO 1 +#define USER_DEMO 2 #ifdef BUILD_DIR #define BUILD BUILD_DIR @@ -87,6 +88,7 @@ /*-----------------------------------------------------------*/ extern void main_blinky( void ); extern void main_full( void ); +extern void main_sensor( void ); static void traceOnEnter( void ); /* @@ -176,6 +178,11 @@ int main( void ) console_print( "Starting full demo\n" ); main_full(); } + #elif ( mainSELECTED_APPLICATION == USER_DEMO ) + { + console_print( "Staring sensors demo\n" ); + main_sensor(); + } #else { #error "The selected demo is not valid" @@ -204,7 +211,7 @@ void vApplicationMallocFailedHook( void ) } /*-----------------------------------------------------------*/ -void vApplicationIdleHook( void ) +__attribute__((noinline)) void vApplicationIdleHook( void ) { /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set * to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle diff --git a/FreeRTOS/Demo/Posix_GCC/main_sensors.c b/FreeRTOS/Demo/Posix_GCC/main_sensors.c new file mode 100644 index 00000000..06cff8fa --- /dev/null +++ b/FreeRTOS/Demo/Posix_GCC/main_sensors.c @@ -0,0 +1,288 @@ +/* + * FreeRTOS V202111.00 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/****************************************************************************** + * NOTE 1: The FreeRTOS demo threads will not be running continuously, so + * do not expect to get real time behaviour from the FreeRTOS Linux port, or + * this demo application. Also, the timing information in the FreeRTOS+Trace + * logs have no meaningful units. See the documentation page for the Linux + * port for further information: + * https://freertos.org/FreeRTOS-simulator-for-Linux.html + * + * NOTE 2: This project provides two demo applications. A simple blinky style + * project, and a more comprehensive test and demo application. The + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select + * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY + * in main.c. This file implements the simply blinky version. Console output + * is used in place of the normal LED toggling. + * + * NOTE 3: This file only contains the source code that is specific to the + * basic demo. Generic functions, such FreeRTOS hook functions, are defined + * in main.c. + ****************************************************************************** + * + * main_blinky() creates one queue, one software timer, and two tasks. It then + * starts the scheduler. + * + * The Queue Send Task: + * The queue send task is implemented by the prvQueueSendTask() function in + * this file. It uses vTaskDelayUntil() to create a periodic task that sends + * the value 100 to the queue every 200 milliseconds (please read the notes + * above regarding the accuracy of timing under Linux). + * + * The Queue Send Software Timer: + * The timer is an auto-reload timer with a period of two seconds. The timer's + * callback function writes the value 200 to the queue. The callback function + * is implemented by prvQueueSendTimerCallback() within this file. + * + * The Queue Receive Task: + * The queue receive task is implemented by the prvQueueReceiveTask() function + * in this file. prvQueueReceiveTask() waits for data to arrive on the queue. + * When data is received, the task checks the value of the data, then outputs a + * message to indicate if the data came from the queue send task or the queue + * send software timer. + * + * Expected Behaviour: + * - The queue send task writes to the queue every 200ms, so every 200ms the + * queue receive task will output a message indicating that data was received + * on the queue from the queue send task. + * - The queue send software timer has a period of two seconds, and is reset + * each time a key is pressed. So if two seconds expire without a key being + * pressed then the queue receive task will output a message indicating that + * data was received on the queue from the queue send software timer. + * + * NOTE: Console input and output relies on Linux system calls, which can + * interfere with the execution of the FreeRTOS Linux port. This demo only + * uses Linux system call occasionally. Heavier use of Linux system calls + * may crash the port. + */ + +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "semphr.h" + +/* Local includes. */ +#include "console.h" + +/* Priorities at which the tasks are created. */ +#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) + +/* The rate at which data is sent to the queue. The times are converted from + * milliseconds to ticks using the pdMS_TO_TICKS() macro. */ +#define mainTASK_SEND_FREQUENCY_MS pdMS_TO_TICKS( 200UL ) +#define mainTIMER_SEND_FREQUENCY_MS pdMS_TO_TICKS( 2000UL ) + +/* The number of items the queue can hold at once. */ +#define mainQUEUE_LENGTH ( 2 ) + +/* The values sent to the queue receive task from the queue send task and the + * queue send software timer respectively. */ +#define mainVALUE_SENT_FROM_TASK ( 100UL ) +#define mainVALUE_SENT_FROM_TIMER ( 200UL ) + +/*-----------------------------------------------------------*/ + +/* + * The tasks as described in the comments at the top of this file. + */ +static void prvQueueReceiveTask( void * pvParameters ); +static void prvQueueSendTask( void * pvParameters ); + +/* + * The callback function executed when the software timer expires. + */ +static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle ); + +/*-----------------------------------------------------------*/ + +/* The queue used by both tasks. */ +static QueueHandle_t xQueue = NULL; + +/* A software timer that is started from the tick hook. */ +static TimerHandle_t xTimer = NULL; + +/* Handels for 2 worker threads, so they can delete themselves */ +static TaskHandle_t txThread = NULL; +static TaskHandle_t rxThread = NULL; +/*-----------------------------------------------------------*/ +void LLVMFuzzerTestOneInput( uint8_t * , size_t ); +static uint8_t Data_own[4096] = {0}; +static uint64_t Data_size = 4096; + +/*** SEE THE COMMENTS AT THE TOP OF THIS FILE ***/ +void main_sensor( void ) +{ + + /* Create the queue. */ + xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) ); + + if( xQueue != NULL ) + { + // vTaskStartScheduler(); + LLVMFuzzerTestOneInput(Data_own, 4096); + } + + /* If all is well, the scheduler will now be running, and the following + * line will never be reached. If the following line does execute, then + * there was insufficient FreeRTOS heap memory available for the idle and/or + * timer tasks to be created. See the memory management section on the + * FreeRTOS web site for more details. */ + // for( ; ; ) + // { + // } +} +/*-----------------------------------------------------------*/ +/* This function will only get called by the alf harnes if it detects the system ideling */ +__attribute__((noinline)) void LLVMFuzzerTestOneInput( uint8_t *Data, size_t Size ) +{ + Data_size = Size; + xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */ + "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ + configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */ + NULL, /* The parameter passed to the task - not used in this simple case. */ + mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */ + NULL ); /* The task handle is not required, so NULL is passed. */ + + xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, Data, mainQUEUE_SEND_TASK_PRIORITY, NULL ); + + vTaskStartScheduler(); + puts("Past End of function"); +} + +/*-----------------------------------------------------------*/ + +__attribute__((noinline)) static void prvQueueSendTask( void * pvParameters ) +{ + TickType_t xNextWakeTime; + const TickType_t xBlockTime = mainTASK_SEND_FREQUENCY_MS; + uint32_t ulValueToSend = mainVALUE_SENT_FROM_TASK; + + /* Prevent the compiler warning about the unused parameter. */ + // ( void ) pvParameters; + + /* Initialise xNextWakeTime - this only needs to be done once. */ + // xNextWakeTime = xTaskGetTickCount(); + + const uint8_t* simulatedInputs = (const uint8_t*) pvParameters; + + static char filter[3] = {0}; + + for(int i=0;i 64 ) + { + printf("Send Input %d\n",ulValueToSend); + xQueueSend( xQueue, &ulValueToSend, 0U ); + } + } + uint32_t errsig = 1; + puts("Data depleted, suspending scedule"); + xQueueSend( xQueue, &errsig, 0U ); + vTaskDelete(txThread); +} +/*-----------------------------------------------------------*/ + +static void prvQueueSendTimerCallback( TimerHandle_t xTimerHandle ) +{ + const uint32_t ulValueToSend = mainVALUE_SENT_FROM_TIMER; + + /* This is the software timer callback function. The software timer has a + * period of two seconds and is reset each time a key is pressed. This + * callback function will execute if the timer expires, which will only happen + * if a key is not pressed for two seconds. */ + + /* Avoid compiler warnings resulting from the unused parameter. */ + ( void ) xTimerHandle; + + /* Send to the queue - causing the queue receive task to unblock and + * write out a message. This function is called from the timer/daemon task, so + * must not block. Hence the block time is set to 0. */ + xQueueSend( xQueue, &ulValueToSend, 0U ); +} +/*-----------------------------------------------------------*/ + +__attribute__((noinline)) static void prvQueueReceiveTask( void * pvParameters ) +{ + uint32_t ulReceivedValue; + + /* Prevent the compiler warning about the unused parameter. */ + ( void ) pvParameters; + + for( ; ; ) + { + /* Wait until something arrives in the queue - this task will block + * indefinitely provided INCLUDE_vTaskSuspend is set to 1 in + * FreeRTOSConfig.h. It will not use any CPU time while it is in the + * Blocked state. */ + xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); + + int counter = 0; + + for (int i=1;i<=ulReceivedValue;i++) + { + if (i % 3 || i % 5) + { + counter++; + } + } + + /* To get here something must have been received from the queue, but + * is it an expected value? Normally calling printf() from a task is not + * a good idea. Here there is lots of stack space and only one task is + * using console IO so it is ok. However, note the comments at the top of + * this file about the risks of making Linux system calls (such as + * console output) from a FreeRTOS task. */ + if( ulReceivedValue == 1 ) + { + puts("Recieved End-Signal"); + // abort(); // vTaskEndSceduler leads to a deadlock when running in the fuzzers fork-server + // exit(0); + vTaskEndScheduler(); + vTaskDelete(txThread); + } + } +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/port.c b/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/port.c index dbcda49e..69b1d688 100644 --- a/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/port.c +++ b/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/port.c @@ -178,7 +178,7 @@ Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); */ portBASE_TYPE xPortStartScheduler( void ) { -int iSignal; +siginfo_t iSignal; sigset_t xSignals; hMainThread = pthread_self(); @@ -193,16 +193,23 @@ sigset_t xSignals; /* Wait until signaled by vPortEndScheduler(). */ sigemptyset( &xSignals ); sigaddset( &xSignals, SIG_RESUME ); + sigaddset( &xSignals, SIGTERM ); + // puts("Waiting for SigTerm"); + struct timespec to_wait = {0}; + to_wait.tv_sec=1; while ( !xSchedulerEnd ) { - sigwait( &xSignals, &iSignal ); + sigtimedwait( &xSignals, &iSignal, &to_wait); + // puts("SigTerm recieved or timeout"); } + puts("Main Thread recieved signal"); /* Cancel the Idle task and free its resources */ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) vPortCancelThread( xTaskGetIdleTaskHandle() ); #endif + puts("Idle Task cancled"); #if ( configUSE_TIMERS == 1 ) /* Cancel the Timer task and free its resources */ @@ -212,6 +219,7 @@ sigset_t xSignals; /* Restore original signal mask. */ (void)pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); + puts("Main Thread returns"); return 0; } /*-----------------------------------------------------------*/ @@ -238,6 +246,7 @@ Thread_t *xCurrentThread; /* Signal the scheduler to exit its loop. */ xSchedulerEnd = pdTRUE; + // printf("Sending SigTerm to %u\n",hMainThread); (void)pthread_kill( hMainThread, SIG_RESUME ); xCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); @@ -418,8 +427,11 @@ Thread_t *pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); * The thread has already been suspended so it can be safely cancelled. */ pthread_cancel( pxThreadToCancel->pthread ); + puts("cancled"); pthread_join( pxThreadToCancel->pthread, NULL ); + puts("joined"); event_delete( pxThreadToCancel->ev ); + puts("event deleted"); } /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c b/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c index 3e66a0f1..0fb8c3ec 100644 --- a/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c +++ b/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c @@ -51,9 +51,13 @@ struct event * event_create() void event_delete( struct event * ev ) { + puts("inside event delete"); pthread_mutex_destroy( &ev->mutex ); + puts("mutex destroyed"); pthread_cond_destroy( &ev->cond ); + puts("cond destroyed"); free( ev ); + puts("freed"); } bool event_wait( struct event * ev )