1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001, 2005 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 6*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 7*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 8*7c478bd9Sstevel@tonic-gate */ 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h> 13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: sem.c,v 1.12 2005/03/25 21:27:02 ca Exp $") 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #if SM_CONF_SEM 16*7c478bd9Sstevel@tonic-gate # include <stdlib.h> 17*7c478bd9Sstevel@tonic-gate # include <unistd.h> 18*7c478bd9Sstevel@tonic-gate # include <sm/sem.h> 19*7c478bd9Sstevel@tonic-gate # include <sm/heap.h> 20*7c478bd9Sstevel@tonic-gate 21*7c478bd9Sstevel@tonic-gate /* 22*7c478bd9Sstevel@tonic-gate ** SM_SEM_START -- initialize semaphores 23*7c478bd9Sstevel@tonic-gate ** 24*7c478bd9Sstevel@tonic-gate ** Parameters: 25*7c478bd9Sstevel@tonic-gate ** key -- key for semaphores. 26*7c478bd9Sstevel@tonic-gate ** nsem -- number of semaphores. 27*7c478bd9Sstevel@tonic-gate ** semflg -- flag for semget(), if 0, use a default. 28*7c478bd9Sstevel@tonic-gate ** owner -- create semaphores. 29*7c478bd9Sstevel@tonic-gate ** 30*7c478bd9Sstevel@tonic-gate ** Returns: 31*7c478bd9Sstevel@tonic-gate ** id for semaphores. 32*7c478bd9Sstevel@tonic-gate ** < 0 on failure. 33*7c478bd9Sstevel@tonic-gate */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate int 36*7c478bd9Sstevel@tonic-gate sm_sem_start(key, nsem, semflg, owner) 37*7c478bd9Sstevel@tonic-gate key_t key; 38*7c478bd9Sstevel@tonic-gate int nsem; 39*7c478bd9Sstevel@tonic-gate int semflg; 40*7c478bd9Sstevel@tonic-gate bool owner; 41*7c478bd9Sstevel@tonic-gate { 42*7c478bd9Sstevel@tonic-gate int semid, i; 43*7c478bd9Sstevel@tonic-gate unsigned short *semvals; 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate semvals = NULL; 46*7c478bd9Sstevel@tonic-gate if (semflg == 0) 47*7c478bd9Sstevel@tonic-gate semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3); 48*7c478bd9Sstevel@tonic-gate if (owner) 49*7c478bd9Sstevel@tonic-gate semflg |= IPC_CREAT|IPC_EXCL; 50*7c478bd9Sstevel@tonic-gate semid = semget(key, nsem, semflg); 51*7c478bd9Sstevel@tonic-gate if (semid < 0) 52*7c478bd9Sstevel@tonic-gate goto error; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate if (owner) 55*7c478bd9Sstevel@tonic-gate { 56*7c478bd9Sstevel@tonic-gate union semun semarg; 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals); 59*7c478bd9Sstevel@tonic-gate if (semvals == NULL) 60*7c478bd9Sstevel@tonic-gate goto error; 61*7c478bd9Sstevel@tonic-gate semarg.array = semvals; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* initialize semaphore values to be available */ 64*7c478bd9Sstevel@tonic-gate for (i = 0; i < nsem; i++) 65*7c478bd9Sstevel@tonic-gate semvals[i] = 1; 66*7c478bd9Sstevel@tonic-gate if (semctl(semid, 0, SETALL, semarg) < 0) 67*7c478bd9Sstevel@tonic-gate goto error; 68*7c478bd9Sstevel@tonic-gate } 69*7c478bd9Sstevel@tonic-gate return semid; 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate error: 72*7c478bd9Sstevel@tonic-gate if (semvals != NULL) 73*7c478bd9Sstevel@tonic-gate sm_free(semvals); 74*7c478bd9Sstevel@tonic-gate if (semid >= 0) 75*7c478bd9Sstevel@tonic-gate sm_sem_stop(semid); 76*7c478bd9Sstevel@tonic-gate return -1; 77*7c478bd9Sstevel@tonic-gate } 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* 80*7c478bd9Sstevel@tonic-gate ** SM_SEM_STOP -- stop using semaphores. 81*7c478bd9Sstevel@tonic-gate ** 82*7c478bd9Sstevel@tonic-gate ** Parameters: 83*7c478bd9Sstevel@tonic-gate ** semid -- id for semaphores. 84*7c478bd9Sstevel@tonic-gate ** 85*7c478bd9Sstevel@tonic-gate ** Returns: 86*7c478bd9Sstevel@tonic-gate ** 0 on success. 87*7c478bd9Sstevel@tonic-gate ** < 0 on failure. 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate int 91*7c478bd9Sstevel@tonic-gate sm_sem_stop(semid) 92*7c478bd9Sstevel@tonic-gate int semid; 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate return semctl(semid, 0, IPC_RMID, NULL); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate /* 98*7c478bd9Sstevel@tonic-gate ** SM_SEM_ACQ -- acquire semaphore. 99*7c478bd9Sstevel@tonic-gate ** 100*7c478bd9Sstevel@tonic-gate ** Parameters: 101*7c478bd9Sstevel@tonic-gate ** semid -- id for semaphores. 102*7c478bd9Sstevel@tonic-gate ** semnum -- number of semaphore. 103*7c478bd9Sstevel@tonic-gate ** timeout -- how long to wait for operation to succeed. 104*7c478bd9Sstevel@tonic-gate ** 105*7c478bd9Sstevel@tonic-gate ** Returns: 106*7c478bd9Sstevel@tonic-gate ** 0 on success. 107*7c478bd9Sstevel@tonic-gate ** < 0 on failure. 108*7c478bd9Sstevel@tonic-gate */ 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate int 111*7c478bd9Sstevel@tonic-gate sm_sem_acq(semid, semnum, timeout) 112*7c478bd9Sstevel@tonic-gate int semid; 113*7c478bd9Sstevel@tonic-gate int semnum; 114*7c478bd9Sstevel@tonic-gate int timeout; 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate int r; 117*7c478bd9Sstevel@tonic-gate struct sembuf semops[1]; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate semops[0].sem_num = semnum; 120*7c478bd9Sstevel@tonic-gate semops[0].sem_op = -1; 121*7c478bd9Sstevel@tonic-gate semops[0].sem_flg = SEM_UNDO | 122*7c478bd9Sstevel@tonic-gate (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 123*7c478bd9Sstevel@tonic-gate if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 124*7c478bd9Sstevel@tonic-gate return semop(semid, semops, 1); 125*7c478bd9Sstevel@tonic-gate do 126*7c478bd9Sstevel@tonic-gate { 127*7c478bd9Sstevel@tonic-gate r = semop(semid, semops, 1); 128*7c478bd9Sstevel@tonic-gate if (r == 0) 129*7c478bd9Sstevel@tonic-gate return r; 130*7c478bd9Sstevel@tonic-gate sleep(1); 131*7c478bd9Sstevel@tonic-gate --timeout; 132*7c478bd9Sstevel@tonic-gate } while (timeout > 0); 133*7c478bd9Sstevel@tonic-gate return r; 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate ** SM_SEM_REL -- release semaphore. 138*7c478bd9Sstevel@tonic-gate ** 139*7c478bd9Sstevel@tonic-gate ** Parameters: 140*7c478bd9Sstevel@tonic-gate ** semid -- id for semaphores. 141*7c478bd9Sstevel@tonic-gate ** semnum -- number of semaphore. 142*7c478bd9Sstevel@tonic-gate ** timeout -- how long to wait for operation to succeed. 143*7c478bd9Sstevel@tonic-gate ** 144*7c478bd9Sstevel@tonic-gate ** Returns: 145*7c478bd9Sstevel@tonic-gate ** 0 on success. 146*7c478bd9Sstevel@tonic-gate ** < 0 on failure. 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate int 150*7c478bd9Sstevel@tonic-gate sm_sem_rel(semid, semnum, timeout) 151*7c478bd9Sstevel@tonic-gate int semid; 152*7c478bd9Sstevel@tonic-gate int semnum; 153*7c478bd9Sstevel@tonic-gate int timeout; 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate int r; 156*7c478bd9Sstevel@tonic-gate struct sembuf semops[1]; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate #if PARANOID 159*7c478bd9Sstevel@tonic-gate /* XXX should we check whether the value is already 0 ? */ 160*7c478bd9Sstevel@tonic-gate SM_REQUIRE(sm_get_sem(semid, semnum) > 0); 161*7c478bd9Sstevel@tonic-gate #endif /* PARANOID */ 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate semops[0].sem_num = semnum; 164*7c478bd9Sstevel@tonic-gate semops[0].sem_op = 1; 165*7c478bd9Sstevel@tonic-gate semops[0].sem_flg = SEM_UNDO | 166*7c478bd9Sstevel@tonic-gate (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 167*7c478bd9Sstevel@tonic-gate if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 168*7c478bd9Sstevel@tonic-gate return semop(semid, semops, 1); 169*7c478bd9Sstevel@tonic-gate do 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate r = semop(semid, semops, 1); 172*7c478bd9Sstevel@tonic-gate if (r == 0) 173*7c478bd9Sstevel@tonic-gate return r; 174*7c478bd9Sstevel@tonic-gate sleep(1); 175*7c478bd9Sstevel@tonic-gate --timeout; 176*7c478bd9Sstevel@tonic-gate } while (timeout > 0); 177*7c478bd9Sstevel@tonic-gate return r; 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate ** SM_SEM_GET -- get semaphore value. 182*7c478bd9Sstevel@tonic-gate ** 183*7c478bd9Sstevel@tonic-gate ** Parameters: 184*7c478bd9Sstevel@tonic-gate ** semid -- id for semaphores. 185*7c478bd9Sstevel@tonic-gate ** semnum -- number of semaphore. 186*7c478bd9Sstevel@tonic-gate ** 187*7c478bd9Sstevel@tonic-gate ** Returns: 188*7c478bd9Sstevel@tonic-gate ** value of semaphore on success. 189*7c478bd9Sstevel@tonic-gate ** < 0 on failure. 190*7c478bd9Sstevel@tonic-gate */ 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate int 193*7c478bd9Sstevel@tonic-gate sm_sem_get(semid, semnum) 194*7c478bd9Sstevel@tonic-gate int semid; 195*7c478bd9Sstevel@tonic-gate int semnum; 196*7c478bd9Sstevel@tonic-gate { 197*7c478bd9Sstevel@tonic-gate int semval; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0) 200*7c478bd9Sstevel@tonic-gate return -1; 201*7c478bd9Sstevel@tonic-gate return semval; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SEM */ 204