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