Semaphore Set Functions
A semaphore is a synchronization mechanism similar to a mutex or a machine interface (MI) lock. It can be used to control access to shared resources, or used to notify other threads of the availability of resources. It differs from a mutex in the following ways:
- A semaphore set is not a single value, but has a set of values. It is
referred to through a semaphore set containing multiple
semaphores. Each semaphore set is identified by a semid, which
identifies the semaphore set, and a semnum, which identifies the
semaphore within the set. Multiple semaphore operations may be specified on one
semop() call. These operations are atomic on multiple
semaphores within a semaphore set.
- Semaphore values can range from 0 to 65535.
- Semaphores have permissions associated with them. A thread
must have appropriate authorities to perform an operation on a semaphore.
- A semaphore can have a semaphore adjustment value associated with it. This value represents resource allocations which can be automatically undone by the system when the thread ends, representing the releasing of resources. The adjustment value can range from -32767 to 32767.
Thus, a semaphore can be used as a resource counter or as a lock.
A process gets a semaphore set identifier by calling the semget() function. Depending on the key and semflg parameters passed in, either a new semaphore set is created or an existing semaphore set is accessed. When a new semaphore set is created, a data structure is also created to contain information about the semaphore set. This structure is defined in the <sys/sem.h> header file as follows:
typedef struct semid_ds {
struct ipc_perm sem_perm; /* Permissions */
unsigned short sem_nsems; /* Number of semaphores in set */
#if ((defined _64_BIT_TIME) && (__OS400_TGTVRM__ >= 740))
time64_t sem_otime; /* Time of last semop() */
time64_t sem_ctime; /* Time of last change by semctl_time64() */
#else
time_t sem_otime; /* Time of last semop() */
time_t sem_ctime; /* Time of last change by semctl() */
#endif
} semtablentry_t;
#if (__OS400_TGTVRM__ >= 740)
/* Semaphore set information */
typedef struct semid_ds_time64 {
struct ipc_perm sem_perm; /* Permissions */
unsigned short sem_nsems; /* Number of semaphores in set */
time64_t sem_otime; /* Time of last semop() */
time64_t sem_ctime; /* Time of last change by semctl_time64() */
} semtablentry_time64_t;
#endif
A thread performs operations on one or more of the semaphores in a set by calling the semop() function. The following parameters are passed in:
- Semaphore ID
- Pointer to an array of sembuf structures
- Number of sembuf structures in the array.
The sembuf structure is defined in the <sys/sem.h> header file as follows:
struct sembuf {
unsigned short sem_num; /* Semaphore number */
short sem_op; /* Semaphore operation */
short sem_flg; /* Operation flags */
};
The operation performed on a semaphore is specified by the sem_op field, which can be positive, negative, or zero:
- If sem_op is positive, the value of sem_op is added to the semaphore's current value.
- If sem_op is zero, the caller will wait until the semaphore's value becomes zero.
- If sem_op is negative, the caller will wait until the semaphore's value is greater than or equal to the absolute value of sem_op. Then the absolute value of sem_op is subtracted from the semaphore's current value.
The sem_flg value specifies whether or not the thread is willing to wait, and also whether or not the thread wants the system to keep a semaphore adjustment value for the semaphore.
Semaphore waits are visible from the Work with Active Jobs display. A thread waiting on a semaphore in a semaphore set appears to be in a semaphore wait state (SEMW) on the Work with Threads display (requested using the WRKJOB command and taking option 20). Displaying the call stack of the thread shows the semop() function near the bottom of the stack.
A thread removes a semaphore set ID by calling the semctl() function. The thread also can use the semctl() function to change the data structure values associated with the semaphore set ID or to retrieve the data structure values associated with the semaphore set ID. The following parameters are passed in:
- Semaphore set ID
- Command the thread wants to perform (remove ID, set data structure values, receive data structure values),
- Pointer to a buffer from which to set data structure values, or in which to receive data structure values.
In addition, the semctl() function can perform various other control operations on a specific semaphore within a set, or on an entire semaphore set:
- Set or retrieve a semaphore value.
- Retrieve the process ID of the last thread to operate on a semaphore.
- Retrieve the number of threads waiting for a semaphore value to increase.
- Retrieve the number of threads waiting for a semaphore value to become zero.
- Retrieve the value of every semaphore in a semaphore set.
- Set the value of every semaphore in a semaphore set.
Semaphore Set Differences and Restrictions
IBM® i semaphore sets differ from the definition in the Single UNIX® Specification in the following ways:
- The Single UNIX Specification does not define threads. Consequently,
Single UNIX Specification semaphores are defined in terms of processes and the semaphore:
- Causes the entire process to wait
- Releases resources when the process ends
- Causes only a single thread to wait
- Releases resources when the thread ends
- The maximum number of semaphore sets that can be created (system-wide) is
2 147 483 646.
- The maximum number of semaphores per semaphore set is 65535.
- Semaphores values are limited to the range from 0 to 65535. Adjustment values associated with a semaphore are limited to the range -32767 to 32767.
The semaphore set functions are:
- semctl() (Perform Semaphore Control Operations) provides semaphore control operations as specified by cmd on the semaphore specified by semnum in the semaphore set specified by semid.
- semctl_time64() (Perform Semaphore Control Operations (64-bit time64_t enabled)) provides semaphore control operations as specified by cmd on the semaphore specified by semnum in the semaphore set specified by semid.
- semget() (Get Semaphore Set with Key) returns the semaphore ID associated with the specified semaphore key.
- semop() (Perform Semaphore Operations on Semaphore Set) performs operations on semaphores in a semaphore set. These operations are supplied in a user-defined array of operations.
See also IPC Key Generation Functions for additional semaphore set functions.