DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 

Intro(SYNCH)


Intro -- introduction to synchronization routines in the Threads Library

Synopsis

   cc [options] -Kthread file
   

#include <synch.h>

Description

The Threads Library supplies routines for thread management that allow a programmer to implement parallel algorithms conveniently. In addition, the Threads Library supplies user-level synchronization routines that allow coordination of threads within a process or across processes. The synchronization interfaces allow coordination of threads within a process as well as coordination of threads in different processes. The following synchronization mechanisms are specified:

Most of these mechanisms can be initialized to be of one of two types: USYNC_THREAD or USYNC_PROCESS. USYNC_THREAD mechanisms should be used only by threads within the current process, whether or not the synchronization objects are in shared memory. USYNC_PROCESS mechanisms can be used by threads in different processes.

In all cases, data is protected by convention; a thread not following the order of acquiring a lock/semaphore, modifying or using the resource, then releasing the lock/semaphore is not prevented from modifying the shared data.

Error handling

None of the Threads Library user synchronization routines set errno; most return an error number if an error is encountered. This discourages use of errno, which is non-reentrant. The Threads Library does not guarantee to preserve errno across calls.

Mutual exclusion locks

A mutual exclusion lock, or ``mutex'', is a synchronization mechanism used to serialize the execution of threads. They are typically used to ensure that only one thread at a time is operating on a shared datum. When mutexes are locked before and unlocked after every access to shared data, the integrity of that data is assured. Note that mutexes protect data only when the convention of acquiring and releasing the mutex is faithfully followed before and after any access of the data.

See mutex(SYNCH), mutex_destroy(SYNCH), mutex_init(SYNCH), mutex_lock(SYNCH), mutex_trylock(SYNCH), and mutex_unlock(SYNCH).

Spin locks and recursive mutex locks are variations of the mutex lock.

Condition variables

A condition variable is a user-level synchronization mechanism used to communicate information between cooperating threads, making it possible for a thread to suspend its execution while waiting for an event or condition. For example, the consumer in a producer-consumer algorithm might need to wait for the producer by waiting for the condition buffer is not empty.

See condition(SYNCH), cond_broadcast(SYNCH), cond_destroy(SYNCH), cond_init(SYNCH), cond_signal(SYNCH), cond_timedwait(SYNCH), and cond_wait(SYNCH).

Reader-writer locks

Reader-writer locks allow many threads to have simultaneous read-only access to data, while allowing only one thread to have write access at any time. They are typically used to protect data that is searched more often than it is changed.

See rwlock(SYNCH), rw_rdlock(SYNCH), rw_tryrdlock(SYNCH), rw_trywrlock(SYNCH), rw_unlock(SYNCH), rw_wrlock(SYNCH), rwlock_destroy(SYNCH), and rwlock_init(SYNCH).

Semaphores

Conceptually, a semaphore is a non-negative integer count. Semaphores are typically used to coordinate access to resources. The semaphore count is initialized with sema_init to the number of free resources. Threads then atomically increment the count with sema_post when resources are released and atomically decrement the count with sema_wait when resources are acquired. When the semaphore count becomes zero, indicating that no more resources are present, threads trying to decrement the semaphore with sema_wait will block until the count becomes greater than zero.

See semaphore(SYNCH), sema_destroy(SYNCH), sema_init(SYNCH), sema_post(SYNCH), sema_trywait(SYNCH), and sema_wait(SYNCH).

Barriers

Barriers provide a simple coordination mechanism for threads. Threads wait at a barrier until a specified number of threads have reached the barrier, then they all resume execution.

There are two types of barriers: blocking and spinning. Threads waiting at a blocking barrier are put to sleep, or ``blocked'', until the specified number of threads have reached the barrier. Threads waiting at a spinning barrier busy-wait, or ``spin'', until the specified number of threads have reached the barrier.

When a thread calls barrier_wait(SYNCH) (for a blocking barrier) or _barrier_spin (for a spinning barrier), it is said to have reached the barrier.

Because spinning barriers waste resources, most applications should use blocking barriers instead of spinning barriers. Spinning barriers should only be used when all participating threads will reach the barrier at approximately the same time.

Spinning barriers should never be used on a single processor system.

