Question

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.

Était-ce utile?

La solution

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.

Autres conseils

What output are you expecting when you say it doesn't work? You are starting tHiPriorityTask and this is immediately reaching the semaphore, forcing tMePriorityTask to wait, even if it has a higher priority. Basically, having a higher priority it doesn't mean it can take over a locked semaphore, it just means that it's more likely to run when itself and its competitors are in the "ready" state. The only scenario where tMePriorityTask would run first, is when tHiPriorityTask is preempted before tryig to reach the semaphore, which I guess it's less likely because you started it first and it may go ahead and run the first instructions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top