SEMOP(2)

NOM
semop, semtimedop - Opérations sur les sémaphores

SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int semid, struct sembuf *sops, unsigned nsops);

int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
               struct timespec *timeout);

Exigences de macros de test de fonctionnalités pour la glibc (voir feature_test_macros(7)) :

semtimedop() : _GNU_SOURCE

DESCRIPTION
Chaque sémaphore dans un jeu de sémaphores se voit associer les valeurs suivantes :

unsigned short  semval;   /* valeur du sémaphore   */
unsigned short  semzcnt;  /* # Attente pour zéro   */
unsigned short  semncnt;  /* # Attente d'incrément */
pid_t           sempid;   /* dernier processus agissant */

semop() effectue des opérations sur les membres du jeu de sémaphores identifié par semid. Chacun des nsops éléments dans le tableau pointé par sops indique une opération à effectuer sur un seul sémaphore. Les éléments de cette structure sont du type struct sembuf, contenant les membres suivants :

  unsigned short sem_num;  /* Numéro du sémaphore */
  short          sem_op;   /* Opération sur le sémaphore */
  short          sem_flg;  /* Options pour l'opération */

Les options possibles pour sem_flg sont IPC_NOWAIT et SEM_UNDO. Si une opération indique l'option SEM_UNDO, elle sera automatiquement annulée lorsque le processus se terminera.

L'ensemble des opérations contenues dans sops est effectué dans l'ordre et atomiquement. Les opérations sont soit toutes réalisées en même temps, soit pas du tout. Le comportement de l'appel système, si toutes les opérations ne sont pas réalisables, dépend de la présence de l'attribut IPC_NOWAIT dans les champs sem_flg décrits plus bas. Chaque opération est effectuée sur le sem_num-ième sémaphore de l'ensemble. Le premier sémaphore est le numéro 0. Pour chaque sémaphore, l'opération est l'une des trois décrites ci-dessous.

Si l'argument sem_op est un entier positif, la fonction ajoute cette valeur à semval. De plus, si SEM_UNDO est demandé, le système met à jour le compteur « undo » du sémaphore (semadj). Cette opération n'est jamais bloquante. Le processus appelant doit avoir l'autorisation de modification sur le jeu de sémaphores.

Si sem_op vaut zéro, le processus doit avoir l'autorisation de lecture sur le jeu de sémaphores. Le processus attend que semval soit nul : si semval vaut zéro, l'appel système continue immédiatement. Sinon, si l'on a réclamé IPC_NOWAIT dans sem_flg, semop() échoue (en annulant les actions précédentes) et errno contient le code d'erreur EAGAIN. Autrement, semzcnt est incrémenté de 1 et le processus s'endort jusqu'à ce que l'un des événements suivants se produise :

•   semval devient égal à 0, alors semzcnt est décrémenté.

•   Le jeu de sémaphores est supprimé. L'appel système échoue et errno contient le code d'erreur EIDRM.

•   Le processus reçoit un signal à intercepter, la valeur de semzcnt est décrémentée et semop() échoue avec errno contenant le code d'erreur EINTR.

•   La limite temporelle indiquée par timeout dans un semtimedop() a expiré : semop() échoue avec errno contenant EAGAIN.

Si sem_op est inférieur à zéro, le processus appelant doit avoir l'autorisation de modification sur le jeu de sémaphores. Si semval est supérieur ou égal à la valeur absolue de sem_op, la valeur absolue de sem_op est soustraite de semval. Si SEM_UNDO est indiqué, le système met à jour le compteur « undo » du sémaphore (semadj). Puis l'appel système continue. Si la valeur absolue de sem_op est plus grande que semval, et si l'on a réclamé IPC_NOWAIT dans sem_flg, semop() échoue (annulant les actions précédentes) et errno contient le code d'erreur EAGAIN. Sinon, semncnt (le compteur de processus attend que cette valeur du sémaphose augmente) est incrémenté de un et le processus s'endort jusqu'à ce que l'un des événements suivants se produise :

•   semval devient supérieur ou égal à la valeur absolue de sem_op, alors la valeur semncnt est décrémentée, la valeur absolue de sem_op est soustraite de semval et si SEM_UNDO est demandé, le système met à jour le compteur « undo » du sémaphore (semadj).

•   Le jeu de sémaphores est supprimé. semop() échoue et errno contient le code d'erreur EIDRM.

•   Le processus reçoit un signal à intercepter, la valeur de semncnt est décrémentée et semop() échoue avec errno contenant le code d'erreur EINTR.

•   La limite temporelle indiquée par timeout dans un semtimedop() a expiré : l'appel système échoue avec errno contenant EAGAIN.

En cas de succès, le membre sempid de chacun des sémaphores indiqués dans le tableau pointé par sops est rempli avec le PID du processus appelant. Enfin, sem_otime est fixé à l'heure actuelle.

semtimedop() se comporte comme semop() sauf que dans le cas où le processus doit dormir, la durée maximale du sommeil est limitée par la valeur spécifiée dans la structure timespec dont l'adresse est transmise dans le paramètre timeout. Si la limite indiquée a été atteinte, semtimedop() échoue avec errno contenant EAGAIN (et aucune opération de sops n'est réalisée). Si le paramètre timeout est NULL, alors semtimedop() se comporte exactement comme semop().

VALEUR RENVOYÉE
S'ils réussissent, semop() et semtimedop() renvoient 0, sinon ils renvoient -1, auquel cas errno contient le code d'erreur.

ERREURS
En cas d'erreur, errno prend l'une des valeurs suivantes :

E2BIG
    L'argument nsops est supérieur à SEMOPM, le nombre maximal d'opérations par appel système.

EACCES
    Le processus appelant n'a pas les permissions nécessaires pour effectuer les opérations sur les sémaphores spécifiés et n'a pas la capacité CAP_IPC_OWNER.

EAGAIN
    Une opération ne pouvait pas être effectuée immédiatement et IPC_NOWAIT a été indiqué dans l'argument sem_flg, ou la durée limite indiquée dans timeout a expiré.

EFAULT
    sops ou timeout pointent en dehors de l'espace d'adressage accessible.

EFBIG
    La valeur de sem_num est inférieure à 0 ou supérieure ou égale au nombre de sémaphores dans l'ensemble.

EIDRM
    Le jeu de sémaphores a été supprimé.

EINTR
    Un signal a été reçu pendant l'attente ; voir signal(7).

EINVAL
    L'ensemble de sémaphores n'existe pas ou semid est inférieur à zéro, ou nsops n'est pas une valeur positive.

ENOMEM
    L'argument sem_flg de certaines opérations demande SEM_UNDO et le système n'a pas assez de mémoire pour allouer les structures nécessaires.

ERANGE
    sem_op+semval est supérieur à SEMVMX, la valeur maximale de semval autorisée par l'implémentation, pour l'une des opérations.

VERSIONS
semtimedop() est apparu pour la première fois dans Linux 2.5.52, et a été retroportée par la suite dans le noyau 2.4.22. La première prise en charge de semtimedop() dans la glibc est apparue dans la version 2.3.3.

CONFORMITÉ
SVr4, POSIX.1-2001.

NOTES
Les structures sem_undo d'un processus ne sont pas héritées par ses enfants lors d'un fork(2). Par contre, elles sont transmises lors d'un execve(2).

semop() n'est jamais relancé automatiquement après avoir été interrompu par un gestionnaire de signal quelque soit l'attribut SA_RESTART durant l'installation du gestionnaire.

semadj est un entier pour le processus qui représente simplement le compte (négatif) des opérations sur le sémaphore réalisées par l'attribut SEM_UNDO. Quand la valeur d'un sémaphore est fixée directement par une requête SETVAL ou SETALL de semctl(2), la valeur semadj correspondante est effacée dans tous les processus.

Les valeurs semval, sempid, semzcnt, et semnct pour un sémaphore peuvent être retrouvées avec des appels semctl(2) spécifiques.

Les limites système suivantes concernent semop() :

SEMOPM
    Nombre maximal d'opérations pour un appel système semop() (32) (sous Linux, cette limite peut être lue et modifiée via le troisième champ de /proc/sys/kernel/sem).

SEMVMX
    Valeur maximale pour semval : dépendante de l'implémentation (32767).

L'implémentation n'a pas de limites intrinsèques pour la valeur maximale d'effacement en sortie (SEMAEM), le nombre de structure d'annulation sur le système (SEMMNU), et le nombre maximal de structures d'annulation pour un processus.

BOGUES
Quand un processus se termine, l'ensemble des structures semadj qui lui sont associées servent à annuler les effets de toutes les opérations sur les sémaphores réalisées avec l'attribut SEM_UNDO. Ceci pose un problème : si l'une (ou plusieurs) des modifications sur les sémaphores demande une descente du compteur d'un sémaphore en-dessous de zéro, que doit faire l'implémentation ? Une approche possible consiste à bloquer jusqu'à ce que la modification du sémaphore soit possible. C'est néanmoins peu désirable car la terminaison du processus peut bloquer pendant une période arbitrairement longue. Une autre possibilité est d'ignorer la modification du sémaphore (comme un échec lorsque IPC_NOWAIT est spécifié durant une opération). Linux adopte une troisième approche : décroître la valeur du sémaphore autant que possible (jusqu'à zéro) et permettre au processus de se terminer immédiatement. Dans les noyaux 2.6.x, x <= 10, un bogue peut, dans certaines circonstances, empêcher un processus attendant que la valeur d'un sémaphore passe à zéro d'être réveillé lorsque cette valeur est actuellement zéro. ce bogue a été corrigé dans le noyau 2.6.11.

EXEMPLE
La portion de code suivante utilise semop() pour attendre atomiquement que la valeur du sémaphore 0 devienne nulle, puis incrémente de 1 la valeur du sémaphore.
    struct sembuf sops[2];
    int semid;
    /* Le code pour configurer semid est omis */
    sops[0].sem_num = 0;        /* Agir sur le sémaphore 0 */
    sops[0].sem_op = 0;         /* Attendre que la valeur soit égale à 0 */
    sops[0].sem_flg = 0;
    sops[1].sem_num = 0;        /* Agir sur le sémaphore 0 */
    sops[1].sem_op = 1;         /* Incrémenter la valeur de 1 */
    sops[1].sem_flg = 0;
    if (semop(semid, &sop, 2) == -1) {
        perror("semop");
        exit(EXIT_FAILURE);
    }

VOIR AUSSI
semctl(2), semget(2), sigaction(2), capabilities(7), sem_overview(7), svipc(7), time(7)

TRADUCTION

Ce document est une traduction réalisée par Christophe Blaess <http://www.blaess.fr/christophe/> le 15 octobre 1996 et révisée le 17 juillet 2008.

L'équipe de traduction a fait le maximum pour réaliser une adaptation française de qualité. La version anglaise la plus à jour de ce document est toujours consultable via la commande : « LANG=C man 2 semop ». N'hésitez pas à signaler à l'auteur ou au traducteur, selon le cas, toute erreur dans cette page de manuel.