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 /* 28 * xsem.c: to provide a semaphore system (used by the smq routines) 29 * 30 * these routines come from the libxposix library. 31 */ 32 33 #include <pthread.h> 34 #include <time.h> 35 36 #include "xsem.h" 37 38 39 int 40 xsem_init(xsem_t *sem, int pshared, unsigned int value) 41 { 42 if (pshared != 0) 43 return (-1); 44 45 pthread_mutex_init(&sem->semMutex, NULL); 46 pthread_cond_init(&sem->semCV, NULL); 47 sem->semaphore = value; 48 49 return (0); 50 } 51 52 void 53 xsem_destroy(xsem_t *sem) 54 { 55 pthread_mutex_destroy(&sem->semMutex); 56 pthread_cond_destroy(&sem->semCV); 57 sem->semaphore = 0; 58 } 59 60 int 61 xsem_wait(xsem_t *sem) 62 { 63 pthread_mutex_lock(&sem->semMutex); 64 65 if (sem->semaphore < 0) { 66 sem->semaphore = 0; 67 pthread_mutex_unlock(&sem->semMutex); 68 return (XSEM_ERROR); 69 } 70 71 if (sem->semaphore > 0) { 72 sem->semaphore--; 73 } else { 74 while (sem->semaphore == 0) 75 pthread_cond_wait(&sem->semCV, &sem->semMutex); 76 77 if (sem->semaphore != 0) { 78 sem->semaphore--; 79 } else { 80 pthread_mutex_unlock(&sem->semMutex); 81 return (XSEM_ERROR); 82 } 83 } 84 85 pthread_mutex_unlock(&sem->semMutex); 86 return (0); 87 } 88 89 90 int 91 xsem_trywait(xsem_t *sem) 92 { 93 pthread_mutex_lock(&sem->semMutex); 94 95 if (sem->semaphore < 0) { 96 sem->semaphore = 0; 97 pthread_mutex_unlock(&sem->semMutex); 98 return (XSEM_ERROR); 99 } 100 101 if (sem->semaphore == 0) { 102 pthread_mutex_unlock(&sem->semMutex); 103 return (XSEM_EBUSY); 104 } else { 105 sem->semaphore--; 106 } 107 108 pthread_mutex_unlock(&sem->semMutex); 109 return (0); 110 } 111 112 113 int 114 xsem_post(xsem_t *sem) 115 { 116 pthread_mutex_lock(&sem->semMutex); 117 sem->semaphore++; 118 pthread_cond_signal(&sem->semCV); 119 pthread_mutex_unlock(&sem->semMutex); 120 121 return (0); 122 } 123 124 125 void 126 xsem_getvalue(xsem_t *sem, int *sval) 127 { 128 *sval = sem->semaphore; 129 } 130 131 132 133 int 134 xsem_xwait(xsem_t *sem, int timeout, timestruc_t *mytime) 135 { 136 int status; 137 timestruc_t delay; 138 139 if (timeout == 0) 140 return (xsem_wait(sem)); 141 else { 142 pthread_mutex_lock(&sem->semMutex); 143 144 if (sem->semaphore < 0) { 145 sem->semaphore = 0; 146 pthread_mutex_unlock(&sem->semMutex); 147 return (XSEM_ERROR); 148 } 149 150 if (sem->semaphore > 0) { 151 sem->semaphore--; 152 } else { 153 status = 0; 154 155 delay = *mytime; 156 delay.tv_sec = delay.tv_sec + time(NULL); 157 while ((sem->semaphore == 0) && (status == 0)) { 158 status = pthread_cond_timedwait(&sem->semCV, 159 &sem->semMutex, &delay); 160 } 161 162 /* 163 * Check one more time in case thread didn't have a 164 * chance to check before timeout ??? TBD 165 */ 166 167 if (status != 0) { 168 pthread_mutex_unlock(&sem->semMutex); 169 return (XSEM_ETIME); 170 } else if (sem->semaphore != 0) { 171 sem->semaphore--; 172 } else { 173 pthread_mutex_unlock(&sem->semMutex); 174 return (XSEM_ERROR); 175 } 176 } 177 178 pthread_mutex_unlock(&sem->semMutex); 179 } 180 181 return (0); 182 } 183