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