There's already a portYIELD_FROM_ISR() macro that calls vPortYield() which wraps the FromISR code.
It doesn't appear that vPortYieldFromISR() is intended to be publicly accessible in this port so
I've marked it as private to silence the warning.
event_create() also got flagged due to missing void in prototype.
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
event_wait_timed() was ignoring a timeout of 1000 ms.
Presumably this is because pthread_cond_timedwait() only
considers tv_nsec less than one second.
Convert the timeout in miliseconds to second and nanosecond
components to fix this.
Co-authored-by: alfred gedeon <28123637+alfred2g@users.noreply.github.com>
* Posix: Fix no task switching issue if a task ended
When the main function of a task exits, no task switching happened.
This is because all the remaining tasks are waiting on the condition
variable. The fix is to trigger a task switch and mark the exiting
task as "Dying" to be suspened and exited properly from the scheduler.
* Posix: Assert and stop if the Task function returned
* Posix: just assert if a task returned from its main function
Co-authored-by: alfred gedeon <alfred2g@hotmail.com>
* Posix: Free Idle task resources after ending the scheduler
In case of using Posix simulator and ending the scheduler, it does
not free the resources allocated by the idle task. This
causes the memory checkers (Valgrind, Address Sanitizers, ..) to
complain.
* Posix: Free the condition variable memory in the correct place
In case of deleting a task from another task, the deletion happens
immediately and the thread is canceled but the memory allocated by
the task condition variable is not freed. This causes the memory
checkers (Valgrind, Address sanitizers, ..) to complain.
* Posix: End Timer thread and free its resources after ending the scheduler
* Style: Change FreeRTOS websites in comments
* Style: Change freertos to FreeRTOS in comments
* Style: Remove broken link
Co-authored-by: Alfred Gedeon <gedeonag@amazon.com>
This is similar to the Windows port, allowing FreeRTOS kernel
applications to run as regular applications on Posix (Linux) systems.
You can use this in a 32-bit or 64-bit application (although there are
dynamic memory allocation trace points that do not support 64-bit
addresses).
Many of the same caveats of running an RTOS on a non-real-time system
apply, but this is still very useful for easy debugging/testing
applications in a simulated environment. In particular, it allows easy
use of tools such as valgrind.
You can call standard library functions from tasks but care must be
taken with any that internally take mutexes or block. This includes
malloc()/free() and many stdio functions (e.g., printf()).
Replacement malloc(), free(), realloc(), and calloc() functions are
provided which are safe. printf() needs to be called with a FreeRTOS
mutex help (or called from only a single task).
Each task is run in its own pthread, which makes debugging with
standard tools (such as GDB) easier backtraces for individual tasks
are available. Threads for non-running tasks are blocked in sigwait().
The stack for each task (thread) is allocated when the thread is
created, and the stack provided during task creation is not used. This
is so the stack has guard pages, to help with detecting stack
overflows.
Task switch is done by resuming the thread for the next task by
sending it the resume signal (SIGUSR1) and then suspending the current
thread.
The timer interrupt uses SIGALRM and care is taken to ensure that the
signal handler runs only on the thread for the current task.
The additional data needed per-thread is stored at the top on the
task's stack.
When a running task is being deleted, its thread is marked it as dying
so when we switch away from it it exits instead of suspending. This
ensures that even if the idle task doesn't run, threads are deleted
which allows for more threads to be created (if many tasks are being
created and deleted in rapid succession).
To further aid debugging, SIGINT (^C) is not blocked inside critical
sections. This allows it to be used break into GDB while in a critical
section. This means that care must be taken with any custom SIGINT
handlers as these are like NMIs.
This is somewhat inspired by an existing port by William Davy
(https://www.freertos.org/FreeRTOS-simulator-for-Linux.html) but it
takes a number of different approaches to make it switch tasks
reliableand there's little similarly with the original implementation.
- Critical sections block scheduling/"interrupts" by blocking signals
using pthread_sigmask(). This is more expensive than attempting to
use flags but works reliably and is analogous to the interrupt
enable/disable on real hardware.
- Care is take to ensure that the SIGALRM handler (for the timer tick)
is runnable only on the pthread for the running task. This makes
tasks switches more straight-forward and reliable as we can suspend
the thread while in the signal handler.
- Task switches save/restore the critical nesting on the stack.
- Only uses a single (SIGUSR1) signal which is ignored and thus GDB's
default signal handling options won't trap/print on this signal.
- Extra per-thread data is stored on the task's stack, making it
accessible in O(1) instead of performing a O(n) lookup of the array.
- Uses the task create/delete hooks in a similar way to the Windows
port, rather than overloading trace points.