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
xsem_init(xsem_t * sem,int pshared,unsigned int value)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
xsem_destroy(xsem_t * sem)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
xsem_wait(xsem_t * sem)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
xsem_trywait(xsem_t * sem)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
xsem_post(xsem_t * sem)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
xsem_getvalue(xsem_t * sem,int * sval)126 xsem_getvalue(xsem_t *sem, int *sval)
127 {
128 *sval = sem->semaphore;
129 }
130
131
132
133 int
xsem_xwait(xsem_t * sem,int timeout,timestruc_t * mytime)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