|
|
1.1 root 1: /*
2: * $Id: xpsem.c,v 1.12 2005/10/21 21:44:23 deuce Exp $
3: *
4: * Copyright (C) 2000 Jason Evans <[email protected]>.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice(s), this list of conditions and the following disclaimer as
12: * the first lines of this file unmodified other than the possible
13: * addition of one or more copyright notices.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice(s), this list of conditions and the following disclaimer in
16: * the documentation and/or other materials provided with the
17: * distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
20: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
23: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: *
31: * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.3.2.1 2000/07/18 02:05:57 jasone Exp $
32: */
33:
34: #include <errno.h>
35: #include "xpsem.h"
36: #include <pthread.h>
37: #include <sys/time.h>
38: #include <stdlib.h>
39: #include "gen_defs.h"
40: #include "genwrap.h"
41:
42: int
43: xp_sem_init(xp_sem_t *sem, int pshared, unsigned int value)
44: {
45: int retval;
46:
47: /*
48: * Range check the arguments.
49: */
50: if (pshared != 0) {
51: /*
52: * The user wants a semaphore that can be shared among
53: * processes, which this implementation can't do. Sounds like a
54: * permissions problem to me (yeah right).
55: */
56: errno = EPERM;
57: retval = -1;
58: goto RETURN;
59: }
60:
61: if (value > XP_SEM_VALUE_MAX) {
62: errno = EINVAL;
63: retval = -1;
64: goto RETURN;
65: }
66:
67: *sem = (xp_sem_t)malloc(sizeof(struct xp_sem));
68: if (*sem == NULL) {
69: errno = ENOSPC;
70: retval = -1;
71: goto RETURN;
72: }
73:
74: /*
75: * Initialize the semaphore.
76: */
77: if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
78: free(*sem);
79: errno = ENOSPC;
80: retval = -1;
81: goto RETURN;
82: }
83:
84: if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
85: while(pthread_mutex_destroy(&(*sem)->lock)==EBUSY)
86: SLEEP(1);
87: free(*sem);
88: errno = ENOSPC;
89: retval = -1;
90: goto RETURN;
91: }
92:
93: (*sem)->count = (u_int32_t)value;
94: (*sem)->nwaiters = 0;
95: (*sem)->magic = XP_SEM_MAGIC;
96:
97: retval = 0;
98: RETURN:
99: return retval;
100: }
101:
102: int
103: xp_sem_destroy(xp_sem_t *sem)
104: {
105: int retval;
106:
107: _SEM_CHECK_VALIDITY(sem);
108:
109: /* Make sure there are no waiters. */
110: pthread_mutex_lock(&(*sem)->lock);
111: if ((*sem)->nwaiters > 0) {
112: pthread_mutex_unlock(&(*sem)->lock);
113: errno = EBUSY;
114: retval = -1;
115: goto RETURN;
116: }
117: pthread_mutex_unlock(&(*sem)->lock);
118:
119: while(pthread_mutex_destroy(&(*sem)->lock)==EBUSY)
120: SLEEP(1);
121: while(pthread_cond_destroy(&(*sem)->gtzero)==EBUSY)
122: SLEEP(1);
123: (*sem)->magic = 0;
124:
125: free(*sem);
126:
127: retval = 0;
128: RETURN:
129: return retval;
130: }
131:
132: xp_sem_t *
133: xp_sem_open(const char *name, int oflag, ...)
134: {
135: errno = ENOSYS;
136: return XP_SEM_FAILED;
137: }
138:
139: int
140: xp_sem_close(xp_sem_t *sem)
141: {
142: errno = ENOSYS;
143: return -1;
144: }
145:
146: int
147: xp_sem_unlink(const char *name)
148: {
149: errno = ENOSYS;
150: return -1;
151: }
152:
153: int
154: xp_sem_wait(xp_sem_t *sem)
155: {
156: int retval;
157:
158: _SEM_CHECK_VALIDITY(sem);
159:
160: pthread_mutex_lock(&(*sem)->lock);
161:
162: while ((*sem)->count == 0) {
163: (*sem)->nwaiters++;
164: pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
165: (*sem)->nwaiters--;
166: }
167: (*sem)->count--;
168:
169: pthread_mutex_unlock(&(*sem)->lock);
170:
171: retval = 0;
172: RETURN:
173:
174: return retval;
175: }
176:
177: int
178: xp_sem_trywait(xp_sem_t *sem)
179: {
180: int retval;
181:
182: _SEM_CHECK_VALIDITY(sem);
183:
184: pthread_mutex_lock(&(*sem)->lock);
185:
186: if ((*sem)->count > 0) {
187: (*sem)->count--;
188: retval = 0;
189: } else {
190: errno = EAGAIN;
191: retval = -1;
192: }
193:
194: pthread_mutex_unlock(&(*sem)->lock);
195:
196: RETURN:
197: return retval;
198: }
199:
200: int
201: xp_sem_post(xp_sem_t *sem)
202: {
203: int retval;
204:
205: _SEM_CHECK_VALIDITY(sem);
206:
207: pthread_mutex_lock(&(*sem)->lock);
208:
209: (*sem)->count++;
210: if ((*sem)->nwaiters > 0) {
211: /*
212: * We must use pthread_cond_broadcast() rather than
213: * pthread_cond_signal() in order to assure that the highest
214: * priority thread is run by the scheduler, since
215: * pthread_cond_signal() signals waiting threads in FIFO order.
216: */
217: pthread_cond_broadcast(&(*sem)->gtzero);
218: }
219:
220: pthread_mutex_unlock(&(*sem)->lock);
221:
222: retval = 0;
223: RETURN:
224: return retval;
225: }
226:
227: int
228: xp_sem_getvalue(xp_sem_t *sem, int *sval)
229: {
230: int retval;
231:
232: _SEM_CHECK_VALIDITY(sem);
233:
234: pthread_mutex_lock(&(*sem)->lock);
235: *sval = (int)(*sem)->count;
236: pthread_mutex_unlock(&(*sem)->lock);
237:
238: retval = 0;
239: RETURN:
240: return retval;
241: }
242:
243: int
244: xp_sem_setvalue(xp_sem_t *sem, int sval)
245: {
246: int retval;
247:
248: _SEM_CHECK_VALIDITY(sem);
249:
250: pthread_mutex_lock(&(*sem)->lock);
251: (*sem)->count=(u_int32_t)sval;
252: if (((*sem)->nwaiters > 0) && sval) {
253: /*
254: * We must use pthread_cond_broadcast() rather than
255: * pthread_cond_signal() in order to assure that the highest
256: * priority thread is run by the scheduler, since
257: * pthread_cond_signal() signals waiting threads in FIFO order.
258: */
259: pthread_cond_broadcast(&(*sem)->gtzero);
260: }
261: pthread_mutex_unlock(&(*sem)->lock);
262:
263: retval = 0;
264: RETURN:
265: return retval;
266: }
267:
268: int
269: xp_sem_timedwait(xp_sem_t *sem, const struct timespec *abs_timeout)
270: {
271: int retval=0;
272:
273: _SEM_CHECK_VALIDITY(sem);
274:
275: pthread_mutex_lock(&(*sem)->lock);
276:
277: while ((*sem)->count == 0) {
278: (*sem)->nwaiters++;
279: retval=pthread_cond_timedwait(&(*sem)->gtzero, &(*sem)->lock, abs_timeout);
280: (*sem)->nwaiters--;
281: if(retval) {
282: errno=retval;
283: retval=-1;
284: break;
285: }
286: }
287: if(retval==0)
288: (*sem)->count--;
289:
290: pthread_mutex_unlock(&(*sem)->lock);
291:
292: RETURN:
293:
294: return retval;
295: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.