xref: /freebsd/contrib/sendmail/libsm/sem.c (revision 4e4196cb7454f47341efebe4e0a17f1b8cd534c7)
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