semctl(2)
semctl(2) ๐ โ System Calls Manual ๐
okay so bestie, semctl(2) has entered the chat, and it is highkey the control room for System V semaphores. No cap, this is the System Calls Manual energy: you've got a semaphore set, you've got operations, and it's giving main character vibes. ๐
๐ NAME ๐
semctl โ System V semaphore control operations. Periodt. โจ
๐ LIBRARY ๐
Standard C library (libc, -lc). Slay. ๐ซถ
โจ SYNOPSIS โจ
#include <sys/sem.h>
int semctl(int semid, int semnum, int op, ...);
๐ธ DESCRIPTION ๐ธ
okay so semctl() performs the control operation specified by op on the System V semaphore set identified by semid, or on the semnum-th semaphore of that set. (The semaphores in a set are numbered starting at 0.) ๐
This function has three or four arguments, depending on op. When there are four, the fourth has the type union semun. The calling program must define this union as follows โ yes, you, bestie, you define it:
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
The semid_ds data structure is defined in <sys/sem.h> as follows:
struct semid_ds {
struct ipc_perm sem_perm; /* Ownership and permissions */
time_t sem_otime; /* Last semop time */
time_t sem_ctime; /* Creation time/time of last
modification via semctl() */
unsigned long sem_nsems; /* # of semaphores in set */
};
The fields of the semid_ds structure are as follows:
sem_permโ This is anipc_permstructure (see below) that specifies the access permissions on the semaphore set. ๐sem_otimeโ Time of lastsemop(2)system call. โฐsem_ctimeโ Time of creation of semaphore set or time of lastsemctl()IPCSET,SETVAL, orSETALLoperation. ๐ฐ๏ธsem_nsemsโ Number of semaphores in the set. Each semaphore of the set is referenced by a nonnegative integer ranging from0tosem_nsems-1. ๐ข
The ipc_perm structure is defined as follows โ the fields settable using IPC_SET are the ones getting the main-character treatment:
struct ipc_perm {
key_t __key; /* Key supplied to semget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions */
unsigned short __seq; /* Sequence number */
};
The least significant 9 bits of the mode field of the ipc_perm structure define the access permissions for the shared memory segment. The permission bits are as follows:
0400 Read by user
0200 Write by user
0040 Read by group
0020 Write by group
0004 Read by others
0002 Write by others
In effect, "write" means "alter" for a semaphore set. Bits 0100, 0010, and 0001 (the execute bits) are unused by the system. ๐ฆ
Valid values for op are literally these, bestie:
IPC_STATโ Copy information from the kernel data structure associated withsemidinto thesemid_dsstructure pointed to byarg.buf. The argumentsemnumis ignored. The calling process must have read permission on the semaphore set. ๐IPC_SETโ Write the values of some members of thesemid_dsstructure pointed to byarg.bufto the kernel data structure associated with this semaphore set, updating also itssem_ctimemember.
The following members of the structure are updated: sem_perm.uid, sem_perm.gid, and (the least significant 9 bits of) sem_perm.mode.
The effective UID of the calling process must match the owner (sem_perm.uid) or creator (sem_perm.cuid) of the semaphore set, or the caller must be privileged. The argument semnum is ignored. ๐
IPC_RMIDโ Immediately remove the semaphore set, awakening all processes blocked insemop(2)calls on the set (with an error return anderrnoset toEIDRM). The effective user ID of the calling process must match the creator or owner of the semaphore set, or the caller must be privileged. The argumentsemnumis ignored. ๐๏ธIPC_INFO(Linux-specific) โ Return information about system-wide semaphore limits and parameters in the structure pointed to byarg.__buf. This structure is of typeseminfo, defined in<sys/sem.h>if the_GNU_SOURCEfeature test macro is defined:
struct seminfo {
int semmap; /* Number of entries in semaphore
map; unused within kernel */
int semmni; /* Maximum number of semaphore sets */
int semmns; /* Maximum number of semaphores in all
semaphore sets */
int semmnu; /* System-wide maximum number of undo
structures; unused within kernel */
int semmsl; /* Maximum number of semaphores in a
set */
int semopm; /* Maximum number of operations for
semop(2) */
int semume; /* Maximum number of undo entries per
process; unused within kernel */
int semusz; /* Size of struct sem_undo */
int semvmx; /* Maximum semaphore value */
int semaem; /* Max. value that can be recorded for
semaphore adjustment (SEM_UNDO) */
};
The semmsl, semmns, semopm, and semmni settings can be changed via /proc/sys/kernel/sem; see proc(5) for details. ๐
SEM_INFO(Linux-specific) โ Return aseminfostructure containing the same information as forIPC_INFO, except that the following fields are returned with information about system resources consumed by semaphores: thesemuszfield returns the number of semaphore sets that currently exist on the system; and thesemaemfield returns the total number of semaphores in all semaphore sets on the system. ๐SEM_STAT(Linux-specific) โ Return asemid_dsstructure as forIPC_STAT. However, thesemidargument is not a semaphore identifier, but instead an index into the kernel's internal array that maintains information about all semaphore sets on the system. ๐ฅSEM_STAT_ANY(Linux-specific, since Linux 4.17) โ Return asemid_dsstructure as forSEM_STAT. However,sem_perm.modeis not checked for read access forsemidmeaning that any user can employ this operation (just as any user may read/proc/sysvipc/semto obtain the same information). ๐GETALLโ Returnsemval(i.e., the current value) for all semaphores of the set intoarg.array. The argumentsemnumis ignored. The calling process must have read permission on the semaphore set. ๐GETNCNTโ Return thesemncntvalue for thesemnum-th semaphore of the set (i.e., the number of processes waiting for the semaphore's value to increase). The calling process must have read permission on the semaphore set. ๐งGETPIDโ Return thesempidvalue for thesemnum-th semaphore of the set. This is the PID of the process that last performed an operation on that semaphore (but see VERSIONS). The calling process must have read permission on the semaphore set. ๐GETVALโ Returnsemval(i.e., the semaphore value) for thesemnum-th semaphore of the set. The calling process must have read permission on the semaphore set. โญGETZCNTโ Return thesemzcntvalue for thesemnum-th semaphore of the set (i.e., the number of processes waiting for the semaphore value to become0). The calling process must have read permission on the semaphore set. ๐SETALLโ Set thesemvalvalues for all semaphores of the set usingarg.array, updating also thesem_ctimemember of thesemid_dsstructure associated with the set. Undo entries (seesemop(2)) are cleared for altered semaphores in all processes. If the changes to semaphore values would permit blockedsemop(2)calls in other processes to proceed, then those processes are woken up. The argumentsemnumis ignored. The calling process must have alter (write) permission on the semaphore set. ๐ฅSETVALโ Set the semaphore value (semval) toarg.valfor thesemnum-th semaphore of the set, updating also thesem_ctimemember of thesemid_dsstructure associated with the set. Undo entries are cleared for altered semaphores in all processes. If the changes to semaphore values would permit blockedsemop(2)calls in other processes to proceed, then those processes are woken up. The calling process must have alter permission on the semaphore set. ๐
๐ RETURN VALUE ๐
On success, semctl() returns a nonnegative value depending on op as follows:
GETNCNTโ the value ofsemncnt. ๐งGETPIDโ the value ofsempid. ๐GETVALโ the value ofsemval. โญGETZCNTโ the value ofsemzcnt. ๐IPC_INFOโ the index of the highest used entry in the kernel's internal array recording information about all semaphore sets. (This information can be used with repeatedSEM_STATorSEM_STAT_ANYoperations to obtain information about all semaphore sets on the system.) ๐SEM_INFOโ as forIPC_INFO. ๐SEM_STATโ the identifier of the semaphore set whose index was given insemid. ๐ฅSEM_STAT_ANYโ as forSEM_STAT. ๐
All other op values return 0 on success. โจ
On failure, semctl() returns -1 and sets errno to indicate the error. ๐ญ
๐ ERRORS ๐
okay so when semctl() is in its flop era, it sets errno and here's the entire receipts list, no gatekeeping:
EACCESโ theopyou passed is one ofGETALL,GETPID,GETVAL,GETNCNT,GETZCNT,IPC_STAT,SEM_STAT,SEM_STAT_ANY,SETALL, orSETVAL, and your calling process does not have the required permissions on the semaphore set, and also doesn't have theCAP_IPC_OWNERcapability in the user namespace that governs its IPC namespace. like bestie, you're literally not on the list ๐EFAULTโ the address thatarg.buforarg.arrayis pointing at isn't accessible. it's giving "pointer to nowhere" ๐ซEIDRMโ the semaphore set was removed. gone, deleted, no longer with us ๐ญEINVALโ invalid value foroporsemid. OR: for aSEM_STAToperation, the index value you put insemidpointed at an array slot that's currently unused. empty seat at the table fr.EPERMโ theopisIPC_SETorIPC_RMID, but the effective user ID of the calling process isn't the creator (that'ssem_perm.cuid) or the owner (that'ssem_perm.uid) of the semaphore set, and the process doesn't have theCAP_SYS_ADMINcapability. not your semaphore, not your call, periodt ๐ โโ๏ธERANGEโ theopisSETALLorSETVAL, and the value you're trying to setsemvalto (for some semaphore in the set) is less than 0 or greater than the implementation limitSEMVMX. stay in your lane, numbers ๐ซ
๐ VERSIONS ๐
okay so tea time, history edition โ:
POSIX.1 says the sem_nsems field of the semid_ds structure has the type unsigned short, and that's how it's defined on most other systems. it was also defined that way on Linux 2.2 and earlier โ but since Linux 2.4, that field has the type unsigned long. glow-up, honestly โจ
๐ฆ The sempid value ๐ฆ
POSIX.1 defines sempid as the "process ID of [the] last operation" on a semaphore, and it explicitly says this value gets set by a successful semop(2) call โ with the implication that literally no other interface touches the sempid value. like, hands off, that's semop(2)'s job ๐
and while some implementations do conform to the behavior POSIX.1 specifies, others simply do not. (the fault here probably lies with POSIX.1 itself, inasmuch as it likely failed to capture the full range of existing implementation behaviors. not to be messy but ๐)
various other implementations also update sempid for the other operations that update the value of a semaphore: the SETVAL and SETALL operations, plus the semaphore adjustments performed on process termination as a consequence of the use of the SEM_UNDO flag (peep semop(2) for that one).
Linux also updates sempid for SETVAL operations and semaphore adjustments. BUT โ and this is the inconsistent part, highkey iconic behavior โ up to and including Linux 4.5, the kernel did not update sempid for SETALL operations. that got rectified in Linux 4.6. character development fr ๐
๐ STANDARDS ๐
POSIX.1-2024. certified canon, no notes ๐
๐ HISTORY ๐
POSIX.1-2001, SVr4. the origin story ๐ซถ
various fields in a struct semid_ds were typed as short under Linux 2.2 and have become long under Linux 2.4. to take advantage of this, a recompilation under glibc-2.1.91 or later should suffice. (the kernel distinguishes old and new calls by an IPC_64 flag in op.) so basically, just rebuild and you're slaying ๐จ
in some earlier versions of glibc, the semun union was defined in <sys/sem.h>, but POSIX.1 requires that the caller define this union. so on versions of glibc where this union is not defined, the macro _SEM_SEMUN_UNDEFINED is defined in <sys/sem.h> โ your little heads-up that "bestie you have to write it yourself" ๐
๐ NOTES ๐
the IPC_INFO, SEM_STAT, and SEM_INFO operations are used by the ipcs(1) program to provide information on allocated resources. and in the future these may be modified or moved to a /proc filesystem interface. so like... watch this space, ig ๐
also, this system limit on semaphore sets affects a semctl() call:
SEMVMXโ maximum value forsemval: implementation dependent (32767).
and for greater portability, it's best to always call semctl() with four arguments. four is the magic number, no cap ๐
real talk: if your code is out here calling semctl() with three arguments and then getting confused, this is your sign. pass all four. future you says thank you ๐
โจ EXAMPLES โจ
see shmop(2).
(yeah, that's it. go read shmop(2), it ate ๐ฝ๏ธ)
๐ SEE ALSO ๐
ipc(2), semget(2), semop(2), capabilities(7), sem_overview(7), sysvipc(7)
and that's a wrap on semctl(2), bestie!! ๐ this little masterpiece comes from Linux man-pages 6.20, dated 2026-02-08 โ so if you're reading this in some future era, hi, hope the semaphores are behaving ๐ฆ
now go forth and manipulate those semaphore sets responsibly, and remember: check your return values, always pass four arguments, and never trust sempid without reading the VERSIONS section first ๐๐
โจ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- Copyright 1993, Giorgio Ciucci <giorgio@crcc.it>
- Copyright 2004-2005, Michael Kerrisk <mtk.manpages@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms