113d88268SGregory Neil Shapiro /* 213d88268SGregory Neil Shapiro * Copyright (c) 2000-2001, 2005 Sendmail, Inc. and its suppliers. 313d88268SGregory Neil Shapiro * All rights reserved. 413d88268SGregory Neil Shapiro * 513d88268SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 613d88268SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 713d88268SGregory Neil Shapiro * the sendmail distribution. 813d88268SGregory Neil Shapiro */ 913d88268SGregory Neil Shapiro 1013d88268SGregory Neil Shapiro #include <sm/gen.h> 114e4196cbSGregory Neil Shapiro SM_RCSID("@(#)$Id: sem.c,v 1.13 2005/08/12 20:39:59 ca Exp $") 1213d88268SGregory Neil Shapiro 1313d88268SGregory Neil Shapiro #if SM_CONF_SEM 1413d88268SGregory Neil Shapiro # include <stdlib.h> 1513d88268SGregory Neil Shapiro # include <unistd.h> 1613d88268SGregory Neil Shapiro # include <sm/sem.h> 1713d88268SGregory Neil Shapiro # include <sm/heap.h> 184e4196cbSGregory Neil Shapiro # include <errno.h> 1913d88268SGregory Neil Shapiro 2013d88268SGregory Neil Shapiro /* 2113d88268SGregory Neil Shapiro ** SM_SEM_START -- initialize semaphores 2213d88268SGregory Neil Shapiro ** 2313d88268SGregory Neil Shapiro ** Parameters: 2413d88268SGregory Neil Shapiro ** key -- key for semaphores. 2513d88268SGregory Neil Shapiro ** nsem -- number of semaphores. 2613d88268SGregory Neil Shapiro ** semflg -- flag for semget(), if 0, use a default. 2713d88268SGregory Neil Shapiro ** owner -- create semaphores. 2813d88268SGregory Neil Shapiro ** 2913d88268SGregory Neil Shapiro ** Returns: 3013d88268SGregory Neil Shapiro ** id for semaphores. 3113d88268SGregory Neil Shapiro ** < 0 on failure. 3213d88268SGregory Neil Shapiro */ 3313d88268SGregory Neil Shapiro 3413d88268SGregory Neil Shapiro int 3513d88268SGregory Neil Shapiro sm_sem_start(key, nsem, semflg, owner) 3613d88268SGregory Neil Shapiro key_t key; 3713d88268SGregory Neil Shapiro int nsem; 3813d88268SGregory Neil Shapiro int semflg; 3913d88268SGregory Neil Shapiro bool owner; 4013d88268SGregory Neil Shapiro { 414e4196cbSGregory Neil Shapiro int semid, i, err; 4213d88268SGregory Neil Shapiro unsigned short *semvals; 4313d88268SGregory Neil Shapiro 4413d88268SGregory Neil Shapiro semvals = NULL; 4513d88268SGregory Neil Shapiro if (semflg == 0) 4613d88268SGregory Neil Shapiro semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3); 4713d88268SGregory Neil Shapiro if (owner) 4813d88268SGregory Neil Shapiro semflg |= IPC_CREAT|IPC_EXCL; 4913d88268SGregory Neil Shapiro semid = semget(key, nsem, semflg); 5013d88268SGregory Neil Shapiro if (semid < 0) 5113d88268SGregory Neil Shapiro goto error; 5213d88268SGregory Neil Shapiro 5313d88268SGregory Neil Shapiro if (owner) 5413d88268SGregory Neil Shapiro { 5513d88268SGregory Neil Shapiro union semun semarg; 5613d88268SGregory Neil Shapiro 5713d88268SGregory Neil Shapiro semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals); 5813d88268SGregory Neil Shapiro if (semvals == NULL) 5913d88268SGregory Neil Shapiro goto error; 6013d88268SGregory Neil Shapiro semarg.array = semvals; 6113d88268SGregory Neil Shapiro 6213d88268SGregory Neil Shapiro /* initialize semaphore values to be available */ 6313d88268SGregory Neil Shapiro for (i = 0; i < nsem; i++) 6413d88268SGregory Neil Shapiro semvals[i] = 1; 6513d88268SGregory Neil Shapiro if (semctl(semid, 0, SETALL, semarg) < 0) 6613d88268SGregory Neil Shapiro goto error; 6713d88268SGregory Neil Shapiro } 6813d88268SGregory Neil Shapiro return semid; 6913d88268SGregory Neil Shapiro 7013d88268SGregory Neil Shapiro error: 714e4196cbSGregory Neil Shapiro err = errno; 7213d88268SGregory Neil Shapiro if (semvals != NULL) 7313d88268SGregory Neil Shapiro sm_free(semvals); 7413d88268SGregory Neil Shapiro if (semid >= 0) 7513d88268SGregory Neil Shapiro sm_sem_stop(semid); 764e4196cbSGregory Neil Shapiro return (err > 0) ? (0 - err) : -1; 7713d88268SGregory Neil Shapiro } 7813d88268SGregory Neil Shapiro 7913d88268SGregory Neil Shapiro /* 8013d88268SGregory Neil Shapiro ** SM_SEM_STOP -- stop using semaphores. 8113d88268SGregory Neil Shapiro ** 8213d88268SGregory Neil Shapiro ** Parameters: 8313d88268SGregory Neil Shapiro ** semid -- id for semaphores. 8413d88268SGregory Neil Shapiro ** 8513d88268SGregory Neil Shapiro ** Returns: 8613d88268SGregory Neil Shapiro ** 0 on success. 8713d88268SGregory Neil Shapiro ** < 0 on failure. 8813d88268SGregory Neil Shapiro */ 8913d88268SGregory Neil Shapiro 9013d88268SGregory Neil Shapiro int 9113d88268SGregory Neil Shapiro sm_sem_stop(semid) 9213d88268SGregory Neil Shapiro int semid; 9313d88268SGregory Neil Shapiro { 9413d88268SGregory Neil Shapiro return semctl(semid, 0, IPC_RMID, NULL); 9513d88268SGregory Neil Shapiro } 9613d88268SGregory Neil Shapiro 9713d88268SGregory Neil Shapiro /* 9813d88268SGregory Neil Shapiro ** SM_SEM_ACQ -- acquire semaphore. 9913d88268SGregory Neil Shapiro ** 10013d88268SGregory Neil Shapiro ** Parameters: 10113d88268SGregory Neil Shapiro ** semid -- id for semaphores. 10213d88268SGregory Neil Shapiro ** semnum -- number of semaphore. 10313d88268SGregory Neil Shapiro ** timeout -- how long to wait for operation to succeed. 10413d88268SGregory Neil Shapiro ** 10513d88268SGregory Neil Shapiro ** Returns: 10613d88268SGregory Neil Shapiro ** 0 on success. 10713d88268SGregory Neil Shapiro ** < 0 on failure. 10813d88268SGregory Neil Shapiro */ 10913d88268SGregory Neil Shapiro 11013d88268SGregory Neil Shapiro int 11113d88268SGregory Neil Shapiro sm_sem_acq(semid, semnum, timeout) 11213d88268SGregory Neil Shapiro int semid; 11313d88268SGregory Neil Shapiro int semnum; 11413d88268SGregory Neil Shapiro int timeout; 11513d88268SGregory Neil Shapiro { 11613d88268SGregory Neil Shapiro int r; 11713d88268SGregory Neil Shapiro struct sembuf semops[1]; 11813d88268SGregory Neil Shapiro 11913d88268SGregory Neil Shapiro semops[0].sem_num = semnum; 12013d88268SGregory Neil Shapiro semops[0].sem_op = -1; 12113d88268SGregory Neil Shapiro semops[0].sem_flg = SEM_UNDO | 12213d88268SGregory Neil Shapiro (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 12313d88268SGregory Neil Shapiro if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 12413d88268SGregory Neil Shapiro return semop(semid, semops, 1); 12513d88268SGregory Neil Shapiro do 12613d88268SGregory Neil Shapiro { 12713d88268SGregory Neil Shapiro r = semop(semid, semops, 1); 12813d88268SGregory Neil Shapiro if (r == 0) 12913d88268SGregory Neil Shapiro return r; 13013d88268SGregory Neil Shapiro sleep(1); 13113d88268SGregory Neil Shapiro --timeout; 13213d88268SGregory Neil Shapiro } while (timeout > 0); 13313d88268SGregory Neil Shapiro return r; 13413d88268SGregory Neil Shapiro } 13513d88268SGregory Neil Shapiro 13613d88268SGregory Neil Shapiro /* 13713d88268SGregory Neil Shapiro ** SM_SEM_REL -- release semaphore. 13813d88268SGregory Neil Shapiro ** 13913d88268SGregory Neil Shapiro ** Parameters: 14013d88268SGregory Neil Shapiro ** semid -- id for semaphores. 14113d88268SGregory Neil Shapiro ** semnum -- number of semaphore. 14213d88268SGregory Neil Shapiro ** timeout -- how long to wait for operation to succeed. 14313d88268SGregory Neil Shapiro ** 14413d88268SGregory Neil Shapiro ** Returns: 14513d88268SGregory Neil Shapiro ** 0 on success. 14613d88268SGregory Neil Shapiro ** < 0 on failure. 14713d88268SGregory Neil Shapiro */ 14813d88268SGregory Neil Shapiro 14913d88268SGregory Neil Shapiro int 15013d88268SGregory Neil Shapiro sm_sem_rel(semid, semnum, timeout) 15113d88268SGregory Neil Shapiro int semid; 15213d88268SGregory Neil Shapiro int semnum; 15313d88268SGregory Neil Shapiro int timeout; 15413d88268SGregory Neil Shapiro { 15513d88268SGregory Neil Shapiro int r; 15613d88268SGregory Neil Shapiro struct sembuf semops[1]; 15713d88268SGregory Neil Shapiro 15813d88268SGregory Neil Shapiro #if PARANOID 15913d88268SGregory Neil Shapiro /* XXX should we check whether the value is already 0 ? */ 16013d88268SGregory Neil Shapiro SM_REQUIRE(sm_get_sem(semid, semnum) > 0); 16113d88268SGregory Neil Shapiro #endif /* PARANOID */ 16213d88268SGregory Neil Shapiro 16313d88268SGregory Neil Shapiro semops[0].sem_num = semnum; 16413d88268SGregory Neil Shapiro semops[0].sem_op = 1; 16513d88268SGregory Neil Shapiro semops[0].sem_flg = SEM_UNDO | 16613d88268SGregory Neil Shapiro (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 16713d88268SGregory Neil Shapiro if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 16813d88268SGregory Neil Shapiro return semop(semid, semops, 1); 16913d88268SGregory Neil Shapiro do 17013d88268SGregory Neil Shapiro { 17113d88268SGregory Neil Shapiro r = semop(semid, semops, 1); 17213d88268SGregory Neil Shapiro if (r == 0) 17313d88268SGregory Neil Shapiro return r; 17413d88268SGregory Neil Shapiro sleep(1); 17513d88268SGregory Neil Shapiro --timeout; 17613d88268SGregory Neil Shapiro } while (timeout > 0); 17713d88268SGregory Neil Shapiro return r; 17813d88268SGregory Neil Shapiro } 17913d88268SGregory Neil Shapiro 18013d88268SGregory Neil Shapiro /* 18113d88268SGregory Neil Shapiro ** SM_SEM_GET -- get semaphore value. 18213d88268SGregory Neil Shapiro ** 18313d88268SGregory Neil Shapiro ** Parameters: 18413d88268SGregory Neil Shapiro ** semid -- id for semaphores. 18513d88268SGregory Neil Shapiro ** semnum -- number of semaphore. 18613d88268SGregory Neil Shapiro ** 18713d88268SGregory Neil Shapiro ** Returns: 18813d88268SGregory Neil Shapiro ** value of semaphore on success. 18913d88268SGregory Neil Shapiro ** < 0 on failure. 19013d88268SGregory Neil Shapiro */ 19113d88268SGregory Neil Shapiro 19213d88268SGregory Neil Shapiro int 19313d88268SGregory Neil Shapiro sm_sem_get(semid, semnum) 19413d88268SGregory Neil Shapiro int semid; 19513d88268SGregory Neil Shapiro int semnum; 19613d88268SGregory Neil Shapiro { 19713d88268SGregory Neil Shapiro int semval; 19813d88268SGregory Neil Shapiro 19913d88268SGregory Neil Shapiro if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0) 20013d88268SGregory Neil Shapiro return -1; 20113d88268SGregory Neil Shapiro return semval; 20213d88268SGregory Neil Shapiro } 20313d88268SGregory Neil Shapiro #endif /* SM_CONF_SEM */ 204