|
|
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.