xref: /titanic_51/usr/src/cmd/scadm/sparc/mpxu/common/xsem.c (revision 03831d35f7499c87d51205817c93e9a8d42c4bae)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*03831d35Sstevel 
29*03831d35Sstevel /*
30*03831d35Sstevel  * xsem.c: to provide a semaphore system (used by the smq routines)
31*03831d35Sstevel  *
32*03831d35Sstevel  * these routines come from the libxposix library.
33*03831d35Sstevel  */
34*03831d35Sstevel 
35*03831d35Sstevel #include <pthread.h>
36*03831d35Sstevel #include <time.h>
37*03831d35Sstevel 
38*03831d35Sstevel #include "xsem.h"
39*03831d35Sstevel 
40*03831d35Sstevel 
41*03831d35Sstevel int
42*03831d35Sstevel xsem_init(xsem_t *sem, int pshared, unsigned int value)
43*03831d35Sstevel {
44*03831d35Sstevel 	if (pshared != 0)
45*03831d35Sstevel 		return (-1);
46*03831d35Sstevel 
47*03831d35Sstevel 	pthread_mutex_init(&sem->semMutex, NULL);
48*03831d35Sstevel 	pthread_cond_init(&sem->semCV, NULL);
49*03831d35Sstevel 	sem->semaphore = value;
50*03831d35Sstevel 
51*03831d35Sstevel 	return (0);
52*03831d35Sstevel }
53*03831d35Sstevel 
54*03831d35Sstevel void
55*03831d35Sstevel xsem_destroy(xsem_t *sem)
56*03831d35Sstevel {
57*03831d35Sstevel 	pthread_mutex_destroy(&sem->semMutex);
58*03831d35Sstevel 	pthread_cond_destroy(&sem->semCV);
59*03831d35Sstevel 	sem->semaphore = 0;
60*03831d35Sstevel }
61*03831d35Sstevel 
62*03831d35Sstevel int
63*03831d35Sstevel xsem_wait(xsem_t *sem)
64*03831d35Sstevel {
65*03831d35Sstevel 	pthread_mutex_lock(&sem->semMutex);
66*03831d35Sstevel 
67*03831d35Sstevel 	if (sem->semaphore < 0) {
68*03831d35Sstevel 		sem->semaphore = 0;
69*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
70*03831d35Sstevel 		return (XSEM_ERROR);
71*03831d35Sstevel 	}
72*03831d35Sstevel 
73*03831d35Sstevel 	if (sem->semaphore > 0) {
74*03831d35Sstevel 		sem->semaphore--;
75*03831d35Sstevel 	} else {
76*03831d35Sstevel 		while (sem->semaphore == 0)
77*03831d35Sstevel 			pthread_cond_wait(&sem->semCV, &sem->semMutex);
78*03831d35Sstevel 
79*03831d35Sstevel 		if (sem->semaphore != 0) {
80*03831d35Sstevel 			sem->semaphore--;
81*03831d35Sstevel 		} else {
82*03831d35Sstevel 			pthread_mutex_unlock(&sem->semMutex);
83*03831d35Sstevel 			return (XSEM_ERROR);
84*03831d35Sstevel 		}
85*03831d35Sstevel 	}
86*03831d35Sstevel 
87*03831d35Sstevel 	pthread_mutex_unlock(&sem->semMutex);
88*03831d35Sstevel 	return (0);
89*03831d35Sstevel }
90*03831d35Sstevel 
91*03831d35Sstevel 
92*03831d35Sstevel int
93*03831d35Sstevel xsem_trywait(xsem_t *sem)
94*03831d35Sstevel {
95*03831d35Sstevel 	pthread_mutex_lock(&sem->semMutex);
96*03831d35Sstevel 
97*03831d35Sstevel 	if (sem->semaphore < 0) {
98*03831d35Sstevel 		sem->semaphore = 0;
99*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
100*03831d35Sstevel 		return (XSEM_ERROR);
101*03831d35Sstevel 	}
102*03831d35Sstevel 
103*03831d35Sstevel 	if (sem->semaphore == 0) {
104*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
105*03831d35Sstevel 		return (XSEM_EBUSY);
106*03831d35Sstevel 	} else {
107*03831d35Sstevel 		sem->semaphore--;
108*03831d35Sstevel 	}
109*03831d35Sstevel 
110*03831d35Sstevel 	pthread_mutex_unlock(&sem->semMutex);
111*03831d35Sstevel 	return (0);
112*03831d35Sstevel }
113*03831d35Sstevel 
114*03831d35Sstevel 
115*03831d35Sstevel int
116*03831d35Sstevel xsem_post(xsem_t *sem)
117*03831d35Sstevel {
118*03831d35Sstevel 	pthread_mutex_lock(&sem->semMutex);
119*03831d35Sstevel 	sem->semaphore++;
120*03831d35Sstevel 	pthread_cond_signal(&sem->semCV);
121*03831d35Sstevel 	pthread_mutex_unlock(&sem->semMutex);
122*03831d35Sstevel 
123*03831d35Sstevel 	return (0);
124*03831d35Sstevel }
125*03831d35Sstevel 
126*03831d35Sstevel 
127*03831d35Sstevel void
128*03831d35Sstevel xsem_getvalue(xsem_t *sem, int *sval)
129*03831d35Sstevel {
130*03831d35Sstevel 	*sval = sem->semaphore;
131*03831d35Sstevel }
132*03831d35Sstevel 
133*03831d35Sstevel 
134*03831d35Sstevel 
135*03831d35Sstevel int
136*03831d35Sstevel xsem_xwait(xsem_t *sem, int timeout, timestruc_t *mytime)
137*03831d35Sstevel {
138*03831d35Sstevel 	int		status;
139*03831d35Sstevel 	timestruc_t	delay;
140*03831d35Sstevel 
141*03831d35Sstevel 	if (timeout == 0)
142*03831d35Sstevel 		return (xsem_wait(sem));
143*03831d35Sstevel 	else {
144*03831d35Sstevel 		pthread_mutex_lock(&sem->semMutex);
145*03831d35Sstevel 
146*03831d35Sstevel 		if (sem->semaphore < 0) {
147*03831d35Sstevel 			sem->semaphore = 0;
148*03831d35Sstevel 			pthread_mutex_unlock(&sem->semMutex);
149*03831d35Sstevel 			return (XSEM_ERROR);
150*03831d35Sstevel 		}
151*03831d35Sstevel 
152*03831d35Sstevel 		if (sem->semaphore > 0) {
153*03831d35Sstevel 			sem->semaphore--;
154*03831d35Sstevel 		} else {
155*03831d35Sstevel 			status = 0;
156*03831d35Sstevel 
157*03831d35Sstevel 			delay  = *mytime;
158*03831d35Sstevel 			delay.tv_sec = delay.tv_sec + time(NULL);
159*03831d35Sstevel 			while ((sem->semaphore == 0) && (status == 0)) {
160*03831d35Sstevel 				status = pthread_cond_timedwait(&sem->semCV,
161*03831d35Sstevel 				    &sem->semMutex, &delay);
162*03831d35Sstevel 			}
163*03831d35Sstevel 
164*03831d35Sstevel 			/*
165*03831d35Sstevel 			 * Check one more time in case thread didn't have a
166*03831d35Sstevel 			 * chance to check before timeout ??? TBD
167*03831d35Sstevel 			 */
168*03831d35Sstevel 
169*03831d35Sstevel 			if (status != 0) {
170*03831d35Sstevel 				pthread_mutex_unlock(&sem->semMutex);
171*03831d35Sstevel 				return (XSEM_ETIME);
172*03831d35Sstevel 			} else if (sem->semaphore != 0) {
173*03831d35Sstevel 				sem->semaphore--;
174*03831d35Sstevel 			} else {
175*03831d35Sstevel 				pthread_mutex_unlock(&sem->semMutex);
176*03831d35Sstevel 				return (XSEM_ERROR);
177*03831d35Sstevel 			}
178*03831d35Sstevel 		}
179*03831d35Sstevel 
180*03831d35Sstevel 		pthread_mutex_unlock(&sem->semMutex);
181*03831d35Sstevel 	}
182*03831d35Sstevel 
183*03831d35Sstevel 	return (0);
184*03831d35Sstevel }
185