Semaphores and Shared Data
Semaphores and Shared Data
Semaphores and Shared Data
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
RTOS can cause a new class of shared-data problems by: Switching the microprocessor from task to task Changing the ow of execution (similar to interrupts) Something called semaphores helps preventing shared
data problems.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
RTOS semaphores
Most RTOS normally use the paired terms take and release. Tasks can call two RTOS functions, TakeSemaphore and
ReleaseSemaphore.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp; void main (void) { //Initialize (but do not start) the RTOS OSInit (); // Tell the RTOS about our tasks OSTaskCreate ( vReadTemperatureTask, NULLP, (void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ ); OSTaskCreate ( vControlTask, NULLP, (void *)&ControlStk[STK_SIZE], TASK_PRIORITY_CONTROL); //Start the RTOS. //This function never returns. OSStart ();
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm; OSSemPost (p_semTemp); !! Do other useful work
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp; void main (void) { //Initialize (but do not start) the RTOS OSInit (); // Tell the RTOS about our tasks OSTaskCreate ( vReadTemperatureTask, NULLP, (void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ ); OSTaskCreate ( vControlTask, NULLP, (void *)&ControlStk[STK_SIZE], TASK_PRIORITY_CONTROL); //Start the RTOS. //This function never returns. OSStart ();
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm;
OS_EVENT structure (dened in the RTOS) stores the data that represents the semaphore.
OSSemPost (p_semTemp); !! Do other useful work
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp;
void main (void) { //Initialize (but do not start) the RTOS OSInit ();
OSSemPost and OSSemPend functions // Tell the and RTOS lower about our tasks raise the OSTaskCreate ( vReadTemperatureTask, semaphore. NULLP, WAIT_FOREVER OSTaskCreate ( parameter to the vControlTask, NULLP, (void *)&ControlStk[STK_SIZE], OSSemPend function TASK_PRIORITY_CONTROL); indicates that the task //Start the RTOS. //This function never returns. making the call is willing to OSStart (); wait forever for the semaphore.
(void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ );
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm; OSSemPost (p_semTemp); !! Do other useful work
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp; void main (void) { //Initialize (but do not start) the RTOS OSInit (); // OSTaskCreate ( vReadTemperatureTask, NULLP, (void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ );
The calls to OSSemPend and OSSemPost in this code x the shared-data Tell the problems. RTOS about our tasks
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm; OSSemPost (p_semTemp); !! Do other useful work
OSTimeDly function causes current task to OSTaskCreate ( a certain time; block for vControlTask, NULLP, the event that unblocks it (void *)&ControlStk[STK_SIZE], TASK_PRIORITY_CONTROL); is simply the expiration of //Start theamount RTOS. that of time. //This function never returns.
} OSStart ();
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp;
void main (void) { //Initialize (but do not start) the RTOS OSInit (); // Tell the RTOS about our tasks OSTaskCreate ( vReadTemperatureTask, NULLP, (void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ ); OSTaskCreate ( vControlTask, NULLP, (void *)&ControlStk[STK_SIZE], TASK_PRIORITY_CONTROL);
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm; OSSemPost (p_semTemp); !! Do other useful work
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp; void main (void) { //Initialize (but do not start) the RTOS OSInit ();
OSSemlnit must happen before vRead TemperatureTask calls OSSemPend to use the semaphore.
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm; OSSemPost (p_semTemp); !! Do other useful work
How do you know that this really happens? You // Tell the RTOS about our tasks OSTaskCreate (don't. vReadTemperatureTask, NULLP, ... vReadTemperatureTask OSTaskCreate ( calls OSTimeDly at the vControlTask, NULLP, beginning before calling (void *)&ControlStk[STK_SIZE], TASK_PRIORITY_CONTROL); OSSemPend, vControlTask //Start should the RTOS. (but not //This function never returns. OSStart (); necessarily) have enough time to call OSSemlnit.
(void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ );
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
#define TASK_PRIORITY_READ 11 #define TASK_PRIORITY_CONTROL 12 #define STK_SIZE 1024 static unsigned int ReadStk [STK_SIZE]; static unsigned int ControlStk [STK_SIZE]; static int iTemperatures[2]; OS_EVENT *p_semTemp; void { //Initialize (but do not start) the RTOS OSInit (); // Tell the RTOS about our tasks OSTaskCreate ( vReadTemperatureTask, NULLP, (void *)&ReadStk[STK_SIZE], TASK_PRIORITY_READ ); OSTaskCreate ( vControlTask, NULLP, (void *)&ControlStk[STK_SIZE], TASK_PRIORITY_CONTROL);
How do you know that there isn't some higherpriority task that takes up all of the delay time in vReadTemperatureTask? main (void)
void vControlTask (void) { p_semTemp = OSSemlnit (1); while (TRUE) { OSSemPend (p_semTemp, WAIT_FOREVER); if ( iTemperatures[0] != iTernperatures[1]) !!Set off howling alarm; OSSemPost (p_semTemp); !! Do other useful work
Best solution is to put OSSemlnit in some startup code that's guaranteed //Start the RTOS. //This never returns. to function run rst... such as the OSStart (); main function.
void vReadTemperatureTask (void) { while (TRUE) { //Delay of 0.25 seconds OSTimeDly (5); OSSemPend (p_semTemp, WAIT_FOREVER); !! read in iTemperatures[0]; !! read in iTemperatures[1]; OSSemPost (p_semTemp); } }
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
Yes!
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
Multiple semaphores
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
Multiple semaphores
task takes semaphore A, another task can take semaphore B without blocking. Similarly, if one task is waiting for semaphore C, that task will still be blocked even if some other task releases semaphore D.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
In a system with only one semaphore, if the lowest-priority By having one semaphore protect the temperatures and a
task takes the semaphore to change data in a shared array of temperatures, the highest-priority task might block waiting for that semaphore. different semaphore protect the error count, you can build your system so the highest-priority task can modify the error count even if the lowest-priority task has taken the semaphore protecting the temperatures. Different semaphores can correspond to different shared resources.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
How does the RTOS know which semaphore protects which data?
It doesn't. If you are using multiple semaphores, it is up to
you to remember which semaphore corresponds to which data. corresponding semaphore. protects.
A task that is modifying the error count must take the You must decide what shared data each of your semaphores
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
communicate from one task to another (or from an interrupt routine to a task).
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
Semaphore problems
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
Semaphores only work if you use them perfectly. Forgetting to take the semaphore: Semaphores only work if
every task that accesses the shared data, for read or for write, uses the semaphore.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
the semaphore, then every other task that ever uses the semaphore will sooner or later be blocked as they wait to take that semaphore.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
semaphores, then taking the wrong one is as bad as forgetting to take one.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
A nasty semaphore problem can arise if the RTOS switches from a lowpriority task (Task C) to a medium-priority task (Task B) after Task C has taken a semaphore.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
A high-priority task (Task A) that wants the semaphore then has to wait until Task B gives up the microprocessor: Task C can't release the semaphore until it gets the microprocessor back.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
This is problematic! TaskA, which is a high priority task should have been executed immediately!
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
In this code
Taskl and Task2 operate on variables a and b after getting permission to use them by getting semaphores SemaphoreA and SemaphoreB.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
but before it can call OSSemPend to get SemaphoreB, the RTOS stops it and runs vTask2.
OSSemPend to get SemaphoreA, it blocks, because another task (vTaskl) already has that semaphore.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering
Deadly-embrace problems
would be easy to nd and x if they always looked as clean as this code. However, deadly embrace is just as deadly if vTaskl takes the rst semaphore and then calls a subroutine that later takes a second one while vTask2 takes the second semaphore and then calls a subroutine that takes the rst. In this case the problem will not be so obvious.
CPE 355 - Real Time Embedded Kernels - Spring 12 Nuno Alves (nalves@wne.edu), College of Engineering