CONCURRENT PROGRAMMING WITH RTOS
Authors: Alex.Nikitenko@sirinsoftware.com
D.Vitman@sirinsoftware.com
OVERVIEW
Theory:
Introduction into RTOS.
What is FreeRTOS app.
What is concurrency.
How to create concurrent applications
Practice:
Create a FreeRTOS simple app in simulator.
Create a concurrent app.
Design a task-safe concurrent app.
Run it on PC simulator and stm32 board.
WHAT IS RTOS ESSENTIALLY?
It is a software that meets
two requirements:
Well defined time constraints.
Guaranty of performance.
Memory
managment
Other
components
libraries
Timers
Task
managment
Devices I/OInterrupts
and events
Intertask
communication
and syncro-
nisation
Diagram 1. RTOS kernel parts
WHAT IS RTOS ESSENTIALLY?
Typical RTOS is built into the
application, everything is one
binary file, no dynamic libraries.
There is no bootloader, program
starts from the very beginning.
OS on the other hand has a few
bootloading stages. It has initial
process that is a father of all other
applications and services.
KERNEL
BSP
DRIVERSOS
RTOS
DESKTOP ENV
USER APPs
Diagram 2. RTOS and OS comparison
MAY LINUX BE CALLED RTOS?
Real-time scheduler.
Linux support scheduler with fixed priorities.
Virtual memory organisation.
mlockall - lock all process’s virtual memory
in RAM.
Deterministic interrupt response.
Current linux version support kernel
preemption, PREEMPT_RT patch resolves
the most of non-preemptible paths in the
kernel.
BARE METAL VS RTOS
Multitasking, preemption and scheduler.
RTOS allow to use concurrent programming paradigm. Splitting the
software on tasks makes it modular, improve maintainability and
performance.
Middleware.
RTOS includes USB stacks, network stack and other drivers or
provide a way to integrate with.
Portability and reuse.
RTOS support various platforms. Migration cost can be decreased
dramatically in case chosen RTOS supports new platform.
WHAT RTOS PROVIDE TO PROGRAMMER
Task management and
synchronization primitives.
Memory management
Driver packages, BSPs
RTOS user task and ISR code
RTOS hardware-agnostic code
RTOS hardware-depebdent code
HARDWARE
Diagram 3. Typical RTOS abstraction
levels.
WHY TO LEARN ABOUT RTOS?
To understand what is RTOS actually.
To see more clearly what’s kernel and it’s implementation.
RTOS is a great example of simplified OS kernel.
To be able to program for a majority of uC.
FREERTOS OVERVIEW
Features:
High quality code standards
Open source
Flexible and configurable
Portable, more than 35 architectures supported
Modesty memory use and CPU overhead
Easy to use API
EXAMPLE APPLICATION
main - entry point, as always with C.
xTaskCreate - create a task, it’s
ready to run.
vTaskStartScheduler - starts the
scheduler, before no tasks were
running, now RTOS takes control of
the program flow.
#include ‘‘FreeRTOS.h‘‘
#include ‘‘task.h‘‘
static void function( void *pvParameters )
{
for ( ;; ) ; // do something
}
Int main( void )
{
// init part
xTaskCreate(function, «name», stack_sz, (void*)
data, task_priority, &taskHandle);
vTaskStartScheduler();
vTaskDelete(taskHandle);
return 0;
}
Code 1. Example application
IMPORTANT FILES FOR BUILD
As a minimum, the following source files must be included in your
project:
1. FreeRTOS/Source/tasks.c
2. FreeRTOS/Source/queue.c
3. FreeRTOS/Source/list.c
4. FreeRTOS/Source/portable/[compiler]/[architecture]/{*.c,*.S}
5. FreeRTOS/Source/portable/MemMang/heap_x.c where ‘x’ is 1, 2, 3, 4 or 5.
As well as the following directories should be in compiler’s include
path:
1. FreeRTOS/Source/include
2. FreeRTOS/Source/portable/[compiler]/[architecture]
3. FreeRTOSConfig.h file with FreeRTOS configuration.
CONCURRENCY
Concurrent programming is the
major point of bringing RTOS into
the project.
A unit of computation is a task.
IPC is provided by concurrency
primitives: Semaphores,
Mutexes, Queues, Direct-to-Task
notifications, Event groups, etc.
Concurrent = Two Queens One Coffee Machines
Parallel = Two Queens Two Coffee Machines
Figure 1. Concurrency vs Parallelism
CONCURRENCY IS FOR PERFORMANCE
Concurrent execution can improve performance in three fundamental
ways:
Reduce latency. Make a unit of work execute faster.
Hide latency. Allow the system to continue doing work during a
longatency operation.
Increase throughput. Make the system able to perform more work.
Another advantage should not be foreseen:
Improve program structure. Some problems and problem domains
are well-suited to representation as concurrent tasks or processes
TASKS
Every task has it’s context. Basically
it’s value of the registers.
Task always is in one of four stages.
Task has a priority. Task with bigger
priority preempts running task with
lower.
Suspended
vTaskSuspend()
called
Blocking API
function called
vTaskSuspend()
called
vTaskSuspend()
called
vTaskSuspend()
called
Event
ReadyR unning
Blocked
Diagram 4. Task states
CONCURRENCY PRIMITIVES
Semaphore.
Any visual signaling system with flags,
lights, or mechanically moving arm.
In computer science, a semaphore is a
variable or abstract data type used to
control access to a common resource or
to synchronize tasks.
SEMAPHORE, MORE DETAILED LOOK
A type, can be either binary two
possible values [0, 1] or counting [0, 1,
2,...].
Defined two operations:	
wait (P) and signal (V).
FreeRTOS API:
SemaphoreHandle_t - type
xSemaphoreCreateBinary - create
xSemaphoreTake - wait (P)
xSemaphoreGive - signal (V)
...
APPLICATION
Index increment. Is it safe to increment a variable, integer concurrently?
Let’s check
static void simpleTask( void *pvParameters )
{
uint uTaskId = (uint) pvParameters;
uint i = 0;
for( ;i < 10000000UL; ++i ) {
uIndex++;
}
printf(‘‘%u %un‘‘, uTaskId, uIndex);
// acording to documentation task should not return,
suspend task til exit
vTaskSuspend ( NULL );
}
OUTPUT:
0 13417239
2 14765457
3 14786973
1 14265594
4 14333205
Code 2. Task function example Screen 1. Program output
TIME TO USE SEMAPHORE!
In order to make increment task safe, it is moved into critical section
surrounded by semaphore.
Code 3a. Semaphore initialization.
static SemaphoreHandle_t xSemaphore;
int main ( void )
{
...
xSemaphore = xSemaphoreCreateBinary();
// is it enough memory to create semaphore
configASSERT(xSemaphore);
// init semaphore with a value of 1
xSemaphoreGive(xSemaphore);
...
}
Code 3b. Increment gourded by sema.
static void simpleTask( void *pvParameters )
{
...
uint i = 0;
for( ;i < 10000000UL; ++i ) {
xSemaphoreTake(xSemaphore, portMAX_DELAY);
uIndex++;
xSemaphoreGive(xSemaphore);
}
...
}
SO, ARE THERE ATOMIC INCREMENT AT ALL?
All atomic operations that access memory are processor dependent, for
example ARM instructions . GCC has extension for atomic memory access.
Moreover, concurrency primitives are based on atomic operations.
void wait(Semaphore_t sem) {
// __sync_lock_test_and_set return previous value
while(1 != __sync_lock_test_and_set(&sem, 0)) {
// add task into queue of waiting process
// polling till resource (1) becomes available
}
// if 1 returned than resource was acquired by
current task
}
static void simpleTask( void *pvParameters )
{
...
uint i = 0;
for( ;i < 10000000UL; ++i ) {
__sync_fetch_and_add(&uIndex, 1);
}
...
}
Code 4a. Semaphore wait function impl. Code 4b. Atomic addition.
PROBLEMS IN CONCURRENCY
Let’s consider more generic problems
in concurrency:
Deadlock
Resource starvation
Data corruption/races
Livelock
Priority inversion
REAL WORLD EXAMPLES 1:
Data races in database:
Dirty data. First transaction read data, second one updates the
same data. First transaction return stale or outdated data.
Incorrect update. A person updates data, B person reads old
data, work with it and try to update. A person’s transaction will
be lost.
Incorrect summary. As one process collect summary of some
array of data, others can update it. In consequence of summary
will include some old data and some updated.
REAL WORLD EXAMPLES 2:
Concurrent data structures:
As data structures become
used in concurrent
applications issues of data
integrity arise. Incorporating
lock protection in the turn
bring performance issues,
access to data becomes a
bottleneck.
Diagram 5. Simultaneous removal of i and i+1
list elements. Results in not removed i+1
element
REAL WORLD EXAMPLES 3:
Peripherals:
First task updates display.
Second taks preempts it.
Second taks updates
display and yields
First task wakes, finishes
display update
Thread 1 prints
Thread 2 Thread 3 prints
prints
Thread Thre Thread 2 prints
ad1 prints
4 prints
Screen 2. Concurrent print to consoleDiagram 3. Concurrent access to display
CLASSICAL CONCURRENCY PROBLEM
Five philosophers sit at a round table with
bowls of rice. Chopsticks are placed between
each pair of adjacent philosophers.
Each philosopher must alternately think
and eat. However, a philosopher can only
eat rice when they have both left and right
chopsticks. After an individual philosopher
finishes eating, they need to put down both
chopsticks so that the chopsticks become
available to others. A philosopher can take
the chopstick on their right or the one on
their left as they become available, but
cannot start eating before getting both
chopsticks.
POSSIBLE SOLUTION:
think until the left chopstick is available; when it is, pick it up;
think until the right chopstick is available; when it is, pick it up;
when both chopsticks are held, eat for a fixed amount of time;
then, put the right chopstick down;
then, put the left chopstick down;
IMPLEMENTATION
Every philosopher implemented as a FSM
with 3 states. Functions FSMThinking,
FSMEating and FSMHungry.
struct Philosopher and struct Chopstick
represent main character of our story.
Function simpleTask is task function.
Every philosopher runs its own instance.
More in source...
NO
YES
Thinking
Eating
Hungry
put chopsticks take chopsticks
has 2
chopsticks
chopsticks
available
Diagram 6. Philosopher FSM
DRAWBACKS AND POSSIBLE PROBLEMS:
Deadlock. All philosopher took left
chopstick and no one can take right.
Starvation. No guarantees that that
everyone will get his portion of rice.
Data corruption. Two philosophers can
break a chopstick trying to get it at the
very same time.
Diagram 7. Deadlock
MUTUAL EXCLUSION:
To prevent a deadlock philosopher before acquiring one
chopstick should make sure he will be eventually able to acquire
another one.
To prevent starvation it’s needed to make chopstick distribution
between philosophers as even as possible.
To prevent data chopstick corruption, make sure that
philosophers take turns to get a chopstick.
A generic term, basic idea of the solution.
ANOTHER CHALLENGE FOR THE SEMAPHORE?
Opening docs on semaphore one can see a tip: “Use task notification as
more efficient mean of synchronisation”. So let’s see: Each RTOS task has
a 32-bit notification value...
Efficient usage of memory
and CPU.
No need to create another
variable, variable is already
in task struct.
Can be used as binary or
counting semaphore, event
groups or queue.
Only one task can receive
notifications.
Only one receiving task
can wait sleeping for a
notification.
Advantages: Limitations:
DIRECT TO TASK NOTIFICATION
Can be enabled in config (by
default):
configUSE_TASK_NOTIFICATIONS 1
Represented as two values in
task struct: ulNotifiedValue and
ucNotifyState
Notified value can be set,
overwritten, incremented or used as
bit mask to set value of a single bit.
Direct notification API:
xTaskNotifyWait() waits, with an
optional timeout, for the calling task
to receive a notification.
xTaskNotify() sends an event
directly to and potentially unblock
an RTOS task.
...
TASK SAFE SOLUTION:
wait for a notification that left chopstick is available, pick it up;
wait for a notification that right chopstick is available, pick it up;
when both chopsticks are held, eat for a fixed amount of time;
then, put the right chopstick down;
sent a right philosopher a notification that his left chopstick became
available;
then, put the left chopstick down;
send a left philosopher a notification that his right chopstick became
available;
IMPLEMENTATION
In order to resolve concurrency we use
so called event-driven computing model.
Philosopher how driven by notifications
from other philosophers.
Notification value is used as a bit mask,
first LSB signals that left chopstick is
free, second - right.
Before taking chopstick task wait for
notification using xTaskNotifyWait
function, on putting chopstick task calls
xTaskNotify for left and left philosopher.
NO
NO
YES
YES
Thinking
Eating
Hungry
put chopsticks
notification
take chopsticks
has 2
chopsticks
chopsticks
available
Send notification
to left and right
neighbor
Diagram 7. Philosopher notification
driven FSM
CONCLUSION
Concurrency can improve efficiency and architecture as well as bring
a lot of hard-to-track problems and bugs. It should be kept in mind
throughout all development phases.
All in all, it’s another interesting and challenging journey in programming.
THANK YOU FOR YOUR ATTENTION
Q&A
REFERENCES:
Official FreeRTOS website
GNU compilers’ manual: Atomic Builtins
Intro to Real-Time Linux for Embedded Developers
AC6 System Workbench for STM32
github repo of FreeRTOS PC simulator
Real-world Concurrency
What really happened to the software on the Mars Pathfinder
spacecraft?
From bare-metal to RTOS
Flavors of concurrency by Oleg Shelajev
Practical Guide to Bare Metal C++
THANK YOU VERY MUCH FOR YOUR ATTENTION.
www.sirinsoftware.com
hr@sirinsoftware.com
www.facebook.com/sirinsoftware
twitter.com/Sirin_Software
www.linkedin.com/company/sirinsoftware

