VxWorks Reference Manual : Libraries
semBLib - binary semaphore library
semBCreate( ) - create and initialize a binary semaphore
This library provides the interface to VxWorks binary semaphores. Binary semaphores are the most versatile, efficient, and conceptually simple type of semaphore. They can be used to: (1) control mutually exclusive access to shared devices or data structures, or (2) synchronize multiple tasks, or task-level and interrupt-level processes. Binary semaphores form the foundation of numerous VxWorks facilities.
A binary semaphore can be viewed as a cell in memory whose contents are in one of two states, full or empty. When a task takes a binary semaphore, using semTake( ), subsequent action depends on the state of the semaphore:
- (1)
- If the semaphore is full, the semaphore is made empty, and the calling task continues executing.
- (2)
- If the semaphore is empty, the task will be blocked, pending the availability of the semaphore. If a timeout is specified and the timeout expires, the pended task will be removed from the queue of pended tasks and enter the ready state with an ERROR status. A pended task is ineligible for CPU allocation. Any number of tasks may be pended simultaneously on the same binary semaphore.
When a task gives a binary semaphore, using semGive( ), the next available task in the pend queue is unblocked. If no task is pending on this semaphore, the semaphore becomes full. Note that if a semaphore is given, and a task is unblocked that is of higher priority than the task that called semGive( ), the unblocked task will preempt the calling task.
To use a binary semaphore as a means of mutual exclusion, first create it with an initial state of full. For example:
SEM_ID semMutex; /* create a binary semaphore that is initially full */ semMutex = semBCreate (SEM_Q_PRIORITY, SEM_FULL);Then guard a critical section or resource by taking the semaphore with semTake( ), and exit the section or release the resource by giving the semaphore with semGive( ). For example:semTake (semMutex, WAIT_FOREVER); ... /* critical region, accessible only by one task at a time */ semGive (semMutex);While there is no restriction on the same semaphore being given, taken, or flushed by multiple tasks, it is important to ensure the proper functionality of the mutual-exclusion construct. While there is no danger in any number of processes taking a semaphore, the giving of a semaphore should be more carefully controlled. If a semaphore is given by a task that did not take it, mutual exclusion could be lost.
To use a binary semaphore as a means of synchronization, create it with an initial state of empty. A task blocks by taking a semaphore at a synchronization point, and it remains blocked until the semaphore is given by another task or interrupt service routine.
Synchronization with interrupt service routines is a particularly common need. Binary semaphores can be given, but not taken, from interrupt level. Thus, a task can block at a synchronization point with semTake( ), and an interrupt service routine can unblock that task with semGive( ).
In the following example, when init( ) is called, the binary semaphore is created, an interrupt service routine is attached to an event, and a task is spawned to process the event. Task 1 will run until it calls semTake( ), at which point it will block until an event causes the interrupt service routine to call semGive( ). When the interrupt service routine completes, task 1 can execute to process the event.
SEM_ID semSync; /* ID of sync semaphore */ init () { intConnect (..., eventInterruptSvcRout, ...); semSync = semBCreate (SEM_Q_FIFO, SEM_EMPTY); taskSpawn (..., task1); } task1 () { ... semTake (semSync, WAIT_FOREVER); /* wait for event */ ... /* process event */ } eventInterruptSvcRout () { ... semGive (semSync); /* let task 1 process event */ ... }A semFlush( ) on a binary semaphore will atomically unblock all pended tasks in the semaphore queue, i.e., all tasks will be unblocked at once, before any actually execute.
There is no mechanism to give back or reclaim semaphores automatically when tasks are suspended or deleted. Such a mechanism, though desirable, is not currently feasible. Without explicit knowledge of the state of the guarded resource or region, reckless automatic reclamation of a semaphore could leave the resource in a partial state. Thus, if a task ceases execution unexpectedly, as with a bus error, currently owned semaphores will not be given back, effectively leaving a resource permanently unavailable. The mutual-exclusion semaphores provided by semMLib offer protection from unexpected task deletion.
semLib.h
semBLib, semLib, semCLib, semMLib, VxWorks Programmer's Guide: Basic OS
semBCreate( ) - create and initialize a binary semaphore
SEM_ID semBCreate ( int options, /* semaphore options */ SEM_B_STATE initialState /* initial semaphore state */ )
This routine allocates and initializes a binary semaphore. The semaphore is initialized to the initialState of either SEM_FULL (1) or SEM_EMPTY (0).
The options parameter specifies the queuing style for blocked tasks. Tasks can be queued on a priority basis or a first-in-first-out basis. These options are SEM_Q_PRIORITY (0x1) and SEM_Q_FIFO (0x0), respectively.
The semaphore ID, or NULL if memory cannot be allocated.