VxWorks Reference Manual : Wind Foundation Classes

VXWSem

NAME

VXWSem - semaphore classes

METHODS

VXWSem::VXWSem( ) - build semaphore object from semaphore ID
VXWSem::~VXWSem( ) - delete a semaphore
VXWSem::give( ) - give a semaphore
VXWSem::take( ) - take a semaphore
VXWSem::flush( ) - unblock every task pended on a semaphore
VXWSem::id( ) - reveal underlying semaphore ID
VXWSem::info( ) - get a list of task IDs that are blocked on a semaphore
VXWSem::show( ) - show information about a semaphore
VXWCSem::VXWCSem( ) - create and initialize a counting semaphore
VXWBSem::VXWBSem( ) - create and initialize a binary semaphore
VXWMSem::VXWMSem( ) - create and initialize a mutual-exclusion semaphore
VXWMSem::giveForce( ) - give a mutual-exclusion semaphore without restrictions

DESCRIPTION

Semaphores are the basis for synchronization and mutual exclusion in VxWorks. They are powerful in their simplicity and form the foundation for numerous VxWorks facilities.

Different semaphore types serve different needs, and while the behavior of the types differs, their basic interface is the same. The VXWSem class provides semaphore routines common to all VxWorks semaphore types. For all types, the two basic operations are VXWSem::take( ) and VXWSem::give( ), the acquisition or relinquishing of a semaphore.

Semaphore creation and initialization is handled by the following classes, which inherit the basic operations from VXWSem:

    VXWBSem  - binary semaphores
    VXWCSem  - counting semaphores
    VXWMSem  - mutual exclusion semaphores

Two additional semaphore classes provide semaphores that operate over shared memory (with the optional product VxMP). These classes also inherit from VXWSmNameLib; they are described in vxwSmLib. The following are the class names for these shared-memory semaphores:

    VXWSmBSem  - shared-memory binary semaphores
    VXWSmCSem  - shared-memory counting semaphores

Binary semaphores offer the greatest speed and the broadest applicability.

The VXWSem class provides all other semaphore operations, including routines for semaphore control, deletion, and information.

SEMAPHORE CONTROL

The VXWSem::take( ) call acquires a specified semaphore, blocking the calling task or making the semaphore unavailable. All semaphore types support a timeout on the VXWSem::take( ) operation. The timeout is specified as the number of ticks to remain blocked on the semaphore. Timeouts of WAIT_FOREVER and NO_WAIT codify common timeouts. If a VXWSem::take( ) times out, it returns ERROR. Refer to the library of the specific semaphore type for the exact behavior of this operation.

The VXWSem::give( ) call relinquishes a specified semaphore, unblocking a pended task or making the semaphore available. Refer to the library of the specific semaphore type for the exact behavior of this operation.

The VXWSem::flush( ) call may be used to atomically unblock all tasks pended on a semaphore queue; that is, it unblocks all tasks before any are allowed to run. It may be thought of as a broadcast operation in synchronization applications. The state of the semaphore is unchanged by the use of VXWSem::flush( ); it is not analogous to VXWSem::give( ).

SEMAPHORE DELETION

The VXWSem::~VXWSem( ) destructor terminates a semaphore and deallocates any associated memory. The deletion of a semaphore unblocks tasks pended on that semaphore; the routines which were pended return ERROR. Take care when deleting semaphores, particularly those used for mutual exclusion, to avoid deleting a semaphore out from under a task that already has taken (owns) that semaphore. Applications should adopt the protocol of only deleting semaphores that the deleting task has successfully taken.

SEMAPHORE INFORMATION

The VXWSem::info( ) call is a useful debugging aid, reporting all tasks blocked on a specified semaphore. It provides a snapshot of the queue at the time of the call, but because semaphores are dynamic, the information may be out of date by the time it is available. As with the current state of the semaphore, use of the queue of pended tasks should be restricted to debugging uses only.

INCLUDE FILES

vxwSemLib.h

SEE ALSO

VXWSem, VXWTask, vxwSmLib, VxWorks Programmer's Guide: Basic OS


Wind Foundation Classes : Methods

VXWSem::VXWSem( )

NAME

VXWSem::VXWSem( ) - build semaphore object from semaphore ID

SYNOPSIS

VXWSem
    (
    SEM_ID id
    )

DESCRIPTION

Use this constructor to manipulate a semaphore that was not created using C++ interfaces. The argument id is the semaphore identifier returned and used by the C interface to the VxWorks semaphore facility.

RETURNS

N/A

SEE ALSO

VXWSem, semLib


Wind Foundation Classes : Methods

VXWSem::~VXWSem( )

NAME

VXWSem::~VXWSem( ) - delete a semaphore

SYNOPSIS

    virtual ~VXWSem ()

DESCRIPTION

