1147078Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2000-2001, 2005, 2008 Proofpoint, Inc. and its suppliers. 3147078Sgshapiro * All rights reserved. 4147078Sgshapiro * 5147078Sgshapiro * By using this file, you agree to the terms and conditions set 6147078Sgshapiro * forth in the LICENSE file which can be found at the top level of 7147078Sgshapiro * the sendmail distribution. 8147078Sgshapiro */ 9147078Sgshapiro 10147078Sgshapiro#include <sm/gen.h> 11266692SgshapiroSM_RCSID("@(#)$Id: sem.c,v 1.15 2013-11-22 20:51:43 ca Exp $") 12147078Sgshapiro 13147078Sgshapiro#if SM_CONF_SEM 14147078Sgshapiro# include <stdlib.h> 15147078Sgshapiro# include <unistd.h> 16203004Sgshapiro# include <sm/string.h> 17147078Sgshapiro# include <sm/sem.h> 18147078Sgshapiro# include <sm/heap.h> 19157001Sgshapiro# include <errno.h> 20147078Sgshapiro 21147078Sgshapiro/* 22147078Sgshapiro** SM_SEM_START -- initialize semaphores 23147078Sgshapiro** 24147078Sgshapiro** Parameters: 25147078Sgshapiro** key -- key for semaphores. 26147078Sgshapiro** nsem -- number of semaphores. 27147078Sgshapiro** semflg -- flag for semget(), if 0, use a default. 28147078Sgshapiro** owner -- create semaphores. 29147078Sgshapiro** 30147078Sgshapiro** Returns: 31147078Sgshapiro** id for semaphores. 32147078Sgshapiro** < 0 on failure. 33147078Sgshapiro*/ 34147078Sgshapiro 35147078Sgshapiroint 36147078Sgshapirosm_sem_start(key, nsem, semflg, owner) 37147078Sgshapiro key_t key; 38147078Sgshapiro int nsem; 39147078Sgshapiro int semflg; 40147078Sgshapiro bool owner; 41147078Sgshapiro{ 42157001Sgshapiro int semid, i, err; 43147078Sgshapiro unsigned short *semvals; 44147078Sgshapiro 45147078Sgshapiro semvals = NULL; 46147078Sgshapiro if (semflg == 0) 47147078Sgshapiro semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3); 48147078Sgshapiro if (owner) 49147078Sgshapiro semflg |= IPC_CREAT|IPC_EXCL; 50147078Sgshapiro semid = semget(key, nsem, semflg); 51147078Sgshapiro if (semid < 0) 52147078Sgshapiro goto error; 53147078Sgshapiro 54147078Sgshapiro if (owner) 55147078Sgshapiro { 56147078Sgshapiro union semun semarg; 57147078Sgshapiro 58147078Sgshapiro semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals); 59147078Sgshapiro if (semvals == NULL) 60147078Sgshapiro goto error; 61147078Sgshapiro semarg.array = semvals; 62147078Sgshapiro 63147078Sgshapiro /* initialize semaphore values to be available */ 64147078Sgshapiro for (i = 0; i < nsem; i++) 65147078Sgshapiro semvals[i] = 1; 66147078Sgshapiro if (semctl(semid, 0, SETALL, semarg) < 0) 67147078Sgshapiro goto error; 68147078Sgshapiro } 69147078Sgshapiro return semid; 70147078Sgshapiro 71147078Sgshapiroerror: 72157001Sgshapiro err = errno; 73147078Sgshapiro if (semvals != NULL) 74147078Sgshapiro sm_free(semvals); 75147078Sgshapiro if (semid >= 0) 76147078Sgshapiro sm_sem_stop(semid); 77157001Sgshapiro return (err > 0) ? (0 - err) : -1; 78147078Sgshapiro} 79147078Sgshapiro 80147078Sgshapiro/* 81147078Sgshapiro** SM_SEM_STOP -- stop using semaphores. 82147078Sgshapiro** 83147078Sgshapiro** Parameters: 84147078Sgshapiro** semid -- id for semaphores. 85147078Sgshapiro** 86147078Sgshapiro** Returns: 87147078Sgshapiro** 0 on success. 88147078Sgshapiro** < 0 on failure. 89147078Sgshapiro*/ 90147078Sgshapiro 91147078Sgshapiroint 92147078Sgshapirosm_sem_stop(semid) 93147078Sgshapiro int semid; 94147078Sgshapiro{ 95147078Sgshapiro return semctl(semid, 0, IPC_RMID, NULL); 96147078Sgshapiro} 97147078Sgshapiro 98147078Sgshapiro/* 99147078Sgshapiro** SM_SEM_ACQ -- acquire semaphore. 100147078Sgshapiro** 101147078Sgshapiro** Parameters: 102147078Sgshapiro** semid -- id for semaphores. 103147078Sgshapiro** semnum -- number of semaphore. 104147078Sgshapiro** timeout -- how long to wait for operation to succeed. 105147078Sgshapiro** 106147078Sgshapiro** Returns: 107147078Sgshapiro** 0 on success. 108147078Sgshapiro** < 0 on failure. 109147078Sgshapiro*/ 110147078Sgshapiro 111147078Sgshapiroint 112147078Sgshapirosm_sem_acq(semid, semnum, timeout) 113147078Sgshapiro int semid; 114147078Sgshapiro int semnum; 115147078Sgshapiro int timeout; 116147078Sgshapiro{ 117147078Sgshapiro int r; 118147078Sgshapiro struct sembuf semops[1]; 119147078Sgshapiro 120147078Sgshapiro semops[0].sem_num = semnum; 121147078Sgshapiro semops[0].sem_op = -1; 122147078Sgshapiro semops[0].sem_flg = SEM_UNDO | 123147078Sgshapiro (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 124147078Sgshapiro if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 125147078Sgshapiro return semop(semid, semops, 1); 126147078Sgshapiro do 127147078Sgshapiro { 128147078Sgshapiro r = semop(semid, semops, 1); 129147078Sgshapiro if (r == 0) 130147078Sgshapiro return r; 131147078Sgshapiro sleep(1); 132147078Sgshapiro --timeout; 133147078Sgshapiro } while (timeout > 0); 134147078Sgshapiro return r; 135147078Sgshapiro} 136147078Sgshapiro 137147078Sgshapiro/* 138147078Sgshapiro** SM_SEM_REL -- release semaphore. 139147078Sgshapiro** 140147078Sgshapiro** Parameters: 141147078Sgshapiro** semid -- id for semaphores. 142147078Sgshapiro** semnum -- number of semaphore. 143147078Sgshapiro** timeout -- how long to wait for operation to succeed. 144147078Sgshapiro** 145147078Sgshapiro** Returns: 146147078Sgshapiro** 0 on success. 147147078Sgshapiro** < 0 on failure. 148147078Sgshapiro*/ 149147078Sgshapiro 150147078Sgshapiroint 151147078Sgshapirosm_sem_rel(semid, semnum, timeout) 152147078Sgshapiro int semid; 153147078Sgshapiro int semnum; 154147078Sgshapiro int timeout; 155147078Sgshapiro{ 156147078Sgshapiro int r; 157147078Sgshapiro struct sembuf semops[1]; 158147078Sgshapiro 159147078Sgshapiro#if PARANOID 160147078Sgshapiro /* XXX should we check whether the value is already 0 ? */ 161147078Sgshapiro SM_REQUIRE(sm_get_sem(semid, semnum) > 0); 162147078Sgshapiro#endif /* PARANOID */ 163147078Sgshapiro 164147078Sgshapiro semops[0].sem_num = semnum; 165147078Sgshapiro semops[0].sem_op = 1; 166147078Sgshapiro semops[0].sem_flg = SEM_UNDO | 167147078Sgshapiro (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT); 168147078Sgshapiro if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER) 169147078Sgshapiro return semop(semid, semops, 1); 170147078Sgshapiro do 171147078Sgshapiro { 172147078Sgshapiro r = semop(semid, semops, 1); 173147078Sgshapiro if (r == 0) 174147078Sgshapiro return r; 175147078Sgshapiro sleep(1); 176147078Sgshapiro --timeout; 177147078Sgshapiro } while (timeout > 0); 178147078Sgshapiro return r; 179147078Sgshapiro} 180147078Sgshapiro 181147078Sgshapiro/* 182147078Sgshapiro** SM_SEM_GET -- get semaphore value. 183147078Sgshapiro** 184147078Sgshapiro** Parameters: 185147078Sgshapiro** semid -- id for semaphores. 186147078Sgshapiro** semnum -- number of semaphore. 187147078Sgshapiro** 188147078Sgshapiro** Returns: 189147078Sgshapiro** value of semaphore on success. 190147078Sgshapiro** < 0 on failure. 191147078Sgshapiro*/ 192147078Sgshapiro 193147078Sgshapiroint 194147078Sgshapirosm_sem_get(semid, semnum) 195147078Sgshapiro int semid; 196147078Sgshapiro int semnum; 197147078Sgshapiro{ 198147078Sgshapiro int semval; 199147078Sgshapiro 200147078Sgshapiro if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0) 201147078Sgshapiro return -1; 202147078Sgshapiro return semval; 203147078Sgshapiro} 204203004Sgshapiro 205203004Sgshapiro/* 206203004Sgshapiro** SM_SEMSETOWNER -- set owner/group/mode of semaphores. 207203004Sgshapiro** 208203004Sgshapiro** Parameters: 209203004Sgshapiro** semid -- id for semaphores. 210203004Sgshapiro** uid -- uid to use 211203004Sgshapiro** gid -- gid to use 212203004Sgshapiro** mode -- mode to use 213203004Sgshapiro** 214203004Sgshapiro** Returns: 215203004Sgshapiro** 0 on success. 216203004Sgshapiro** < 0 on failure. 217203004Sgshapiro*/ 218203004Sgshapiro 219203004Sgshapiroint 220203004Sgshapirosm_semsetowner(semid, uid, gid, mode) 221203004Sgshapiro int semid; 222203004Sgshapiro uid_t uid; 223203004Sgshapiro gid_t gid; 224203004Sgshapiro mode_t mode; 225203004Sgshapiro{ 226203004Sgshapiro int r; 227203004Sgshapiro struct semid_ds semidds; 228203004Sgshapiro union semun { 229203004Sgshapiro int val; 230203004Sgshapiro struct semid_ds *buf; 231203004Sgshapiro ushort *array; 232203004Sgshapiro } arg; 233203004Sgshapiro 234203004Sgshapiro memset(&semidds, 0, sizeof(semidds)); 235203004Sgshapiro arg.buf = &semidds; 236203004Sgshapiro if ((r = semctl(semid, 1, IPC_STAT, arg)) < 0) 237203004Sgshapiro return r; 238203004Sgshapiro semidds.sem_perm.uid = uid; 239203004Sgshapiro semidds.sem_perm.gid = gid; 240203004Sgshapiro semidds.sem_perm.mode = mode; 241203004Sgshapiro if ((r = semctl(semid, 1, IPC_SET, arg)) < 0) 242203004Sgshapiro return r; 243203004Sgshapiro return 0; 244203004Sgshapiro} 245147078Sgshapiro#endif /* SM_CONF_SEM */ 246