sem.c revision 147078
1226586Sdim/* 2226586Sdim * Copyright (c) 2000-2001, 2005 Sendmail, Inc. and its suppliers. 3226586Sdim * All rights reserved. 4226586Sdim * 5226586Sdim * By using this file, you agree to the terms and conditions set 6226586Sdim * forth in the LICENSE file which can be found at the top level of 7226586Sdim * the sendmail distribution. 8226586Sdim */ 9226586Sdim 10226586Sdim#include <sm/gen.h> 11226586SdimSM_RCSID("@(#)$Id: sem.c,v 1.12 2005/03/25 21:27:02 ca Exp $") 12226586Sdim 13226586Sdim#if SM_CONF_SEM 14226586Sdim# include <stdlib.h> 15226586Sdim# include <unistd.h> 16226586Sdim# include <sm/sem.h> 17226586Sdim# include <sm/heap.h> 18249423Sdim 19249423Sdim/* 20226586Sdim** SM_SEM_START -- initialize semaphores 21226586Sdim** 22249423Sdim** Parameters: 23226586Sdim** key -- key for semaphores. 24249423Sdim** nsem -- number of semaphores. 25226586Sdim** semflg -- flag for semget(), if 0, use a default. 26226586Sdim** owner -- create semaphores. 27226586Sdim** 28226586Sdim** Returns: 29226586Sdim** id for semaphores. 30226586Sdim** < 0 on failure. 31226586Sdim*/ 32226586Sdim 33226586Sdimint 34226586Sdimsm_sem_start(key, nsem, semflg, owner) 35226586Sdim key_t key; 36226586Sdim int nsem; 37226586Sdim int semflg; 38226586Sdim bool owner; 39226586Sdim{ 40226586Sdim int semid, i; 41226586Sdim unsigned short *semvals; 42226586Sdim 43226586Sdim semvals = NULL; 44226586Sdim if (semflg == 0) 45226586Sdim semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3); 46226586Sdim if (owner) 47226586Sdim semflg |= IPC_CREAT|IPC_EXCL; 48226586Sdim semid = semget(key, nsem, semflg); 49226586Sdim if (semid < 0) 50226586Sdim goto error; 51226586Sdim 52226586Sdim if (owner) 53234353Sdim { 54226586Sdim union semun semarg; 55226586Sdim 56226586Sdim semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals); 57226586Sdim if (semvals == NULL) 58226586Sdim goto error; 59226586Sdim semarg.array = semvals; 60226586Sdim 61226586Sdim /* initialize semaphore values to be available */ 62226586Sdim for (i = 0; i < nsem; i++) 63226586Sdim semvals[i] = 1; 64226586Sdim if (semctl(semid, 0, SETALL, semarg) < 0) 65226586Sdim goto error; 66226586Sdim } 67226586Sdim return semid; 68226586Sdim 69226586Sdimerror: 70226586Sdim if (semvals != NULL) 71234353Sdim sm_free(semvals); 72226586Sdim if (semid >= 0) 73226586Sdim sm_sem_stop(semid); 74226586Sdim return -1; 75226586Sdim} 76226586Sdim 77226586Sdim/* 78226586Sdim** SM_SEM_STOP -- stop using semaphores. 79226586Sdim** 80226586Sdim** Parameters: 81234353Sdim** semid -- id for semaphores. 82226586Sdim** 83226586Sdim** Returns: 84234353Sdim** 0 on success. 85234353Sdim** < 0 on failure. 86234353Sdim*/ 87234353Sdim 88234353Sdimint 89234353Sdimsm_sem_stop(semid) 90234353Sdim int semid; 91234353Sdim{ 92234353Sdim return semctl(semid, 0, IPC_RMID, NULL); 93234353Sdim} 94234353Sdim 95234353Sdim/* 96234353Sdim** SM_SEM_ACQ -- acquire semaphore. 97234353Sdim** 98226586Sdim** Parameters: 99226586Sdim** semid -- id for semaphores. 100226586Sdim** semnum -- number of semaphore. 101226586Sdim** timeout -- how long to wait for operation to succeed. 102226586Sdim** 103226586Sdim** Returns: 104226586Sdim** 0 on success. 105226586Sdim** < 0 on failure. 106226586Sdim*/ 107226586Sdim 108226586Sdimint 109226586Sdimsm_sem_acq(semid, semnum, timeout) 110226586Sdim int semid; 111226586Sdim int semnum; 112226586Sdim int timeout; 113226586Sdim{ 114226586Sdim int r; 115226586Sdim struct sembuf semops[1]; 116226586Sdim 117226586Sdim semops[0].sem_num = semnum; 118226586Sdim semops[0].sem_op = -1; 119226586Sdim semops[0].sem_flg = SEM_UNDO | 120226586Sdim (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 121226586Sdim if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 122234353Sdim return semop(semid, semops, 1); 123234353Sdim do 124226586Sdim { 125234353Sdim r = semop(semid, semops, 1); 126234353Sdim if (r == 0) 127234353Sdim return r; 128226586Sdim sleep(1); 129226586Sdim --timeout; 130226586Sdim } while (timeout > 0); 131226586Sdim return r; 132226586Sdim} 133226586Sdim 134226586Sdim/* 135226586Sdim** SM_SEM_REL -- release semaphore. 136226586Sdim** 137226586Sdim** Parameters: 138226586Sdim** semid -- id for semaphores. 139226586Sdim** semnum -- number of semaphore. 140226586Sdim** timeout -- how long to wait for operation to succeed. 141226586Sdim** 142226586Sdim** Returns: 143226586Sdim** 0 on success. 144226586Sdim** < 0 on failure. 145226586Sdim*/ 146226586Sdim 147226586Sdimint 148226586Sdimsm_sem_rel(semid, semnum, timeout) 149226586Sdim int semid; 150226586Sdim int semnum; 151226586Sdim int timeout; 152226586Sdim{ 153226586Sdim int r; 154226586Sdim struct sembuf semops[1]; 155226586Sdim 156226586Sdim#if PARANOID 157226586Sdim /* XXX should we check whether the value is already 0 ? */ 158226586Sdim SM_REQUIRE(sm_get_sem(semid, semnum) > 0); 159226586Sdim#endif /* PARANOID */ 160226586Sdim 161226586Sdim semops[0].sem_num = semnum; 162226586Sdim semops[0].sem_op = 1; 163226586Sdim semops[0].sem_flg = SEM_UNDO | 164226586Sdim (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 165226586Sdim if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 166226586Sdim return semop(semid, semops, 1); 167226586Sdim do 168226586Sdim { 169226586Sdim r = semop(semid, semops, 1); 170226586Sdim if (r == 0) 171226586Sdim return r; 172226586Sdim sleep(1); 173226586Sdim --timeout; 174226586Sdim } while (timeout > 0); 175226586Sdim return r; 176226586Sdim} 177226586Sdim 178226586Sdim/* 179226586Sdim** SM_SEM_GET -- get semaphore value. 180226586Sdim** 181226586Sdim** Parameters: 182226586Sdim** semid -- id for semaphores. 183226586Sdim** semnum -- number of semaphore. 184226586Sdim** 185226586Sdim** Returns: 186226586Sdim** value of semaphore on success. 187226586Sdim** < 0 on failure. 188226586Sdim*/ 189226586Sdim 190226586Sdimint 191226586Sdimsm_sem_get(semid, semnum) 192226586Sdim int semid; 193226586Sdim int semnum; 194234353Sdim{ 195234353Sdim int semval; 196226586Sdim 197226586Sdim if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0) 198226586Sdim return -1; 199226586Sdim return semval; 200234353Sdim} 201234353Sdim#endif /* SM_CONF_SEM */ 202234353Sdim