portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/*
|
|
|
|
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
|
|
|
* Copyright (C) 2020 Cambridge Consultants Ltd.
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
* 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
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------
|
|
|
|
* Implementation of functions defined in portable.h for the Posix port.
|
|
|
|
*
|
|
|
|
* Each task has a pthread which eases use of standard debuggers
|
|
|
|
* (allowing backtraces of tasks etc). Threads for tasks that are not
|
|
|
|
* running are blocked in sigwait().
|
|
|
|
*
|
|
|
|
* Task switch is done by resuming the thread for the next task by
|
|
|
|
* signaling the condition variable and then waiting on a condition variable
|
|
|
|
* with 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.
|
|
|
|
*
|
|
|
|
* Use of part of the standard C library requires care as some
|
|
|
|
* functions can take pthread mutexes internally which can result in
|
|
|
|
* deadlocks as the FreeRTOS kernel can switch tasks while they're
|
|
|
|
* holding a pthread mutex.
|
|
|
|
*
|
|
|
|
* stdio (printf() and friends) should be called from a single task
|
|
|
|
* only or serialized with a FreeRTOS primitive such as a binary
|
|
|
|
* semaphore or mutex.
|
|
|
|
*----------------------------------------------------------*/
|
|
|
|
#include "portmacro.h"
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
#define __USE_GNU
|
|
|
|
#endif
|
|
|
|
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
#include <errno.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/times.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#include <mach/mach_vm.h>
|
|
|
|
#endif
|
|
|
|
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/* Scheduler includes. */
|
|
|
|
#include "FreeRTOS.h"
|
|
|
|
#include "task.h"
|
|
|
|
#include "list.h"
|
|
|
|
#include "timers.h"
|
|
|
|
#include "utils/wait_for_event.h"
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
#define SIG_RESUME SIGUSR1
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
typedef struct THREAD
|
|
|
|
{
|
|
|
|
pthread_t pthread;
|
|
|
|
TaskFunction_t pxCode;
|
|
|
|
void * pvParams;
|
|
|
|
BaseType_t xDying;
|
|
|
|
struct event * ev;
|
|
|
|
ListItem_t xThreadListItem;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
} Thread_t;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The additional per-thread data is stored at the beginning of the
|
|
|
|
* task's stack.
|
|
|
|
*/
|
|
|
|
static inline Thread_t * prvGetThreadFromTask( TaskHandle_t xTask )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
StackType_t * pxTopOfStack = *( StackType_t ** ) xTask;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
return ( Thread_t * ) ( pxTopOfStack + 1 );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT;
|
|
|
|
static sigset_t xAllSignals;
|
|
|
|
static sigset_t xSchedulerOriginalSignalMask;
|
|
|
|
static pthread_t hMainThread = ( pthread_t ) NULL;
|
|
|
|
static volatile BaseType_t uxCriticalNesting;
|
|
|
|
static BaseType_t xSchedulerEnd = pdFALSE;
|
|
|
|
static pthread_t hTimerTickThread;
|
|
|
|
static bool xTimerTickThreadShouldRun;
|
|
|
|
static uint64_t prvStartTimeNs;
|
|
|
|
static List_t xThreadList;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvSetupSignalsAndSchedulerPolicy( void );
|
|
|
|
static void prvSetupTimerInterrupt( void );
|
|
|
|
static void * prvWaitForStart( void * pvParams );
|
|
|
|
static void prvSwitchThread( Thread_t * xThreadToResume,
|
|
|
|
Thread_t * xThreadToSuspend );
|
|
|
|
static void prvSuspendSelf( Thread_t * thread );
|
|
|
|
static void prvResumeThread( Thread_t * xThreadId );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
static void vPortSystemTickHandler( int sig );
|
|
|
|
static void vPortStartFirstTask( void );
|
|
|
|
static void prvPortYieldFromISR( void );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvFatalError( const char * pcCall,
|
|
|
|
int iErrno ) __attribute__( ( __noreturn__ ) );
|
|
|
|
|
|
|
|
void prvFatalError( const char * pcCall,
|
|
|
|
int iErrno )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) );
|
|
|
|
abort();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
static void prvPortSetCurrentThreadName(char * pxThreadName)
|
|
|
|
{
|
|
|
|
#ifdef __APPLE__
|
|
|
|
pthread_setname_np(pxThreadName);
|
|
|
|
#else
|
|
|
|
pthread_setname_np(pthread_self(), pxThreadName);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/*
|
|
|
|
* See header file for description.
|
|
|
|
*/
|
|
|
|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
|
|
|
|
StackType_t * pxEndOfStack,
|
|
|
|
TaskFunction_t pxCode,
|
|
|
|
void * pvParameters )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
Thread_t * thread;
|
|
|
|
pthread_attr_t xThreadAttributes;
|
|
|
|
size_t ulStackSize;
|
|
|
|
int iRet;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
( void ) pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/*
|
|
|
|
* Store the additional thread data at the start of the stack.
|
|
|
|
*/
|
|
|
|
thread = ( Thread_t * ) ( pxTopOfStack + 1 ) - 1;
|
|
|
|
pxTopOfStack = ( StackType_t * ) thread - 1;
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
pxEndOfStack = ( StackType_t * ) mach_vm_round_page( pxEndOfStack );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ulStackSize = ( size_t ) ( pxTopOfStack + 1 - pxEndOfStack ) * sizeof( *pxTopOfStack );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
ulStackSize = mach_vm_trunc_page( ulStackSize );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
thread->pxCode = pxCode;
|
|
|
|
thread->pvParams = pvParameters;
|
|
|
|
thread->xDying = pdFALSE;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
POSIX port - Switch from allowing the user to specify the stack memory itself, to allowing them to specify the stack size
Change from pthread_attr_setstack() to pthread_attr_setstacksize(), and automatically adjust the stack size
to be at least PTHREAD_STACK_MIN if it wasn't already, removing the size warning.
This permits the user to increase the pthread stack size beyond the PTHREAD_STACK_MIN default of 16384 if
desired, without producing a warning in the typical case where stacks are minimized for RAM limited targets.
Continue to store thread paramters on the provided stack, for consistency with the MCU targets.
Previously pthread_attr_setstack() was used to enable user defined stacks.
Note that:
1. The stack size can still be specified by the user.
2. pxPortInitialiseStack(), and pthread_addr_setstack() was failing on stacks of typical size, as
these are smaller than PTHREAD_STACK_MIN (16384) bytes, and printing out a series of warnings.
Improve usability by having the posix port automatically increase the stack size to be
at least PTHREAD_STACK_MIN as posix platforms have enough memory for this not to be a concern.
3. Reuse of stack memory will also result in valgrind 'invalid write' errors to what is demonstrably
valid memory. Root cause is that Valgrind is tracking a stack pointer as the stack is used.
Reuse of a stack buffer results in the stack being used at its start, in an area that Valgrind thinks
is far away from the start of the stack. There are ways to notify Valgrind of these changes
however this would require linking against and calling Valgrind functions from the FreeRTOS application using
the posix port, https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq.
Also, apparently it isn't permitted by posix to reuse stack memory once its been used in a pthread via pthread_attr_setstack(),
see https://stackoverflow.com/a/5422134
1 year ago
|
|
|
/* Ensure ulStackSize is at least PTHREAD_STACK_MIN */
|
|
|
|
ulStackSize = (ulStackSize < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : ulStackSize;
|
|
|
|
|
|
|
|
pthread_attr_init( &xThreadAttributes );
|
POSIX port - Switch from allowing the user to specify the stack memory itself, to allowing them to specify the stack size
Change from pthread_attr_setstack() to pthread_attr_setstacksize(), and automatically adjust the stack size
to be at least PTHREAD_STACK_MIN if it wasn't already, removing the size warning.
This permits the user to increase the pthread stack size beyond the PTHREAD_STACK_MIN default of 16384 if
desired, without producing a warning in the typical case where stacks are minimized for RAM limited targets.
Continue to store thread paramters on the provided stack, for consistency with the MCU targets.
Previously pthread_attr_setstack() was used to enable user defined stacks.
Note that:
1. The stack size can still be specified by the user.
2. pxPortInitialiseStack(), and pthread_addr_setstack() was failing on stacks of typical size, as
these are smaller than PTHREAD_STACK_MIN (16384) bytes, and printing out a series of warnings.
Improve usability by having the posix port automatically increase the stack size to be
at least PTHREAD_STACK_MIN as posix platforms have enough memory for this not to be a concern.
3. Reuse of stack memory will also result in valgrind 'invalid write' errors to what is demonstrably
valid memory. Root cause is that Valgrind is tracking a stack pointer as the stack is used.
Reuse of a stack buffer results in the stack being used at its start, in an area that Valgrind thinks
is far away from the start of the stack. There are ways to notify Valgrind of these changes
however this would require linking against and calling Valgrind functions from the FreeRTOS application using
the posix port, https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq.
Also, apparently it isn't permitted by posix to reuse stack memory once its been used in a pthread via pthread_attr_setstack(),
see https://stackoverflow.com/a/5422134
1 year ago
|
|
|
iRet = pthread_attr_setstacksize( &xThreadAttributes, ulStackSize );
|
|
|
|
|
|
|
|
if( iRet != 0 )
|
|
|
|
{
|
POSIX port - Switch from allowing the user to specify the stack memory itself, to allowing them to specify the stack size
Change from pthread_attr_setstack() to pthread_attr_setstacksize(), and automatically adjust the stack size
to be at least PTHREAD_STACK_MIN if it wasn't already, removing the size warning.
This permits the user to increase the pthread stack size beyond the PTHREAD_STACK_MIN default of 16384 if
desired, without producing a warning in the typical case where stacks are minimized for RAM limited targets.
Continue to store thread paramters on the provided stack, for consistency with the MCU targets.
Previously pthread_attr_setstack() was used to enable user defined stacks.
Note that:
1. The stack size can still be specified by the user.
2. pxPortInitialiseStack(), and pthread_addr_setstack() was failing on stacks of typical size, as
these are smaller than PTHREAD_STACK_MIN (16384) bytes, and printing out a series of warnings.
Improve usability by having the posix port automatically increase the stack size to be
at least PTHREAD_STACK_MIN as posix platforms have enough memory for this not to be a concern.
3. Reuse of stack memory will also result in valgrind 'invalid write' errors to what is demonstrably
valid memory. Root cause is that Valgrind is tracking a stack pointer as the stack is used.
Reuse of a stack buffer results in the stack being used at its start, in an area that Valgrind thinks
is far away from the start of the stack. There are ways to notify Valgrind of these changes
however this would require linking against and calling Valgrind functions from the FreeRTOS application using
the posix port, https://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq.
Also, apparently it isn't permitted by posix to reuse stack memory once its been used in a pthread via pthread_attr_setstack(),
see https://stackoverflow.com/a/5422134
1 year ago
|
|
|
fprintf( stderr, "[WARN] pthread_attr_setstacksize failed with return value: %d. Default stack size will be used.\n", iRet );
|
|
|
|
}
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
thread->ev = event_create();
|
|
|
|
|
|
|
|
vListInitialiseItem( &thread->xThreadListItem );
|
|
|
|
listSET_LIST_ITEM_OWNER( &thread->xThreadListItem, thread );
|
|
|
|
|
|
|
|
vPortEnterCritical();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Add the new thread in xThreadList. */
|
|
|
|
vListInsertEnd( &xThreadList, &thread->xThreadListItem );
|
|
|
|
|
|
|
|
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
|
|
|
|
prvWaitForStart, thread );
|
|
|
|
|
|
|
|
if( iRet != 0 )
|
|
|
|
{
|
|
|
|
prvFatalError( "pthread_create", iRet );
|
|
|
|
}
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
vPortExitCritical();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
return pxTopOfStack;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortStartFirstTask( void )
|
|
|
|
{
|
|
|
|
Thread_t * pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Start the first task. */
|
|
|
|
prvResumeThread( pxFirstThread );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See header file for description.
|
|
|
|
*/
|
|
|
|
BaseType_t xPortStartScheduler( void )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
int iSignal;
|
|
|
|
sigset_t xSignals;
|
|
|
|
ListItem_t * pxIterator;
|
|
|
|
const ListItem_t * pxEndMarker;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
hMainThread = pthread_self();
|
|
|
|
prvPortSetCurrentThreadName("Scheduler");
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Start the timer that generates the tick ISR(SIGALRM).
|
|
|
|
* Interrupts are disabled here already. */
|
|
|
|
prvSetupTimerInterrupt();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/*
|
|
|
|
* Block SIG_RESUME before starting any tasks so the main thread can sigwait on it.
|
|
|
|
* To sigwait on an unblocked signal is undefined.
|
|
|
|
* https://pubs.opengroup.org/onlinepubs/009604499/functions/sigwait.html
|
|
|
|
*/
|
|
|
|
sigemptyset( &xSignals );
|
|
|
|
sigaddset( &xSignals, SIG_RESUME );
|
|
|
|
( void ) pthread_sigmask( SIG_BLOCK, &xSignals, NULL );
|
|
|
|
|
|
|
|
/* Start the first task. */
|
|
|
|
vPortStartFirstTask();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Wait until signaled by vPortEndScheduler(). */
|
|
|
|
while( xSchedulerEnd != pdTRUE )
|
|
|
|
{
|
|
|
|
sigwait( &xSignals, &iSignal );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cancel all the running thread. */
|
|
|
|
pxEndMarker = listGET_END_MARKER( &xThreadList );
|
|
|
|
|
|
|
|
for( pxIterator = listGET_HEAD_ENTRY( &xThreadList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
|
|
|
|
{
|
|
|
|
Thread_t * pxThread = ( Thread_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
|
|
|
|
|
|
|
|
pthread_cancel( pxThread->pthread );
|
|
|
|
event_signal( pxThread->ev );
|
|
|
|
pthread_join( pxThread->pthread, NULL );
|
|
|
|
event_delete( pxThread->ev );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* clear out the variable that is used to end the scheduler, otherwise
|
|
|
|
* subsequent scheduler restarts will end immediately.
|
|
|
|
*/
|
|
|
|
xSchedulerEnd = pdFALSE;
|
|
|
|
|
|
|
|
/* Reset the pthread_once_t structure. This is required if the port
|
|
|
|
* starts the scheduler again. */
|
|
|
|
hSigSetupThread = PTHREAD_ONCE_INIT;
|
|
|
|
|
|
|
|
/* Restore original signal mask. */
|
|
|
|
( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
return 0;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortEndScheduler( void )
|
|
|
|
{
|
|
|
|
/* Stop the timer tick thread. */
|
|
|
|
xTimerTickThreadShouldRun = false;
|
|
|
|
pthread_join( hTimerTickThread, NULL );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Signal the scheduler to exit its loop. */
|
|
|
|
xSchedulerEnd = pdTRUE;
|
|
|
|
( void ) pthread_kill( hMainThread, SIG_RESUME );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
pthread_exit( NULL );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortEnterCritical( void )
|
|
|
|
{
|
|
|
|
if( uxCriticalNesting == 0 )
|
|
|
|
{
|
|
|
|
vPortDisableInterrupts();
|
|
|
|
}
|
|
|
|
|
|
|
|
uxCriticalNesting++;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortExitCritical( void )
|
|
|
|
{
|
|
|
|
uxCriticalNesting--;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* If we have reached 0 then re-enable the interrupts. */
|
|
|
|
if( uxCriticalNesting == 0 )
|
|
|
|
{
|
|
|
|
vPortEnableInterrupts();
|
|
|
|
}
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvPortYieldFromISR( void )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
Thread_t * xThreadToSuspend;
|
|
|
|
Thread_t * xThreadToResume;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
vTaskSwitchContext();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
prvSwitchThread( xThreadToResume, xThreadToSuspend );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortYield( void )
|
|
|
|
{
|
|
|
|
vPortEnterCritical();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
prvPortYieldFromISR();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
vPortExitCritical();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortDisableInterrupts( void )
|
|
|
|
{
|
|
|
|
pthread_sigmask( SIG_BLOCK, &xAllSignals, NULL );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortEnableInterrupts( void )
|
|
|
|
{
|
|
|
|
pthread_sigmask( SIG_UNBLOCK, &xAllSignals, NULL );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
UBaseType_t xPortSetInterruptMask( void )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
/* Interrupts are always disabled inside ISRs (signals
|
|
|
|
* handlers). */
|
|
|
|
return ( UBaseType_t ) 0;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortClearInterruptMask( UBaseType_t uxMask )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
( void ) uxMask;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static uint64_t prvGetTimeNs( void )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
struct timespec t;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
clock_gettime( CLOCK_MONOTONIC, &t );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
return ( uint64_t ) t.tv_sec * ( uint64_t ) 1000000000UL + ( uint64_t ) t.tv_nsec;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
/* commented as part of the code below in vPortSystemTickHandler,
|
|
|
|
* to adjust timing according to full demo requirements */
|
|
|
|
/* static uint64_t prvTickCount; */
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
static void * prvTimerTickHandler( void * arg )
|
POSIX - Switch from posix timers to a timer thread to fix signal handling with non-FreeRTOS pthreads
Improve upon the elegant approach of using signals to cause task/pthreads
suspension and scheduler execution by using directed signals.
This fixes:
- Deadlocks in non-FreeRTOS pthreads
- Multiple FreeRTOS tasks(pthreads) incorrectly running at the same time
By directing the signals using pthread_kill() the signal handler in the presently running
FreeRTOS task/pthread will be called, ensuring that the scheduler runs both in the context
of a FreeRTOS task/pthread and from the presently executing FreeRTOS task/pthread.
Details
==============
The POSIX port uses signals to preempt FreeRTOS tasks (implemented as pthreads), a very neat and elegant
approach to forcing tasks/pthreads to suspend and run the scheduler.
Signal handlers are process global.
Posix timers generate signals when the timer expires, and the signal is sent to the currently
running pthread.
In systems where there are pthreads that are NOT a result of creating FreeRTOS tasks, such as the
entry point thread that calls main(), or user created pthreads, this poses a serious issue.
While the POSIX port only allows a single FreeRTOS pthread to run at once, by causing all suspended
threads to not be scheduled due to their waiting on a pthread condition variable,
this isn't the case with non-FreeRTOS pthreads.
Thus it is possible that a non-FreeRTOS pthread is running when the timer expires and the signal
is generated. This results in the signal handler running in the non-FreeRTOS thread.
The sequence of events results in these events from signal handler context:
- vPortSystemTickHandler() being called
- The scheduler running
- Selecting another FreeRTOS task to run and switching the active task
- The newly selected task released from suspension by pthread_cond_signal()
- The presently active thread calling event_wait()
- The pthread calling pthread_cond_wait(), suspending the thread and allowing the host OS scheduler
to schedule another thread to run.
If this occurs from a non-FreeRTOS thread this results in:
- The active FreeRTOS pthread (Task A/Thread A) continuing to run (as the signal handler that calls
event_wait() ran instead in a non-FreeRTOS pthread.
- The pthread where the signal handler did run (Thread B) will call event_wait() and pthread_cond_wait(),
but on the condition variable of the previously active FreeRTOS task, oops. This causes the
non-FreeRTOS pthread to block unexpectedly relative to what the developer might have expected.
- The newly selected FreeRTOS Task (Task C/Thread C) will resume and start running.
At this point Task A/Thread A is running concurrently with Task C/Thread C. While this may not
necessarily be an issue, it does not replicate the expected behavior of a single Task running at
once.
Note that Thread B will resume if/when Task A/ThreadA is switched to. However, this could be delayed
by an arbitrary amount of time, or could never occur.
Also note that if there are multiple non-FreeRTOS pthreads that Thread D, E, F...etc could suffer the
same fate as Thread B, if the scheduler were to suspend Task C/Thread C and resume Task E/Thread E.
Implementation
==============
Timer details
-------------
A standalone pthread for the signal generation thread was chosen, rather than using
a posix timer_settime() handler function because the latter creates a temporary
pthread for each handler callback. This makes debugging much more difficult due to
gdb detecting the creation and destruction of these temporary threads.
Signal delivery
--------------
While signal handlers are per-thread, it is possible for pthreads to selectively block
signals, rather than using thread directed signals. However, the approach of blocking
signals in non-FreeRTOS pthreads adds complexity to each of these non-FreeRTOS pthreads
including ensuring that these signals are blocked at thread creation, prior to the thread
starting up. Directed signals removes the requirement for non-FreeRTOS pthreads to be aware
of and take action to protect against these signals, reducing complexity.
1 year ago
|
|
|
{
|
|
|
|
( void ) arg;
|
|
|
|
|
|
|
|
prvPortSetCurrentThreadName("Scheduler timer");
|
|
|
|
|
|
|
|
while( xTimerTickThreadShouldRun )
|
POSIX - Switch from posix timers to a timer thread to fix signal handling with non-FreeRTOS pthreads
Improve upon the elegant approach of using signals to cause task/pthreads
suspension and scheduler execution by using directed signals.
This fixes:
- Deadlocks in non-FreeRTOS pthreads
- Multiple FreeRTOS tasks(pthreads) incorrectly running at the same time
By directing the signals using pthread_kill() the signal handler in the presently running
FreeRTOS task/pthread will be called, ensuring that the scheduler runs both in the context
of a FreeRTOS task/pthread and from the presently executing FreeRTOS task/pthread.
Details
==============
The POSIX port uses signals to preempt FreeRTOS tasks (implemented as pthreads), a very neat and elegant
approach to forcing tasks/pthreads to suspend and run the scheduler.
Signal handlers are process global.
Posix timers generate signals when the timer expires, and the signal is sent to the currently
running pthread.
In systems where there are pthreads that are NOT a result of creating FreeRTOS tasks, such as the
entry point thread that calls main(), or user created pthreads, this poses a serious issue.
While the POSIX port only allows a single FreeRTOS pthread to run at once, by causing all suspended
threads to not be scheduled due to their waiting on a pthread condition variable,
this isn't the case with non-FreeRTOS pthreads.
Thus it is possible that a non-FreeRTOS pthread is running when the timer expires and the signal
is generated. This results in the signal handler running in the non-FreeRTOS thread.
The sequence of events results in these events from signal handler context:
- vPortSystemTickHandler() being called
- The scheduler running
- Selecting another FreeRTOS task to run and switching the active task
- The newly selected task released from suspension by pthread_cond_signal()
- The presently active thread calling event_wait()
- The pthread calling pthread_cond_wait(), suspending the thread and allowing the host OS scheduler
to schedule another thread to run.
If this occurs from a non-FreeRTOS thread this results in:
- The active FreeRTOS pthread (Task A/Thread A) continuing to run (as the signal handler that calls
event_wait() ran instead in a non-FreeRTOS pthread.
- The pthread where the signal handler did run (Thread B) will call event_wait() and pthread_cond_wait(),
but on the condition variable of the previously active FreeRTOS task, oops. This causes the
non-FreeRTOS pthread to block unexpectedly relative to what the developer might have expected.
- The newly selected FreeRTOS Task (Task C/Thread C) will resume and start running.
At this point Task A/Thread A is running concurrently with Task C/Thread C. While this may not
necessarily be an issue, it does not replicate the expected behavior of a single Task running at
once.
Note that Thread B will resume if/when Task A/ThreadA is switched to. However, this could be delayed
by an arbitrary amount of time, or could never occur.
Also note that if there are multiple non-FreeRTOS pthreads that Thread D, E, F...etc could suffer the
same fate as Thread B, if the scheduler were to suspend Task C/Thread C and resume Task E/Thread E.
Implementation
==============
Timer details
-------------
A standalone pthread for the signal generation thread was chosen, rather than using
a posix timer_settime() handler function because the latter creates a temporary
pthread for each handler callback. This makes debugging much more difficult due to
gdb detecting the creation and destruction of these temporary threads.
Signal delivery
--------------
While signal handlers are per-thread, it is possible for pthreads to selectively block
signals, rather than using thread directed signals. However, the approach of blocking
signals in non-FreeRTOS pthreads adds complexity to each of these non-FreeRTOS pthreads
including ensuring that these signals are blocked at thread creation, prior to the thread
starting up. Directed signals removes the requirement for non-FreeRTOS pthreads to be aware
of and take action to protect against these signals, reducing complexity.
1 year ago
|
|
|
{
|
|
|
|
/*
|
|
|
|
* signal to the active task to cause tick handling or
|
|
|
|
* preemption (if enabled)
|
|
|
|
*/
|
|
|
|
Thread_t * thread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
|
|
|
pthread_kill( thread->pthread, SIGALRM );
|
POSIX - Switch from posix timers to a timer thread to fix signal handling with non-FreeRTOS pthreads
Improve upon the elegant approach of using signals to cause task/pthreads
suspension and scheduler execution by using directed signals.
This fixes:
- Deadlocks in non-FreeRTOS pthreads
- Multiple FreeRTOS tasks(pthreads) incorrectly running at the same time
By directing the signals using pthread_kill() the signal handler in the presently running
FreeRTOS task/pthread will be called, ensuring that the scheduler runs both in the context
of a FreeRTOS task/pthread and from the presently executing FreeRTOS task/pthread.
Details
==============
The POSIX port uses signals to preempt FreeRTOS tasks (implemented as pthreads), a very neat and elegant
approach to forcing tasks/pthreads to suspend and run the scheduler.
Signal handlers are process global.
Posix timers generate signals when the timer expires, and the signal is sent to the currently
running pthread.
In systems where there are pthreads that are NOT a result of creating FreeRTOS tasks, such as the
entry point thread that calls main(), or user created pthreads, this poses a serious issue.
While the POSIX port only allows a single FreeRTOS pthread to run at once, by causing all suspended
threads to not be scheduled due to their waiting on a pthread condition variable,
this isn't the case with non-FreeRTOS pthreads.
Thus it is possible that a non-FreeRTOS pthread is running when the timer expires and the signal
is generated. This results in the signal handler running in the non-FreeRTOS thread.
The sequence of events results in these events from signal handler context:
- vPortSystemTickHandler() being called
- The scheduler running
- Selecting another FreeRTOS task to run and switching the active task
- The newly selected task released from suspension by pthread_cond_signal()
- The presently active thread calling event_wait()
- The pthread calling pthread_cond_wait(), suspending the thread and allowing the host OS scheduler
to schedule another thread to run.
If this occurs from a non-FreeRTOS thread this results in:
- The active FreeRTOS pthread (Task A/Thread A) continuing to run (as the signal handler that calls
event_wait() ran instead in a non-FreeRTOS pthread.
- The pthread where the signal handler did run (Thread B) will call event_wait() and pthread_cond_wait(),
but on the condition variable of the previously active FreeRTOS task, oops. This causes the
non-FreeRTOS pthread to block unexpectedly relative to what the developer might have expected.
- The newly selected FreeRTOS Task (Task C/Thread C) will resume and start running.
At this point Task A/Thread A is running concurrently with Task C/Thread C. While this may not
necessarily be an issue, it does not replicate the expected behavior of a single Task running at
once.
Note that Thread B will resume if/when Task A/ThreadA is switched to. However, this could be delayed
by an arbitrary amount of time, or could never occur.
Also note that if there are multiple non-FreeRTOS pthreads that Thread D, E, F...etc could suffer the
same fate as Thread B, if the scheduler were to suspend Task C/Thread C and resume Task E/Thread E.
Implementation
==============
Timer details
-------------
A standalone pthread for the signal generation thread was chosen, rather than using
a posix timer_settime() handler function because the latter creates a temporary
pthread for each handler callback. This makes debugging much more difficult due to
gdb detecting the creation and destruction of these temporary threads.
Signal delivery
--------------
While signal handlers are per-thread, it is possible for pthreads to selectively block
signals, rather than using thread directed signals. However, the approach of blocking
signals in non-FreeRTOS pthreads adds complexity to each of these non-FreeRTOS pthreads
including ensuring that these signals are blocked at thread creation, prior to the thread
starting up. Directed signals removes the requirement for non-FreeRTOS pthreads to be aware
of and take action to protect against these signals, reducing complexity.
1 year ago
|
|
|
usleep( portTICK_RATE_MICROSECONDS );
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
POSIX - Switch from posix timers to a timer thread to fix signal handling with non-FreeRTOS pthreads
Improve upon the elegant approach of using signals to cause task/pthreads
suspension and scheduler execution by using directed signals.
This fixes:
- Deadlocks in non-FreeRTOS pthreads
- Multiple FreeRTOS tasks(pthreads) incorrectly running at the same time
By directing the signals using pthread_kill() the signal handler in the presently running
FreeRTOS task/pthread will be called, ensuring that the scheduler runs both in the context
of a FreeRTOS task/pthread and from the presently executing FreeRTOS task/pthread.
Details
==============
The POSIX port uses signals to preempt FreeRTOS tasks (implemented as pthreads), a very neat and elegant
approach to forcing tasks/pthreads to suspend and run the scheduler.
Signal handlers are process global.
Posix timers generate signals when the timer expires, and the signal is sent to the currently
running pthread.
In systems where there are pthreads that are NOT a result of creating FreeRTOS tasks, such as the
entry point thread that calls main(), or user created pthreads, this poses a serious issue.
While the POSIX port only allows a single FreeRTOS pthread to run at once, by causing all suspended
threads to not be scheduled due to their waiting on a pthread condition variable,
this isn't the case with non-FreeRTOS pthreads.
Thus it is possible that a non-FreeRTOS pthread is running when the timer expires and the signal
is generated. This results in the signal handler running in the non-FreeRTOS thread.
The sequence of events results in these events from signal handler context:
- vPortSystemTickHandler() being called
- The scheduler running
- Selecting another FreeRTOS task to run and switching the active task
- The newly selected task released from suspension by pthread_cond_signal()
- The presently active thread calling event_wait()
- The pthread calling pthread_cond_wait(), suspending the thread and allowing the host OS scheduler
to schedule another thread to run.
If this occurs from a non-FreeRTOS thread this results in:
- The active FreeRTOS pthread (Task A/Thread A) continuing to run (as the signal handler that calls
event_wait() ran instead in a non-FreeRTOS pthread.
- The pthread where the signal handler did run (Thread B) will call event_wait() and pthread_cond_wait(),
but on the condition variable of the previously active FreeRTOS task, oops. This causes the
non-FreeRTOS pthread to block unexpectedly relative to what the developer might have expected.
- The newly selected FreeRTOS Task (Task C/Thread C) will resume and start running.
At this point Task A/Thread A is running concurrently with Task C/Thread C. While this may not
necessarily be an issue, it does not replicate the expected behavior of a single Task running at
once.
Note that Thread B will resume if/when Task A/ThreadA is switched to. However, this could be delayed
by an arbitrary amount of time, or could never occur.
Also note that if there are multiple non-FreeRTOS pthreads that Thread D, E, F...etc could suffer the
same fate as Thread B, if the scheduler were to suspend Task C/Thread C and resume Task E/Thread E.
Implementation
==============
Timer details
-------------
A standalone pthread for the signal generation thread was chosen, rather than using
a posix timer_settime() handler function because the latter creates a temporary
pthread for each handler callback. This makes debugging much more difficult due to
gdb detecting the creation and destruction of these temporary threads.
Signal delivery
--------------
While signal handlers are per-thread, it is possible for pthreads to selectively block
signals, rather than using thread directed signals. However, the approach of blocking
signals in non-FreeRTOS pthreads adds complexity to each of these non-FreeRTOS pthreads
including ensuring that these signals are blocked at thread creation, prior to the thread
starting up. Directed signals removes the requirement for non-FreeRTOS pthreads to be aware
of and take action to protect against these signals, reducing complexity.
1 year ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
POSIX - Switch from posix timers to a timer thread to fix signal handling with non-FreeRTOS pthreads
Improve upon the elegant approach of using signals to cause task/pthreads
suspension and scheduler execution by using directed signals.
This fixes:
- Deadlocks in non-FreeRTOS pthreads
- Multiple FreeRTOS tasks(pthreads) incorrectly running at the same time
By directing the signals using pthread_kill() the signal handler in the presently running
FreeRTOS task/pthread will be called, ensuring that the scheduler runs both in the context
of a FreeRTOS task/pthread and from the presently executing FreeRTOS task/pthread.
Details
==============
The POSIX port uses signals to preempt FreeRTOS tasks (implemented as pthreads), a very neat and elegant
approach to forcing tasks/pthreads to suspend and run the scheduler.
Signal handlers are process global.
Posix timers generate signals when the timer expires, and the signal is sent to the currently
running pthread.
In systems where there are pthreads that are NOT a result of creating FreeRTOS tasks, such as the
entry point thread that calls main(), or user created pthreads, this poses a serious issue.
While the POSIX port only allows a single FreeRTOS pthread to run at once, by causing all suspended
threads to not be scheduled due to their waiting on a pthread condition variable,
this isn't the case with non-FreeRTOS pthreads.
Thus it is possible that a non-FreeRTOS pthread is running when the timer expires and the signal
is generated. This results in the signal handler running in the non-FreeRTOS thread.
The sequence of events results in these events from signal handler context:
- vPortSystemTickHandler() being called
- The scheduler running
- Selecting another FreeRTOS task to run and switching the active task
- The newly selected task released from suspension by pthread_cond_signal()
- The presently active thread calling event_wait()
- The pthread calling pthread_cond_wait(), suspending the thread and allowing the host OS scheduler
to schedule another thread to run.
If this occurs from a non-FreeRTOS thread this results in:
- The active FreeRTOS pthread (Task A/Thread A) continuing to run (as the signal handler that calls
event_wait() ran instead in a non-FreeRTOS pthread.
- The pthread where the signal handler did run (Thread B) will call event_wait() and pthread_cond_wait(),
but on the condition variable of the previously active FreeRTOS task, oops. This causes the
non-FreeRTOS pthread to block unexpectedly relative to what the developer might have expected.
- The newly selected FreeRTOS Task (Task C/Thread C) will resume and start running.
At this point Task A/Thread A is running concurrently with Task C/Thread C. While this may not
necessarily be an issue, it does not replicate the expected behavior of a single Task running at
once.
Note that Thread B will resume if/when Task A/ThreadA is switched to. However, this could be delayed
by an arbitrary amount of time, or could never occur.
Also note that if there are multiple non-FreeRTOS pthreads that Thread D, E, F...etc could suffer the
same fate as Thread B, if the scheduler were to suspend Task C/Thread C and resume Task E/Thread E.
Implementation
==============
Timer details
-------------
A standalone pthread for the signal generation thread was chosen, rather than using
a posix timer_settime() handler function because the latter creates a temporary
pthread for each handler callback. This makes debugging much more difficult due to
gdb detecting the creation and destruction of these temporary threads.
Signal delivery
--------------
While signal handlers are per-thread, it is possible for pthreads to selectively block
signals, rather than using thread directed signals. However, the approach of blocking
signals in non-FreeRTOS pthreads adds complexity to each of these non-FreeRTOS pthreads
including ensuring that these signals are blocked at thread creation, prior to the thread
starting up. Directed signals removes the requirement for non-FreeRTOS pthreads to be aware
of and take action to protect against these signals, reducing complexity.
1 year ago
|
|
|
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
/*
|
|
|
|
* Setup the systick timer to generate the tick interrupts at the required
|
|
|
|
* frequency.
|
|
|
|
*/
|
|
|
|
void prvSetupTimerInterrupt( void )
|
|
|
|
{
|
|
|
|
xTimerTickThreadShouldRun = true;
|
POSIX - Switch from posix timers to a timer thread to fix signal handling with non-FreeRTOS pthreads
Improve upon the elegant approach of using signals to cause task/pthreads
suspension and scheduler execution by using directed signals.
This fixes:
- Deadlocks in non-FreeRTOS pthreads
- Multiple FreeRTOS tasks(pthreads) incorrectly running at the same time
By directing the signals using pthread_kill() the signal handler in the presently running
FreeRTOS task/pthread will be called, ensuring that the scheduler runs both in the context
of a FreeRTOS task/pthread and from the presently executing FreeRTOS task/pthread.
Details
==============
The POSIX port uses signals to preempt FreeRTOS tasks (implemented as pthreads), a very neat and elegant
approach to forcing tasks/pthreads to suspend and run the scheduler.
Signal handlers are process global.
Posix timers generate signals when the timer expires, and the signal is sent to the currently
running pthread.
In systems where there are pthreads that are NOT a result of creating FreeRTOS tasks, such as the
entry point thread that calls main(), or user created pthreads, this poses a serious issue.
While the POSIX port only allows a single FreeRTOS pthread to run at once, by causing all suspended
threads to not be scheduled due to their waiting on a pthread condition variable,
this isn't the case with non-FreeRTOS pthreads.
Thus it is possible that a non-FreeRTOS pthread is running when the timer expires and the signal
is generated. This results in the signal handler running in the non-FreeRTOS thread.
The sequence of events results in these events from signal handler context:
- vPortSystemTickHandler() being called
- The scheduler running
- Selecting another FreeRTOS task to run and switching the active task
- The newly selected task released from suspension by pthread_cond_signal()
- The presently active thread calling event_wait()
- The pthread calling pthread_cond_wait(), suspending the thread and allowing the host OS scheduler
to schedule another thread to run.
If this occurs from a non-FreeRTOS thread this results in:
- The active FreeRTOS pthread (Task A/Thread A) continuing to run (as the signal handler that calls
event_wait() ran instead in a non-FreeRTOS pthread.
- The pthread where the signal handler did run (Thread B) will call event_wait() and pthread_cond_wait(),
but on the condition variable of the previously active FreeRTOS task, oops. This causes the
non-FreeRTOS pthread to block unexpectedly relative to what the developer might have expected.
- The newly selected FreeRTOS Task (Task C/Thread C) will resume and start running.
At this point Task A/Thread A is running concurrently with Task C/Thread C. While this may not
necessarily be an issue, it does not replicate the expected behavior of a single Task running at
once.
Note that Thread B will resume if/when Task A/ThreadA is switched to. However, this could be delayed
by an arbitrary amount of time, or could never occur.
Also note that if there are multiple non-FreeRTOS pthreads that Thread D, E, F...etc could suffer the
same fate as Thread B, if the scheduler were to suspend Task C/Thread C and resume Task E/Thread E.
Implementation
==============
Timer details
-------------
A standalone pthread for the signal generation thread was chosen, rather than using
a posix timer_settime() handler function because the latter creates a temporary
pthread for each handler callback. This makes debugging much more difficult due to
gdb detecting the creation and destruction of these temporary threads.
Signal delivery
--------------
While signal handlers are per-thread, it is possible for pthreads to selectively block
signals, rather than using thread directed signals. However, the approach of blocking
signals in non-FreeRTOS pthreads adds complexity to each of these non-FreeRTOS pthreads
including ensuring that these signals are blocked at thread creation, prior to the thread
starting up. Directed signals removes the requirement for non-FreeRTOS pthreads to be aware
of and take action to protect against these signals, reducing complexity.
1 year ago
|
|
|
pthread_create( &hTimerTickThread, NULL, prvTimerTickHandler, NULL );
|
|
|
|
|
|
|
|
prvStartTimeNs = prvGetTimeNs();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void vPortSystemTickHandler( int sig )
|
|
|
|
{
|
|
|
|
Thread_t * pxThreadToSuspend;
|
|
|
|
Thread_t * pxThreadToResume;
|
|
|
|
|
|
|
|
( void ) sig;
|
|
|
|
|
|
|
|
/* uint64_t xExpectedTicks; */
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
uxCriticalNesting++; /* Signals are blocked in this signal handler. */
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
|
|
pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
|
|
|
#endif
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Tick Increment, accounting for any lost signals or drift in
|
|
|
|
* the timer. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Comment code to adjust timing according to full demo requirements
|
|
|
|
* xExpectedTicks = (prvGetTimeNs() - prvStartTimeNs)
|
|
|
|
* / (portTICK_RATE_MICROSECONDS * 1000);
|
|
|
|
* do { */
|
|
|
|
xTaskIncrementTick();
|
|
|
|
|
|
|
|
/* prvTickCount++;
|
|
|
|
* } while (prvTickCount < xExpectedTicks);
|
|
|
|
*/
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
#if ( configUSE_PREEMPTION == 1 )
|
|
|
|
/* Select Next Task. */
|
|
|
|
vTaskSwitchContext();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
prvSwitchThread( pxThreadToResume, pxThreadToSuspend );
|
|
|
|
#endif
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
uxCriticalNesting--;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
void vPortThreadDying( void * pxTaskToDelete,
|
|
|
|
volatile BaseType_t * pxPendYield )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
Thread_t * pxThread = prvGetThreadFromTask( pxTaskToDelete );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
( void ) pxPendYield;
|
|
|
|
|
|
|
|
pxThread->xDying = pdTRUE;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
void vPortCancelThread( void * pxTaskToDelete )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
|
|
|
|
|
|
|
|
/* Remove the thread from xThreadList. */
|
|
|
|
vPortEnterCritical();
|
|
|
|
uxListRemove( &pxThreadToCancel->xThreadListItem );
|
|
|
|
vPortExitCritical();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The thread has already been suspended so it can be safely cancelled.
|
|
|
|
*/
|
|
|
|
pthread_cancel( pxThreadToCancel->pthread );
|
|
|
|
event_signal( pxThreadToCancel->ev );
|
|
|
|
pthread_join( pxThreadToCancel->pthread, NULL );
|
|
|
|
event_delete( pxThreadToCancel->ev );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void * prvWaitForStart( void * pvParams )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
Thread_t * pxThread = pvParams;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
prvSuspendSelf( pxThread );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Resumed for the first time, unblocks all signals. */
|
|
|
|
uxCriticalNesting = 0;
|
|
|
|
vPortEnableInterrupts();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* Set thread name */
|
|
|
|
prvPortSetCurrentThreadName(pcTaskGetName(xTaskGetCurrentTaskHandle()));
|
|
|
|
|
|
|
|
/* Call the task's entry point. */
|
|
|
|
pxThread->pxCode( pxThread->pvParams );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
/* A function that implements a task must not exit or attempt to return to
|
|
|
|
* its caller as there is nothing to return to. If a task wants to exit it
|
|
|
|
* should instead call vTaskDelete( NULL ). Artificially force an assert()
|
|
|
|
* to be triggered if configASSERT() is defined, so application writers can
|
|
|
|
* catch the error. */
|
|
|
|
configASSERT( pdFALSE );
|
|
|
|
|
|
|
|
return NULL;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvSwitchThread( Thread_t * pxThreadToResume,
|
|
|
|
Thread_t * pxThreadToSuspend )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
BaseType_t uxSavedCriticalNesting;
|
|
|
|
|
|
|
|
if( pxThreadToSuspend != pxThreadToResume )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Switch tasks.
|
|
|
|
*
|
|
|
|
* The critical section nesting is per-task, so save it on the
|
|
|
|
* stack of the current (suspending thread), restoring it when
|
|
|
|
* we switch back to this task.
|
|
|
|
*/
|
|
|
|
uxSavedCriticalNesting = uxCriticalNesting;
|
|
|
|
|
|
|
|
prvResumeThread( pxThreadToResume );
|
|
|
|
|
|
|
|
if( pxThreadToSuspend->xDying == pdTRUE )
|
|
|
|
{
|
|
|
|
pthread_exit( NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
prvSuspendSelf( pxThreadToSuspend );
|
|
|
|
|
|
|
|
uxCriticalNesting = uxSavedCriticalNesting;
|
|
|
|
}
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvSuspendSelf( Thread_t * thread )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Suspend this thread by waiting for a pthread_cond_signal event.
|
|
|
|
*
|
|
|
|
* A suspended thread must not handle signals (interrupts) so
|
|
|
|
* all signals must be blocked by calling this from:
|
|
|
|
*
|
|
|
|
* - Inside a critical section (vPortEnterCritical() /
|
|
|
|
* vPortExitCritical()).
|
|
|
|
*
|
|
|
|
* - From a signal handler that has all signals masked.
|
|
|
|
*
|
|
|
|
* - A thread with all signals blocked with pthread_sigmask().
|
|
|
|
*/
|
|
|
|
event_wait( thread->ev );
|
|
|
|
pthread_testcancel();
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvResumeThread( Thread_t * xThreadId )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
if( pthread_self() != xThreadId->pthread )
|
|
|
|
{
|
|
|
|
event_signal( xThreadId->ev );
|
|
|
|
}
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
static void prvSetupSignalsAndSchedulerPolicy( void )
|
|
|
|
{
|
|
|
|
struct sigaction sigtick;
|
|
|
|
int iRet;
|
|
|
|
|
|
|
|
hMainThread = pthread_self();
|
|
|
|
|
|
|
|
/* Setup thread list to record all the task which are not deleted. */
|
|
|
|
vListInitialise( &xThreadList );
|
|
|
|
|
|
|
|
/* Initialise common signal masks. */
|
|
|
|
sigfillset( &xAllSignals );
|
|
|
|
|
|
|
|
/* Don't block SIGINT so this can be used to break into GDB while
|
|
|
|
* in a critical section. */
|
|
|
|
sigdelset( &xAllSignals, SIGINT );
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Block all signals in this thread so all new threads
|
|
|
|
* inherits this mask.
|
|
|
|
*
|
|
|
|
* When a thread is resumed for the first time, all signals
|
|
|
|
* will be unblocked.
|
|
|
|
*/
|
|
|
|
( void ) pthread_sigmask( SIG_SETMASK,
|
|
|
|
&xAllSignals,
|
|
|
|
&xSchedulerOriginalSignalMask );
|
|
|
|
|
|
|
|
sigtick.sa_flags = 0;
|
|
|
|
sigtick.sa_handler = vPortSystemTickHandler;
|
|
|
|
sigfillset( &sigtick.sa_mask );
|
|
|
|
|
|
|
|
iRet = sigaction( SIGALRM, &sigtick, NULL );
|
|
|
|
|
|
|
|
if( iRet == -1 )
|
|
|
|
{
|
|
|
|
prvFatalError( "sigaction", errno );
|
|
|
|
}
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
|
|
uint32_t ulPortGetRunTime( void )
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
{
|
|
|
|
struct tms xTimes;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
times( &xTimes );
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
|
|
|
|
return ( uint32_t ) xTimes.tms_utime;
|
portable/GCC/Posix: add new port for Posix (Linux) applications
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.
5 years ago
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|