This destructor terminates and deallocates any memory associated with a specified semaphore. Any pended tasks unblock and return ERROR.

WARNING

Take care when deleting semaphores, particularly those used for mutual exclusion, to avoid deleting a semaphore out from under a task that already has taken (owns) that semaphore. Applications should adopt the protocol of only deleting semaphores that the deleting task has successfully taken.

RETURNS

N/A

SEE ALSO

VXWSem, VxWorks Programmer's Guide: Basic OS


Wind Foundation Classes : Methods

VXWSem::give( )

NAME

VXWSem::give( ) - give a semaphore

SYNOPSIS

    STATUS give ()

DESCRIPTION

This routine performs the give operation on a specified semaphore. Depending on the type of semaphore, the state of the semaphore and of the pending tasks may be affected. The behavior of VXWSem::give( ) is discussed fully in the constructor description for the specific semaphore type being used.

RETURNS

OK.

SEE ALSO

VXWSem, VXWCSem::VXWCsem( ), VXWBSem::VXWBsem( ), VXWMSem::VXWMsem( ), VxWorks Programmer's Guide: Basic OS


Wind Foundation Classes : Methods

VXWSem::take( )

NAME

VXWSem::take( ) - take a semaphore

SYNOPSIS

STATUS take
    (
    int timeout
    )

DESCRIPTION

This routine performs the take operation on a specified semaphore. Depending on the type of semaphore, the state of the semaphore and the calling task may be affected. The behavior of VXWSem::take( ) is discussed fully in the constructor description for the specific semaphore type being used.

A timeout in ticks may be specified. If a task times out, VXWSem::take( ) returns ERROR. Timeouts of WAIT_FOREVER and NO_WAIT indicate to wait indefinitely or not to wait at all.

When VXWSem::take( ) returns due to timeout, it sets the errno to S_objLib_OBJ_TIMEOUT (defined in objLib.h).

The VXWSem::take( ) routine must not be called from interrupt service routines.

RETURNS

OK, or ERROR if the task timed out.

SEE ALSO

VXWSem, VXWCSem::VXWCsem( ), VXWBSem::VXWBsem( ), VXWMSem::VXWMsem( ), VxWorks Programmer's Guide: Basic OS


Wind Foundation Classes : Methods

VXWSem::flush( )

NAME

VXWSem::flush( ) - unblock every task pended on a semaphore

SYNOPSIS

    STATUS flush ()

DESCRIPTION

This routine atomically unblocks all tasks pended on a specified semaphore; that is, all tasks are unblocked before any is allowed to run. The state of the underlying semaphore is unchanged. All pended tasks will enter the ready queue before having a chance to execute.

The flush operation is useful as a means of broadcast in synchronization applications. Its use is illegal for mutual-exclusion semaphores created with VXWMSem::VXWMSem( ).

RETURNS

OK, or ERROR if the operation is not supported.

SEE ALSO

VXWSem, VXWCSem::VXWCsem( ), VXWBSem::VXWBsem( ), VXWMSem::VXWMsem( ), VxWorks Programmer's Guide: Basic OS


Wind Foundation Classes : Methods

VXWSem::id( )

NAME

VXWSem::id( ) - reveal underlying semaphore ID

SYNOPSIS

    SEM_ID id ()

DESCRIPTION

This routine returns the semaphore ID corresponding to a semaphore object. The semaphore ID is used by the C interface to VxWorks semaphores.

RETURNS

Semaphore ID.

SEE ALSO

VXWSem, semLib


Wind Foundation Classes : Methods

VXWSem::info( )

NAME

VXWSem::info( ) - get a list of task IDs that are blocked on a semaphore

SYNOPSIS

STATUS info
    (
    int idList[],
    int maxTasks
    ) const

DESCRIPTION

This routine reports the tasks blocked on a specified semaphore. Up to maxTasks task IDs are copied to the array specified by idList. The array is unordered.

WARNING

There is no guarantee that all listed tasks are still valid or that new tasks have not been blocked by the time VXWSem::info( ) returns.

RETURNS

The number of blocked tasks placed in idList.

SEE ALSO

VXWSem


Wind Foundation Classes : Methods

VXWSem::show( )

NAME

VXWSem::show( ) - show information about a semaphore

SYNOPSIS

STATUS show
    (
    int level
    ) const

DESCRIPTION

This routine displays (on standard output) the state and optionally the pended tasks of a semaphore.

A summary of the state of the semaphore is displayed as follows:

    Semaphore Id        : 0x585f2
    Semaphore Type      : BINARY
    Task Queuing        : PRIORITY
    Pended Tasks        : 1
    State               : EMPTY {Count if COUNTING, Owner if MUTEX}
If level is 1, more detailed information is displayed. If tasks are blocked on the queue, they are displayed in the order in which they will unblock, as follows:
       NAME      TID    PRI DELAY
    ---------- -------- --- -----
    tExcTask    3fd678   0    21
    tLogTask    3f8ac0   0   611