Concurrent programming with RTOS

  • 1.
    CONCURRENT PROGRAMMING WITHRTOS Authors: Alex.Nikitenko@sirinsoftware.com D.Vitman@sirinsoftware.com
  • 2.
    OVERVIEW Theory: Introduction into RTOS. Whatis FreeRTOS app. What is concurrency. How to create concurrent applications Practice: Create a FreeRTOS simple app in simulator. Create a concurrent app. Design a task-safe concurrent app. Run it on PC simulator and stm32 board.
  • 3.
    WHAT IS RTOSESSENTIALLY? It is a software that meets two requirements: Well defined time constraints. Guaranty of performance. Memory managment Other components libraries Timers Task managment Devices I/OInterrupts and events Intertask communication and syncro- nisation Diagram 1. RTOS kernel parts
  • 4.
    WHAT IS RTOSESSENTIALLY? Typical RTOS is built into the application, everything is one binary file, no dynamic libraries. There is no bootloader, program starts from the very beginning. OS on the other hand has a few bootloading stages. It has initial process that is a father of all other applications and services. KERNEL BSP DRIVERSOS RTOS DESKTOP ENV USER APPs Diagram 2. RTOS and OS comparison
  • 5.
    MAY LINUX BECALLED RTOS? Real-time scheduler. Linux support scheduler with fixed priorities. Virtual memory organisation. mlockall - lock all process’s virtual memory in RAM. Deterministic interrupt response. Current linux version support kernel preemption, PREEMPT_RT patch resolves the most of non-preemptible paths in the kernel.
  • 6.
    BARE METAL VSRTOS Multitasking, preemption and scheduler. RTOS allow to use concurrent programming paradigm. Splitting the software on tasks makes it modular, improve maintainability and performance. Middleware. RTOS includes USB stacks, network stack and other drivers or provide a way to integrate with. Portability and reuse. RTOS support various platforms. Migration cost can be decreased dramatically in case chosen RTOS supports new platform.
  • 7.
    WHAT RTOS PROVIDETO PROGRAMMER Task management and synchronization primitives. Memory management Driver packages, BSPs RTOS user task and ISR code RTOS hardware-agnostic code RTOS hardware-depebdent code HARDWARE Diagram 3. Typical RTOS abstraction levels.
  • 8.
    WHY TO LEARNABOUT RTOS? To understand what is RTOS actually. To see more clearly what’s kernel and it’s implementation. RTOS is a great example of simplified OS kernel. To be able to program for a majority of uC.
  • 9.
    FREERTOS OVERVIEW Features: High qualitycode standards Open source Flexible and configurable Portable, more than 35 architectures supported Modesty memory use and CPU overhead Easy to use API
  • 10.
    EXAMPLE APPLICATION main -entry point, as always with C. xTaskCreate - create a task, it’s ready to run. vTaskStartScheduler - starts the scheduler, before no tasks were running, now RTOS takes control of the program flow. #include ‘‘FreeRTOS.h‘‘ #include ‘‘task.h‘‘ static void function( void *pvParameters ) { for ( ;; ) ; // do something } Int main( void ) { // init part xTaskCreate(function, «name», stack_sz, (void*) data, task_priority, &taskHandle); vTaskStartScheduler(); vTaskDelete(taskHandle); return 0; } Code 1. Example application
  • 11.
    IMPORTANT FILES FORBUILD As a minimum, the following source files must be included in your project: 1. FreeRTOS/Source/tasks.c 2. FreeRTOS/Source/queue.c 3. FreeRTOS/Source/list.c 4. FreeRTOS/Source/portable/[compiler]/[architecture]/{*.c,*.S} 5. FreeRTOS/Source/portable/MemMang/heap_x.c where ‘x’ is 1, 2, 3, 4 or 5. As well as the following directories should be in compiler’s include path: 1. FreeRTOS/Source/include 2. FreeRTOS/Source/portable/[compiler]/[architecture] 3. FreeRTOSConfig.h file with FreeRTOS configuration.
  • 12.
    CONCURRENCY Concurrent programming isthe major point of bringing RTOS into the project. A unit of computation is a task. IPC is provided by concurrency primitives: Semaphores, Mutexes, Queues, Direct-to-Task notifications, Event groups, etc. Concurrent = Two Queens One Coffee Machines Parallel = Two Queens Two Coffee Machines Figure 1. Concurrency vs Parallelism
  • 13.
    CONCURRENCY IS FORPERFORMANCE Concurrent execution can improve performance in three fundamental ways: Reduce latency. Make a unit of work execute faster. Hide latency. Allow the system to continue doing work during a longatency operation. Increase throughput. Make the system able to perform more work. Another advantage should not be foreseen: Improve program structure. Some problems and problem domains are well-suited to representation as concurrent tasks or processes
  • 14.
    TASKS Every task hasit’s context. Basically it’s value of the registers. Task always is in one of four stages. Task has a priority. Task with bigger priority preempts running task with lower. Suspended vTaskSuspend() called Blocking API function called vTaskSuspend() called vTaskSuspend() called vTaskSuspend() called Event ReadyR unning Blocked Diagram 4. Task states
  • 15.
    CONCURRENCY PRIMITIVES Semaphore. Any visualsignaling system with flags, lights, or mechanically moving arm. In computer science, a semaphore is a variable or abstract data type used to control access to a common resource or to synchronize tasks.
  • 16.
    SEMAPHORE, MORE DETAILEDLOOK A type, can be either binary two possible values [0, 1] or counting [0, 1, 2,...]. Defined two operations: wait (P) and signal (V). FreeRTOS API: SemaphoreHandle_t - type xSemaphoreCreateBinary - create xSemaphoreTake - wait (P) xSemaphoreGive - signal (V) ...
  • 17.
    APPLICATION Index increment. Isit safe to increment a variable, integer concurrently? Let’s check static void simpleTask( void *pvParameters ) { uint uTaskId = (uint) pvParameters; uint i = 0; for( ;i < 10000000UL; ++i ) { uIndex++; } printf(‘‘%u %un‘‘, uTaskId, uIndex); // acording to documentation task should not return, suspend task til exit vTaskSuspend ( NULL ); } OUTPUT: 0 13417239 2 14765457 3 14786973 1 14265594 4 14333205 Code 2. Task function example Screen 1. Program output
  • 18.
    TIME TO USESEMAPHORE! In order to make increment task safe, it is moved into critical section surrounded by semaphore. Code 3a. Semaphore initialization. static SemaphoreHandle_t xSemaphore; int main ( void ) { ... xSemaphore = xSemaphoreCreateBinary(); // is it enough memory to create semaphore configASSERT(xSemaphore); // init semaphore with a value of 1 xSemaphoreGive(xSemaphore); ... } Code 3b. Increment gourded by sema. static void simpleTask( void *pvParameters ) { ... uint i = 0; for( ;i < 10000000UL; ++i ) { xSemaphoreTake(xSemaphore, portMAX_DELAY); uIndex++; xSemaphoreGive(xSemaphore); } ... }
  • 19.
    SO, ARE THEREATOMIC INCREMENT AT ALL? All atomic operations that access memory are processor dependent, for example ARM instructions . GCC has extension for atomic memory access. Moreover, concurrency primitives are based on atomic operations. void wait(Semaphore_t sem) { // __sync_lock_test_and_set return previous value while(1 != __sync_lock_test_and_set(&sem, 0)) { // add task into queue of waiting process // polling till resource (1) becomes available } // if 1 returned than resource was acquired by current task } static void simpleTask( void *pvParameters ) { ... uint i = 0; for( ;i < 10000000UL; ++i ) { __sync_fetch_and_add(&uIndex, 1); } ... } Code 4a. Semaphore wait function impl. Code 4b. Atomic addition.
  • 20.
    PROBLEMS IN CONCURRENCY Let’sconsider more generic problems in concurrency: Deadlock Resource starvation Data corruption/races Livelock Priority inversion
  • 21.
    REAL WORLD EXAMPLES1: Data races in database: Dirty data. First transaction read data, second one updates the same data. First transaction return stale or outdated data. Incorrect update. A person updates data, B person reads old data, work with it and try to update. A person’s transaction will be lost. Incorrect summary. As one process collect summary of some array of data, others can update it. In consequence of summary will include some old data and some updated.
  • 22.
    REAL WORLD EXAMPLES2: Concurrent data structures: As data structures become used in concurrent applications issues of data integrity arise. Incorporating lock protection in the turn bring performance issues, access to data becomes a bottleneck. Diagram 5. Simultaneous removal of i and i+1 list elements. Results in not removed i+1 element
  • 23.
    REAL WORLD EXAMPLES3: Peripherals: First task updates display. Second taks preempts it. Second taks updates display and yields First task wakes, finishes display update Thread 1 prints Thread 2 Thread 3 prints prints Thread Thre Thread 2 prints ad1 prints 4 prints Screen 2. Concurrent print to consoleDiagram 3. Concurrent access to display
  • 24.
    CLASSICAL CONCURRENCY PROBLEM Fivephilosophers sit at a round table with bowls of rice. Chopsticks are placed between each pair of adjacent philosophers. Each philosopher must alternately think and eat. However, a philosopher can only eat rice when they have both left and right chopsticks. After an individual philosopher finishes eating, they need to put down both chopsticks so that the chopsticks become available to others. A philosopher can take the chopstick on their right or the one on their left as they become available, but cannot start eating before getting both chopsticks.
  • 25.
    POSSIBLE SOLUTION: think untilthe left chopstick is available; when it is, pick it up; think until the right chopstick is available; when it is, pick it up; when both chopsticks are held, eat for a fixed amount of time; then, put the right chopstick down; then, put the left chopstick down;
  • 26.
    IMPLEMENTATION Every philosopher implementedas a FSM with 3 states. Functions FSMThinking, FSMEating and FSMHungry. struct Philosopher and struct Chopstick represent main character of our story. Function simpleTask is task function. Every philosopher runs its own instance. More in source... NO YES Thinking Eating Hungry put chopsticks take chopsticks has 2 chopsticks chopsticks available Diagram 6. Philosopher FSM
  • 27.
    DRAWBACKS AND POSSIBLEPROBLEMS: Deadlock. All philosopher took left chopstick and no one can take right. Starvation. No guarantees that that everyone will get his portion of rice. Data corruption. Two philosophers can break a chopstick trying to get it at the very same time. Diagram 7. Deadlock
  • 28.
    MUTUAL EXCLUSION: To preventa deadlock philosopher before acquiring one chopstick should make sure he will be eventually able to acquire another one. To prevent starvation it’s needed to make chopstick distribution between philosophers as even as possible. To prevent data chopstick corruption, make sure that philosophers take turns to get a chopstick. A generic term, basic idea of the solution.
  • 29.
    ANOTHER CHALLENGE FORTHE SEMAPHORE? Opening docs on semaphore one can see a tip: “Use task notification as more efficient mean of synchronisation”. So let’s see: Each RTOS task has a 32-bit notification value... Efficient usage of memory and CPU. No need to create another variable, variable is already in task struct. Can be used as binary or counting semaphore, event groups or queue. Only one task can receive notifications. Only one receiving task can wait sleeping for a notification. Advantages: Limitations:
  • 30.
    DIRECT TO TASKNOTIFICATION Can be enabled in config (by default): configUSE_TASK_NOTIFICATIONS 1 Represented as two values in task struct: ulNotifiedValue and ucNotifyState Notified value can be set, overwritten, incremented or used as bit mask to set value of a single bit. Direct notification API: xTaskNotifyWait() waits, with an optional timeout, for the calling task to receive a notification. xTaskNotify() sends an event directly to and potentially unblock an RTOS task. ...
  • 31.
    TASK SAFE SOLUTION: waitfor a notification that left chopstick is available, pick it up; wait for a notification that right chopstick is available, pick it up; when both chopsticks are held, eat for a fixed amount of time; then, put the right chopstick down; sent a right philosopher a notification that his left chopstick became available; then, put the left chopstick down; send a left philosopher a notification that his right chopstick became available;
  • 32.
    IMPLEMENTATION In order toresolve concurrency we use so called event-driven computing model. Philosopher how driven by notifications from other philosophers. Notification value is used as a bit mask, first LSB signals that left chopstick is free, second - right. Before taking chopstick task wait for notification using xTaskNotifyWait function, on putting chopstick task calls xTaskNotify for left and left philosopher. NO NO YES YES Thinking Eating Hungry put chopsticks notification take chopsticks has 2 chopsticks chopsticks available Send notification to left and right neighbor Diagram 7. Philosopher notification driven FSM
  • 33.
    CONCLUSION Concurrency can improveefficiency and architecture as well as bring a lot of hard-to-track problems and bugs. It should be kept in mind throughout all development phases. All in all, it’s another interesting and challenging journey in programming.
  • 34.
    THANK YOU FORYOUR ATTENTION Q&A
  • 35.
    REFERENCES: Official FreeRTOS website GNUcompilers’ manual: Atomic Builtins Intro to Real-Time Linux for Embedded Developers AC6 System Workbench for STM32 github repo of FreeRTOS PC simulator Real-world Concurrency What really happened to the software on the Mars Pathfinder spacecraft? From bare-metal to RTOS Flavors of concurrency by Oleg Shelajev Practical Guide to Bare Metal C++
  • 36.
    THANK YOU VERYMUCH FOR YOUR ATTENTION. www.sirinsoftware.com hr@sirinsoftware.com www.facebook.com/sirinsoftware twitter.com/Sirin_Software www.linkedin.com/company/sirinsoftware