I'm fairly new to RTOS programming and I'm having some problems with priority when using Mutexes.
I have the following priorities established.
#define T_HI_PRIORITY 10
#define T_ME_PRIORITY 50
and I want this code to run the task "tMePriorityTask" with the highest priority and "tHiPriorityTask" with medium priority. "tLoPriorityTask" is commented and, therefore, should not run now.
#include <stdio.h>
#include "main.h"
#include "vxWorks.h"
#include "semLib.h"
#include "taskLib.h"
SEM_ID semMutex; // named semaphore object
char alphabet[27]; // memory resource to have exclusive access
void tHiPriorityTask (void)
{
int i;
// enter critical region - any other tasks wanting access to alphabet[] should
// wait for available semaphore
semTake (semMutex, WAIT_FOREVER);
// write alphabet to global array
for (i= 0; i < 26; i++)
alphabet[i] = 'A' + i;
alphabet[i] = '\0';
printf("High priority.\n-Counting alphabet...\n");
// leave critical region
semGive (semMutex);
}
void tMePriorityTask (void)
{
// enter critical region
semTake (semMutex, WAIT_FOREVER);
//medium priority task enters
printf("Medium priority.\n-Just entering...\n");
// leave critical region
semGive (semMutex);
}
/*void tLoPriorityTask (void)
{
// enter critical region
semTake (semMutex, WAIT_FOREVER);
// array members guaranteed stable while being read by this task
printf("Low priority\n");
printf ("-alphabet= %s ", alphabet);
// leave critical region
semGive (semMutex);
}*/
void main (void)
{
//create binary semaphore which is initially full (available)
semMutex = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
// spawn high priority task
taskSpawn ("hi_priority_task", T_ME_PRIORITY, VX_FP_TASK, 10000, (FUNCPTR) tHiPriorityTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
// spawn medium priority task
taskSpawn ("me_priority_task", T_HI_PRIORITY, VX_FP_TASK, 10000, (FUNCPTR) tMePriorityTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
// spawn low priority task
//taskSpawn ("lo_priority_task", T_LO_PRIORITY, VX_FP_TASK, 10000, (FUNCPTR) tLoPriorityTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
I've tried to change the priorities when spawning the tasks but that doesn't seem to work, at least it doesn't change anything on screen. I'm using VxWorks RTOS.
Thank you.
If you want to guarantee that two threads run in a specific order then you must use proper synchronization of the threads. Just setting the priority and hoping that it works is very poor design, you might get it to work, but it will eventually break (for example if you make a blocking call then there is nothing preventing any other thread from running.)
Here is the easiest way to modify your code to guarantee that your tMePriorityTask thread runs to completion before tHiPriorityTask is allowed to run regardless of priority or anything else you do in your threads.
#include <stdio.h>
#include "main.h"
#include "vxWorks.h"
#include "semLib.h"
#include "taskLib.h"
SEM_ID semMutex; // named semaphore object
char alphabet[27]; // memory resource to have exclusive access
void tHiPriorityTask (void)
{
int i;
// enter critical region - any other tasks wanting access to alphabet[] should
// wait for available semaphore
semTake (semMutex, WAIT_FOREVER);
// write alphabet to global array
for (i= 0; i < 26; i++)
alphabet[i] = 'A' + i;
alphabet[i] = '\0';
printf("High priority.\n-Counting alphabet...\n");
// leave critical region
semGive (semMutex);
}
void tMePriorityTask (void)
{
// enter critical region
//semTake (semMutex, WAIT_FOREVER);
//medium priority task enters
printf("Medium priority.\n-Just entering...\n");
// leave critical region
semGive (semMutex);
}
/*void tLoPriorityTask (void)
{
// enter critical region
semTake (semMutex, WAIT_FOREVER);
// array members guaranteed stable while being read by this task
printf("Low priority\n");
printf ("-alphabet= %s ", alphabet);
// leave critical region
semGive (semMutex);
}*/
void main (void)
{
//create binary semaphore which is initially full (available)
semMutex = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
// spawn high priority task
taskSpawn ("hi_priority_task", T_ME_PRIORITY, VX_FP_TASK, 10000, (FUNCPTR) tHiPriorityTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
// spawn medium priority task
taskSpawn ("me_priority_task", T_HI_PRIORITY, VX_FP_TASK, 10000, (FUNCPTR) tMePriorityTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
// spawn low priority task
//taskSpawn ("lo_priority_task", T_LO_PRIORITY, VX_FP_TASK, 10000, (FUNCPTR) tLoPriorityTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
All I did, was create the semaphore with SEM_EMPTY, and then remove the semTake from the tMePriorityTask.
This way the tHiPriorityTask can run at any priority, and it will block on the semTake until tMePriorityTask issues the semGive. Furthermore the tMePriorityTask thread can do other blocking calls (like I/O calls for example) and the tHiPriorityTask thread will still not be able to run until the semGive.
Checkout the vxworks API reference for semBCreate and read the section entitled SYNCHRONIZATION.