See barrier(SYNCH), barrier_destroy(SYNCH), barrier_init(SYNCH), _barrier_spin(SYNCH), _barrier_spin_destroy(SYNCH), _barrier_spin_init(SYNCH), and barrier_wait(SYNCH).

Spin locks

Spin locks are a type of mutex. The difference between spin locks and ordinary mutex locks is in their locking routines. When a mutex is already locked, the locking routine (mutex_lock(SYNCH)) will block the caller until the lock is available. When a spin lock is already locked, the locking routine (_spin_lock(SYNCH)) will busy-wait, or ``spin'', in a loop, testing if the lock has become available. Such spinning wastes processor cycles and can slow processors doing useful work, including the processor holding the lock, by consuming communication bandwidth.

Because spin locks waste system resources, most applications should use mutexes instead of spin locks for mutual exclusion. However, spin locks are useful when:

Spin locks should only be used when there is a guarantee that the thread will not be preempted or blocked while holding a spin lock. It is the responsibility of each application to unlock all spin locks before calling sleep or blocking routines.

Spin locks must not be used on a single processor system. In the best case, a spin lock on a single processor system will waste resources, slowing down the owner of the lock; in the worst case, it will deadlock the processor.

See _spin(SYNCH), _spin_destroy(SYNCH), _spin_init(SYNCH), _spin_lock(SYNCH), _spin_trylock(SYNCH), and _spin_unlock(SYNCH).

Recursive mutex locks

Recursive mutual exclusion locks, or ``rmutexe''s, are mutexes that can be locked recursively. That is, a thread that has locked an rmutex can lock it again without releasing it. The thread that has locked an rmutex is referred to as the owner of the rmutex. Only the owner of an rmutex can lock it again while the rmutex is locked; other threads are denied access as with ordinary mutexes. Each rmutex_lock(SYNCH) or rmutex_trylock(SYNCH) call must be matched by a corresponding rmutex_unlock before the rmutex is made available to threads other than the owner.

Note that rmutexes, like mutexes, protect data only when the convention of acquiring the rmutex is faithfully followed before any access of the data.

See rmutex(SYNCH), rmutex_destroy(SYNCH), rmutex_init(SYNCH), rmutex_lock(SYNCH), rmutex_trylock(SYNCH), and rmutex_unlock(SYNCH).

Tracing mechanism

The Threads Library provides a mechanism for tracing significant library events. Calls to all Threads Library interfaces can be traced. See thread_trace(F).

Warnings

The Threads Library does not guarantee to preserve errno across calls.

References

barrier(SYNCH), barrier_destroy(SYNCH), barrier_init(SYNCH), _barrier_spin(SYNCH), _barrier_spin_destroy(SYNCH), _barrier_spin_init(SYNCH), barrier_wait(SYNCH), condition(SYNCH), cond_broadcast(SYNCH), cond_destroy(SYNCH), cond_init(SYNCH), cond_signal(SYNCH), cond_timedwait(SYNCH), cond_wait(SYNCH), mutex(SYNCH), mutex_destroy(SYNCH), mutex_init(SYNCH), mutex_lock(SYNCH), mutex_trylock(SYNCH), mutex_unlock(SYNCH), rmutex(SYNCH), rmutex_destroy(SYNCH), rmutex_init(SYNCH), rmutex_lock(SYNCH), rmutex_trylock(SYNCH), rmutex_unlock(SYNCH), rwlock(SYNCH), rw_rdlock(SYNCH), rw_tryrdlock(SYNCH), rw_trywrlock(SYNCH), rw_unlock(SYNCH), rw_wrlock(SYNCH), rwlock_destroy(SYNCH), rwlock_init(SYNCH), semaphore(SYNCH), sema_destroy(SYNCH), sema_init(SYNCH), sema_post(SYNCH), sema_trywait(SYNCH), sema_wait(SYNCH), _spin(SYNCH), _spin_destroy(SYNCH), _spin_init(SYNCH), _spin_lock(SYNCH), _spin_trylock(SYNCH), _spin_unlock(SYNCH), thread(THREAD), thread_trace(F)

Standards compliance

The synch library is not part of any currently supported standard.
© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 - 01 June 2005