1*03831d35Sstevel /*
2*03831d35Sstevel  * CDDL HEADER START
3*03831d35Sstevel  *
4*03831d35Sstevel  * The contents of this file are subject to the terms of the
5*03831d35Sstevel  * Common Development and Distribution License, Version 1.0 only
6*03831d35Sstevel  * (the "License").  You may not use this file except in compliance
7*03831d35Sstevel  * with the License.
8*03831d35Sstevel  *
9*03831d35Sstevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*03831d35Sstevel  * or http://www.opensolaris.org/os/licensing.
11*03831d35Sstevel  * See the License for the specific language governing permissions
12*03831d35Sstevel  * and limitations under the License.
13*03831d35Sstevel  *
14*03831d35Sstevel  * When distributing Covered Code, include this CDDL HEADER in each
15*03831d35Sstevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*03831d35Sstevel  * If applicable, add the following below this CDDL HEADER, with the
17*03831d35Sstevel  * fields enclosed by brackets "[]" replaced with your own identifying
18*03831d35Sstevel  * information: Portions Copyright [yyyy] [name of copyright owner]
19*03831d35Sstevel  *
20*03831d35Sstevel  * CDDL HEADER END
21*03831d35Sstevel  */
22*03831d35Sstevel /*
23*03831d35Sstevel  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24*03831d35Sstevel  * Use is subject to license terms.
25*03831d35Sstevel  */
26*03831d35Sstevel 
27*03831d35Sstevel /*
28*03831d35Sstevel  * xsem.c: to provide a semaphore system (used by the smq routines)
29*03831d35Sstevel  *
30*03831d35Sstevel  * these routines come from the libxposix library.
31*03831d35Sstevel  */
32*03831d35Sstevel 
33*03831d35Sstevel #include <pthread.h>
34*03831d35Sstevel #include <time.h>
35*03831d35Sstevel 
36*03831d35Sstevel #include "xsem.h"
37*03831d35Sstevel 
38*03831d35Sstevel 
39*03831d35Sstevel int
xsem_init(xsem_t * sem,int pshared,unsigned int value)40*03831d35Sstevel xsem_init(xsem_t *sem, int pshared, unsigned int value)
41*03831d35Sstevel {
42*03831d35Sstevel 	if (pshared != 0)
43*03831d35Sstevel 		return (-1);
44*03831d35Sstevel 
45*03831d35Sstevel 	pthread_mutex_init(&sem->semMutex, NULL);
46*03831d35Sstevel 	pthread_cond_init(&sem->semCV, NULL);
47*03831d35Sstevel 	sem->semaphore = value;
48*03831d35Sstevel 
49*03831d35Sstevel 	return (0);
50*03831d35Sstevel }
51*03831d35Sstevel 
52*03831d35Sstevel void
xsem_destroy(xsem_t * sem)53*03831d35Sstevel xsem_destroy(xsem_t *sem)
54*03831d35Sstevel {
55*03831d35Sstevel 	pthread_mutex_destroy(&sem->semMutex);
56*03831d35Sstevel 	pthread_cond_destroy(&sem->semCV);
57*03831d35Sstevel 	sem->semaphore = 0;
58*03831d35Sstevel }
59*03831d35Sstevel 
60*03831d35Sstevel int
xsem_wait(xsem_t * sem)61*03831d35Sstevel xsem_wait(xsem_t *sem)
62*03831d35Sstevel {
63*03831d35Sstevel 	pthread_mutex_lock(&sem->semMutex);
64*03831d35Sstevel 
65*03831d35Sstevel 	if (sem->semaphore < 0) {
66*03831d35Sstevel 		sem->semaphore = 0;
67*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
68*03831d35Sstevel 		return (XSEM_ERROR);
69*03831d35Sstevel 	}
70*03831d35Sstevel 
71*03831d35Sstevel 	if (sem->semaphore > 0) {
72*03831d35Sstevel 		sem->semaphore--;
73*03831d35Sstevel 	} else {
74*03831d35Sstevel 		while (sem->semaphore == 0)
75*03831d35Sstevel 			pthread_cond_wait(&sem->semCV, &sem->semMutex);
76*03831d35Sstevel 
77*03831d35Sstevel 		if (sem->semaphore != 0) {
78*03831d35Sstevel 			sem->semaphore--;
79*03831d35Sstevel 		} else {
80*03831d35Sstevel 			pthread_mutex_unlock(&sem->semMutex);
81*03831d35Sstevel 			return (XSEM_ERROR);
82*03831d35Sstevel 		}
83*03831d35Sstevel 	}
84*03831d35Sstevel 
85*03831d35Sstevel 	pthread_mutex_unlock(&sem->semMutex);
86*03831d35Sstevel 	return (0);
87*03831d35Sstevel }
88*03831d35Sstevel 
89*03831d35Sstevel 
90*03831d35Sstevel int
xsem_trywait(xsem_t * sem)91*03831d35Sstevel xsem_trywait(xsem_t *sem)
92*03831d35Sstevel {
93*03831d35Sstevel 	pthread_mutex_lock(&sem->semMutex);
94*03831d35Sstevel 
95*03831d35Sstevel 	if (sem->semaphore < 0) {
96*03831d35Sstevel 		sem->semaphore = 0;
97*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
98*03831d35Sstevel 		return (XSEM_ERROR);
99*03831d35Sstevel 	}
100*03831d35Sstevel 
101*03831d35Sstevel 	if (sem->semaphore == 0) {
102*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
103*03831d35Sstevel 		return (XSEM_EBUSY);
104*03831d35Sstevel 	} else {
105*03831d35Sstevel 		sem->semaphore--;
106*03831d35Sstevel 	}
107*03831d35Sstevel 
108*03831d35Sstevel 	pthread_mutex_unlock(&sem->semMutex);
109*03831d35Sstevel 	return (0);
110*03831d35Sstevel }
111*03831d35Sstevel 
112*03831d35Sstevel 
113*03831d35Sstevel int
xsem_post(xsem_t * sem)114*03831d35Sstevel xsem_post(xsem_t *sem)
115*03831d35Sstevel {
116*03831d35Sstevel 	pthread_mutex_lock(&sem->semMutex);
117*03831d35Sstevel 	sem->semaphore++;
118*03831d35Sstevel 	pthread_cond_signal(&sem->semCV);
119*03831d35Sstevel 	pthread_mutex_unlock(&sem->semMutex);
120*03831d35Sstevel 
121*03831d35Sstevel 	return (0);
122*03831d35Sstevel }
123*03831d35Sstevel 
124*03831d35Sstevel 
125*03831d35Sstevel void
xsem_getvalue(xsem_t * sem,int * sval)126*03831d35Sstevel xsem_getvalue(xsem_t *sem, int *sval)
127*03831d35Sstevel {
128*03831d35Sstevel 	*sval = sem->semaphore;
129*03831d35Sstevel }
130*03831d35Sstevel 
131*03831d35Sstevel 
132*03831d35Sstevel 
133*03831d35Sstevel int
xsem_xwait(xsem_t * sem,int timeout,timestruc_t * mytime)134*03831d35Sstevel xsem_xwait(xsem_t *sem, int timeout, timestruc_t *mytime)
135*03831d35Sstevel {
136*03831d35Sstevel 	int		status;
137*03831d35Sstevel 	timestruc_t	delay;
138*03831d35Sstevel 
139*03831d35Sstevel 	if (timeout == 0)
140*03831d35Sstevel 		return (xsem_wait(sem));
141*03831d35Sstevel 	else {
142*03831d35Sstevel 		pthread_mutex_lock(&sem->semMutex);
143*03831d35Sstevel 
144*03831d35Sstevel 		if (sem->semaphore < 0) {
145*03831d35Sstevel 			sem->semaphore = 0;
146*03831d35Sstevel 			pthread_mutex_unlock(&sem->semMutex);
147*03831d35Sstevel 			return (XSEM_ERROR);
148*03831d35Sstevel 		}
149*03831d35Sstevel 
150*03831d35Sstevel 		if (sem->semaphore > 0) {
151*03831d35Sstevel 			sem->semaphore--;
152*03831d35Sstevel 		} else {
153*03831d35Sstevel 			status = 0;
154*03831d35Sstevel 
155*03831d35Sstevel 			delay  = *mytime;
156*03831d35Sstevel 			delay.tv_sec = delay.tv_sec + time(NULL);
157*03831d35Sstevel 			while ((sem->semaphore == 0) && (status == 0)) {
158*03831d35Sstevel 				status = pthread_cond_timedwait(&sem->semCV,
159*03831d35Sstevel 				    &sem->semMutex, &delay);
160*03831d35Sstevel 			}
161*03831d35Sstevel 
162*03831d35Sstevel 			/*
163*03831d35Sstevel 			 * Check one more time in case thread didn't have a
164*03831d35Sstevel 			 * chance to check before timeout ??? TBD
165*03831d35Sstevel 			 */
166*03831d35Sstevel 
167*03831d35Sstevel 			if (status != 0) {
168*03831d35Sstevel 				pthread_mutex_unlock(&sem->semMutex);
169*03831d35Sstevel 				return (XSEM_ETIME);
170*03831d35Sstevel 			} else if (sem->semaphore != 0) {
171*03831d35Sstevel 				sem->semaphore--;
172*03831d35Sstevel 			} else {
173*03831d35Sstevel 				pthread_mutex_unlock(&sem->semMutex);
174*03831d35Sstevel 				return (XSEM_ERROR);
175*03831d35Sstevel 			}
176*03831d35Sstevel 		}
177*03831d35Sstevel 
178*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
179*03831d35Sstevel 	}
180*03831d35Sstevel 
181*03831d35Sstevel 	return (0);
182*03831d35Sstevel }
183