Overview of Semaphores in VxWorks 7
In real-time operating systems (RTOS), semaphores are an important synchronization mechanism used to manage resource access and task synchronization in a multitasking environment.VxWorks 7 provides various types of semaphores to meet different application scenario requirements, mainly including:
- • Mutex Semaphores: Ensure mutual access to shared resources.
- • Binary Semaphores: Similar to mutex semaphores but simpler, commonly used for task synchronization.
- • Counting Semaphores: Can count and represent the availability of multiple resources.
Basic Operations of Semaphores
- 1. Create Semaphore:
- • semMCreate creates a mutex semaphore.
- • semBCreate creates a binary semaphore.
- • semCCreate creates a counting semaphore.
- 2. Acquire Semaphore:
- • semTake acquires the semaphore in blocking mode.
- • semTakeWithTimeout acquires the semaphore with a timeout feature.
- 3. Release Semaphore:
- • semGive releases the semaphore.
- 4. Delete Semaphore:
- • semDelete deletes the semaphore.
Code Example
Creating and Using a Mutex Semaphore
#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
/* Mutex semaphore handle */
SEM_ID mutexSem;
void task1(void)
{
while (1)
{
/* Acquire mutex semaphore */
if (semTake(mutexSem, WAIT_FOREVER) == OK)
{
printf("Task1: Got the mutex\n");
/* Critical section code */
/* For example, modify shared resources */
/* Release mutex semaphore */
semGive(mutexSem);
taskDelay(100); // Delay to simulate task execution
}
}
}
void task2(void)
{
while (1)
{
/* Acquire mutex semaphore */
if (semTake(mutexSem, WAIT_FOREVER) == OK)
{
printf("Task2: Got the mutex\n");
/* Critical section code */
/* For example, access shared resources */
/* Release mutex semaphore */
semGive(mutexSem);
taskDelay(100); // Delay to simulate task execution
}
}
}
int main()
{
/* Create mutex semaphore */
mutexSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
if (mutexSem == NULL)
{
printf("Failed to create mutex semaphore\n");
return ERROR;
}
/* Create tasks */
if (taskSpawn("t1", 100, 0, 4000, (FUNCPTR)task1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
{
printf("Failed to spawn task1\n");
return ERROR;
}
if (taskSpawn("t2", 100, 0, 4000, (FUNCPTR)task2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR)
{
printf("Failed to spawn task2\n");
return ERROR;
}
return 0;
}
Error Handling
For rigor, the above code needs to include relevant error handling as follows:
#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
#include <errnoLib.h>
/* Mutex semaphore handle */
SEM_ID mutexSem;
void task1(void)
{
STATUS status;
while (1)
{
/* Acquire mutex semaphore */
status = semTake(mutexSem, WAIT_FOREVER);
if (status != OK)
{
printf("Task1: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
}
else
{
printf("Task1: Got the mutex\n");
/* Critical section code */
/* For example, modify shared resources */
/* Release mutex semaphore */
status = semGive(mutexSem);
if (status != OK)
{
printf("Task1: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
}
taskDelay(100); // Delay to simulate task execution
}
}
}
void task2(void)
{
STATUS status;
while (1)
{
/* Acquire mutex semaphore */
status = semTake(mutexSem, WAIT_FOREVER);
if (status != OK)
{
printf("Task2: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
}
else
{
printf("Task2: Got the mutex\n");
/* Critical section code */
/* For example, access shared resources */
/* Release mutex semaphore */
status = semGive(mutexSem);
if (status != OK)
{
printf("Task2: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
}
taskDelay(100); // Delay to simulate task execution
}
}
}
int main()
{
STATUS status;
/* Create mutex semaphore */
mutexSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
if (mutexSem == NULL)
{
printf("Failed to create mutex semaphore. Error: %s\n", strerror(errnoGet()));
return ERROR;
}
/* Create tasks */
status = taskSpawn("t1", 100, 0, 4000, (FUNCPTR)task1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (status == ERROR)
{
printf("Failed to spawn task1. Error: %s\n", strerror(errnoGet()));
return ERROR;
}
status = taskSpawn("t2", 100, 0, 4000, (FUNCPTR)task2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (status == ERROR)
{
printf("Failed to spawn task2. Error: %s\n", strerror(errnoGet()));
return ERROR;
}
return 0;
}
Error handling explanation:
- • The return values of the semTake and semGive functions are checked; if the return value is not OK, it indicates that the operation failed, and an error message will be printed.
- • The errnoGet() function is used to obtain the error code, and strerror() is used to convert the error code into a readable error message.
- • The return values for semaphore creation and task generation are also checked to ensure successful operations, providing corresponding error messages if unsuccessful.
- • This approach can help you more easily diagnose and fix issues in your program, especially regarding semaphore operations or task management.
Timeout Handling
#include <vxWorks.h>
#include <semLib.h>
#include <taskLib.h>
#include <stdio.h>
#include <errnoLib.h>
/* Mutex semaphore handle */
SEM_ID mutexSem;
/* Timeout definition in ticks */
#define SEM_TIMEOUT 100
void task1(void)
{
STATUS status;
while (1)
{
/* Acquire mutex semaphore with timeout handling */
status = semTake(mutexSem, SEM_TIMEOUT);
if (status != OK)
{
if (status == ERROR)
{
printf("Task1: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
}
else if (status == S_objLib_OBJ_TIMEOUT)
{
printf("Task1: Timed out waiting for semaphore.\n");
}
}
else
{
printf("Task1: Got the mutex\n");
/* Critical section code */
/* For example, modify shared resources */
/* Release mutex semaphore */
status = semGive(mutexSem);
if (status != OK)
{
printf("Task1: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
}
taskDelay(100); // Delay to simulate task execution
}
}
}
void task2(void)
{
STATUS status;
while (1)
{
/* Acquire mutex semaphore with timeout handling */
status = semTake(mutexSem, SEM_TIMEOUT);
if (status != OK)
{
if (status == ERROR)
{
printf("Task2: Failed to take semaphore. Error: %s\n", strerror(errnoGet()));
}
else if (status == S_objLib_OBJ_TIMEOUT)
{
printf("Task2: Timed out waiting for semaphore.\n");
}
}
else
{
printf("Task2: Got the mutex\n");
/* Critical section code */
/* For example, access shared resources */
/* Release mutex semaphore */
status = semGive(mutexSem);
if (status != OK)
{
printf("Task2: Failed to give semaphore. Error: %s\n", strerror(errnoGet()));
}
taskDelay(100); // Delay to simulate task execution
}
}
}
int main()
{
STATUS status;
/* Create mutex semaphore */
mutexSem = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);
if (mutexSem == NULL)
{
printf("Failed to create mutex semaphore. Error: %s\n", strerror(errnoGet()));
return ERROR;
}
/* Create tasks */
status = taskSpawn("t1", 100, 0, 4000, (FUNCPTR)task1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (status == ERROR)
{
printf("Failed to spawn task1. Error: %s\n", strerror(errnoGet()));
return ERROR;
}
status = taskSpawn("t2", 100, 0, 4000, (FUNCPTR)task2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (status == ERROR)
{
printf("Failed to spawn task2. Error: %s\n", strerror(errnoGet()));
return ERROR;
}
return 0;
}
Timeout handling explanation:
- • When calling semTake, the second parameter is no longer WAIT_FOREVER, but uses SEM_TIMEOUT to set the timeout period.
- • If the semaphore is not acquired within the specified time, semTake will return S_objLib_OBJ_TIMEOUT, at which point the task can be notified of the timeout.
- • This method can prevent tasks from being indefinitely blocked while waiting for a semaphore, which is particularly useful in systems requiring real-time responses.
Considerations
- • Semaphores must be created before use and deleted when no longer needed to free resources.
- • Holding a semaphore for an extended period may lead to priority inversion issues; VxWorks provides priority inheritance to address this problem.
- • When using semaphores, consider the task’s priority and real-time requirements to avoid deadlocks and other issues.
This example demonstrates how to use mutex semaphores in VxWorks 7 to coordinate access to shared resources between two tasks. In practical applications, you may need to choose different types of semaphores based on specific requirements and consider the balance between performance and resource utilization.
Click “Read the original text” to access more free resources on VxWorks.