RETURNS

OK or ERROR.

SEE ALSO

VXWSem


Wind Foundation Classes : Methods

VXWCSem::VXWCSem( )

NAME

VXWCSem::VXWCSem( ) - create and initialize a counting semaphore

SYNOPSIS

VXWCSem
    (
    int opts,
    int count
    )

DESCRIPTION

This routine allocates and initializes a counting semaphore. The semaphore is initialized to the specified initial count.

The opts parameter specifies the queuing style for blocked tasks. Tasks may be queued on a priority basis or a first-in-first-out basis. These options are SEM_Q_PRIORITY and SEM_Q_FIFO, respectively.

A counting semaphore may be viewed as a cell in memory whose contents keep track of a count. When a task takes a counting semaphore, using VXWSem::take( ), subsequent action depends on the state of the count:

(1)
If the count is non-zero, it is decremented and the calling task continues executing.

(2)
If the count is zero, the task is blocked, pending the availability of the semaphore. If a timeout is specified and the timeout expires, the pended task is removed from the queue of pended tasks and enters 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 counting semaphore.

When a task gives a semaphore, using VXWSem::give( ), the next available task in the pend queue is unblocked. If no task is pending on this semaphore, the semaphore count is incremented. Note that if a semaphore is given, and a task is unblocked that is of higher priority than the task that called VXWSem::give( ), the unblocked task preempts the calling task.

A VXWSem::flush( ) on a counting semaphore atomically unblocks all pended tasks in the semaphore queue. Thus, all tasks are made ready before any task actually executes. The count of the semaphore remains unchanged.

INTERRUPT USAGE

Counting semaphores may be given but not taken from interrupt level.

CAVEATS

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 are not given back, effectively leaving a resource permanently unavailable. The mutual-exclusion semaphores provided by VXWMSem offer protection from unexpected task deletion.

RETURNS

N/A

SEE ALSO

VXWSem


Wind Foundation Classes : Methods

VXWBSem::VXWBSem( )

NAME

VXWBSem::VXWBSem( ) - create and initialize a binary semaphore

SYNOPSIS

VXWBSem
    (
    int         opts,
    SEM_B_STATE iState
    )

DESCRIPTION

This routine allocates and initializes a binary semaphore. The semaphore is initialized to the state iState: either SEM_FULL (1) or SEM_EMPTY (0).

The opts 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 and SEM_Q_FIFO, respectively.

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 VXWSem::take( ), 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 is blocked, pending the availability of the semaphore. If a timeout is specified and the timeout expires, the pended task is removed from the queue of pended tasks and enters 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 VXWSem::give( ), 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 VXWSem::give( ), the unblocked task preempts the calling task.

MUTUAL EXCLUSION

To use a binary semaphore as a means of mutual exclusion, first create it with an initial state of full.

Then guard a critical section or resource by taking the semaphore with VXWSem::take( ), and exit the section or release the resource by giving the semaphore with VXWSem::give( ).

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.

SYNCHRONIZATION

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 VXWSem::take( ), and an interrupt service routine can unblock that task with VXWSem::give( ).

A semFlush( ) on a binary semaphore atomically unblocks all pended tasks in the semaphore queue; that is, all tasks are unblocked at once, before any actually execute.

CAVEATS

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 VXWMSem offer protection from unexpected task deletion.

RETURNS

N/A

SEE ALSO

VXWSem


Wind Foundation Classes : Methods

VXWMSem::VXWMSem( )

NAME

VXWMSem::VXWMSem( ) - create and initialize a mutual-exclusion semaphore

SYNOPSIS

VXWMSem
    (
    int opts
    )

DESCRIPTION

This routine allocates and initializes a mutual-exclusion semaphore. The semaphore state is initialized to full.

Semaphore options include the following:

SEM_Q_PRIORITY
Queue pended tasks on the basis of their priority.

SEM_Q_FIFO
Queue pended tasks on a first-in-first-out basis.

SEM_DELETE_SAFE
Protect a task that owns the semaphore from unexpected deletion. This option enables an implicit taskSafe( ) for each VXWSem::take( ), and an implicit taskUnsafe( ) for each VXWSem::give( ).

SEM_INVERSION_SAFE
Protect the system from priority inversion. With this option, the task owning the semaphore executes at the highest priority of the tasks pended on the semaphore, if that is higher than its current priority. This option must be accompanied by the SEM_Q_PRIORITY queuing mode.

Mutual-exclusion semaphores offer convenient options suited for situations that require mutually exclusive access to resources. Typical applications include sharing devices and protecting data structures. Mutual-exclusion semaphores are used by many higher-level VxWorks facilities.

