|
|
1.1 root 1: /*
2: * $Id: xpsem.c,v 1.6 2003/05/08 18:17:49 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:
40: int
41: xp_sem_init(xp_sem_t *sem, int pshared, unsigned int value)
42: {
43: int retval;
44:
45: /*
46: * Range check the arguments.
47: */
48: if (pshared != 0) {
49: /*
50: * The user wants a semaphore that can be shared among
51: * processes, which this implementation can't do. Sounds like a
52: * permissions problem to me (yeah right).
53: */
54: errno = EPERM;
55: retval = -1;
56: goto RETURN;
57: }
58:
59: if (value > SEM_VALUE_MAX) {
60: errno = EINVAL;
61: retval = -1;
62: goto RETURN;
63: }
64:
65: *sem = (xp_sem_t)malloc(sizeof(struct xp_sem));
66: if (*sem == NULL) {
67: errno = ENOSPC;
68: retval = -1;
69: goto RETURN;
70: }
71:
72: /*
73: * Initialize the semaphore.
74: */
75: if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
76: free(*sem);
77: errno = ENOSPC;
78: retval = -1;
79: goto RETURN;
80: }
81:
82: if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
83: pthread_mutex_destroy(&(*sem)->lock);
84: free(*sem);
85: errno = ENOSPC;
86: retval = -1;
87: goto RETURN;
88: }
89:
90: (*sem)->count = (u_int32_t)value;
91: (*sem)->nwaiters = 0;
92: (*sem)->magic = SEM_MAGIC;
93:
94: retval = 0;
95: RETURN:
96: return retval;
97: }
98:
99: int
100: xp_sem_destroy(xp_sem_t *sem)
101: {
102: int retval;
103:
104: _SEM_CHECK_VALIDITY(sem);
105:
106: /* Make sure there are no waiters. */
107: pthread_mutex_lock(&(*sem)->lock);
108: if ((*sem)->nwaiters > 0) {
109: pthread_mutex_unlock(&(*sem)->lock);
110: errno = EBUSY;
111: retval = -1;
112: goto RETURN;
113: }
114: pthread_mutex_unlock(&(*sem)->lock);
115:
116: pthread_mutex_destroy(&(*sem)->lock);
117: pthread_cond_destroy(&(*sem)->gtzero);
118: (*sem)->magic = 0;
119:
120: free(*sem);
121:
122: retval = 0;
123: RETURN:
124: return retval;
125: }
126:
127: xp_sem_t *
128: xp_sem_open(const char *name, int oflag, ...)
129: {
130: errno = ENOSYS;
131: return SEM_FAILED;
132: }
133:
134: int
135: xp_sem_close(xp_sem_t *sem)
136: {
137: errno = ENOSYS;
138: return -1;
139: }
140:
141: int
142: xp_sem_unlink(const char *name)
143: {
144: errno = ENOSYS;
145: return -1;
146: }
147:
148: int
149: xp_sem_wait(xp_sem_t *sem)
150: {
151: int retval;
152:
153: pthread_testcancel();
154:
155: _SEM_CHECK_VALIDITY(sem);
156:
157: pthread_mutex_lock(&(*sem)->lock);
158:
159: while ((*sem)->count == 0) {
160: (*sem)->nwaiters++;
161: pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
162: (*sem)->nwaiters--;
163: }
164: (*sem)->count--;
165:
166: pthread_mutex_unlock(&(*sem)->lock);
167:
168: retval = 0;
169: RETURN:
170:
171: pthread_testcancel();
172: return retval;
173: }
174:
175: int
176: xp_sem_trywait(xp_sem_t *sem)
177: {
178: int retval;
179:
180: _SEM_CHECK_VALIDITY(sem);
181:
182: pthread_mutex_lock(&(*sem)->lock);
183:
184: if ((*sem)->count > 0) {
185: (*sem)->count--;
186: retval = 0;
187: } else {
188: errno = EAGAIN;
189: retval = -1;
190: }
191:
192: pthread_mutex_unlock(&(*sem)->lock);
193:
194: RETURN:
195: return retval;
196: }
197:
198: int
199: xp_sem_post(xp_sem_t *sem)
200: {
201: int retval;
202:
203: _SEM_CHECK_VALIDITY(sem);
204:
205: pthread_mutex_lock(&(*sem)->lock);
206:
207: (*sem)->count++;
208: if ((*sem)->nwaiters > 0) {
209: /*
210: * We must use pthread_cond_broadcast() rather than
211: * pthread_cond_signal() in order to assure that the highest
212: * priority thread is run by the scheduler, since
213: * pthread_cond_signal() signals waiting threads in FIFO order.
214: */
215: pthread_cond_broadcast(&(*sem)->gtzero);
216: }
217:
218: pthread_mutex_unlock(&(*sem)->lock);
219:
220: retval = 0;
221: RETURN:
222: return retval;
223: }
224:
225: int
226: xp_sem_getvalue(xp_sem_t *sem, int *sval)
227: {
228: int retval;
229:
230: _SEM_CHECK_VALIDITY(sem);
231:
232: pthread_mutex_lock(&(*sem)->lock);
233: *sval = (int)(*sem)->count;
234: pthread_mutex_unlock(&(*sem)->lock);
235:
236: retval = 0;
237: RETURN:
238: return retval;
239: }
240:
241: int
242: xp_sem_timedwait(xp_sem_t *sem, const struct timespec *abs_timeout)
243: {
244: int retval=0;
245:
246: pthread_testcancel();
247:
248: _SEM_CHECK_VALIDITY(sem);
249:
250: pthread_mutex_lock(&(*sem)->lock);
251:
252: while ((*sem)->count == 0) {
253: (*sem)->nwaiters++;
254: retval=pthread_cond_timedwait(&(*sem)->gtzero, &(*sem)->lock, abs_timeout);
255: (*sem)->nwaiters--;
256: if(retval) {
257: errno=retval;
258: retval=-1;
259: break;
260: }
261: }
262: if(retval==0)
263: (*sem)->count--;
264:
265: pthread_mutex_unlock(&(*sem)->lock);
266:
267: RETURN:
268:
269: pthread_testcancel();
270: return retval;
271: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.