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