The mutual-exclusion semaphore is a specialized version of the binary semaphore, designed to address issues inherent in mutual exclusion, such as recursive access to resources, priority inversion, and deletion safety. The fundamental behavior of the mutual-exclusion semaphore is identical to the binary semaphore as described for VXWBSem::VXWBSem( ), except for the following restrictions:

These last two operations have no meaning in mutual-exclusion situations.

RECURSIVE RESOURCE ACCESS

A special feature of the mutual-exclusion semaphore is that it may be taken "recursively;" that is, it can be taken more than once by the task that owns it before finally being released. Recursion is useful for a set of routines that need mutually exclusive access to a resource, but may need to call each other.

Recursion is possible because the system keeps track of which task currently owns a mutual-exclusion semaphore. Before being released, a mutual-exclusion semaphore taken recursively must be given the same number of times it has been taken; this is tracked by means of a count which increments with each VXWSem::take( ) and decrements with each VXWSem::give( ).

PRIORITY-INVERSION SAFETY

If the option SEM_INVERSION_SAFE is selected, the library adopts a priority-inheritance protocol to resolve potential occurrences of "priority inversion," a problem stemming from the use semaphores for mutual exclusion. Priority inversion arises when a higher-priority task is forced to wait an indefinite period of time for the completion of a lower-priority task.

Consider the following scenario: T1, T2, and T3 are tasks of high, medium, and low priority, respectively. T3 has acquired some resource by taking its associated semaphore. When T1 preempts T3 and contends for the resource by taking the same semaphore, it becomes blocked. If we could be assured that T1 would be blocked no longer than the time it normally takes T3 to finish with the resource, the situation would not be problematic. However, the low-priority task is vulnerable to preemption by medium-priority tasks; a preempting task, T2, could inhibit T3 from relinquishing the resource. This condition could persist, blocking T1 for an indefinite period of time.

The priority-inheritance protocol solves the problem of priority inversion by elevating the priority of T3 to the priority of T1 during the time T1 is blocked on T3. This protects T3, and indirectly T1, from preemption by T2. Stated more generally, the priority-inheritance protocol assures that a task which owns a resource executes at the priority of the highest priority task blocked on that resource. When execution is complete, the task gives up the resource and returns to its normal, or standard, priority. Hence, the "inheriting" task is protected from preemption by any intermediate-priority tasks.

The priority-inheritance protocol also takes into consideration a task's ownership of more than one mutual-exclusion semaphore at a time. Such a task will execute at the priority of the highest priority task blocked on any of the resources it owns. The task returns to its normal priority only after relinquishing all of its mutual-exclusion semaphores that have the inversion-safety option enabled.

SEMAPHORE DELETION

The VXWSem::~VXWSem( ) destructor terminates a semaphore and deallocates any associated memory. The deletion of a semaphore unblocks tasks pended on that semaphore; the routines which were pended return ERROR. Take special care when deleting mutual-exclusion semaphores to avoid deleting a semaphore out from under a task that already owns (has taken) that semaphore. Applications should adopt the protocol of only deleting semaphores that the deleting task owns.

TASK-DELETION SAFETY

If the option SEM_DELETE_SAFE is selected, the task owning the semaphore is protected from deletion as long as it owns the semaphore. This solves another problem endemic to mutual exclusion. Deleting a task executing in a critical region can be catastrophic. The resource could be left in a corrupted state and the semaphore guarding the resource would be unavailable, effectively shutting off all access to the resource.

As discussed in taskLib, the primitives taskSafe( ) and taskUnsafe( ) offer one solution, but as this type of protection goes hand in hand with mutual exclusion, the mutual-exclusion semaphore provides the option SEM_DELETE_SAFE, which enables an implicit taskSafe( ) with each VXWSem::take( ), and a taskUnsafe( ) with each VXWSem::give( ). This convenience is also more efficient, as the resulting code requires fewer entrances to the kernel.

CAVEATS

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 SEM_DELETE_SAFE option partially protects an application, to the extent that unexpected deletions will be deferred until the resource is released.

RETURNS

N/A

SEE ALSO

VXWSem, taskSafe( ), taskUnsafe( )


Wind Foundation Classes : Methods

VXWMSem::giveForce( )

NAME

VXWMSem::giveForce( ) - give a mutual-exclusion semaphore without restrictions

SYNOPSIS

    STATUS giveForce ()

DESCRIPTION

This routine gives a mutual-exclusion semaphore, regardless of semaphore ownership. It is intended as a debugging aid only.

The routine is particularly useful when a task dies while holding some mutual-exclusion semaphore, because the semaphore can be resurrected. The routine gives the semaphore to the next task in the pend queue, or makes the semaphore full if no tasks are pending. In effect, execution continues as if the task owning the semaphore had actually given the semaphore.

CAVEATS

Use this routine should only as a debugging aid, when the condition of the semaphore is known.

RETURNS

OK.

SEE ALSO

VXWSem::give( )