Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / NBSD / osi_sleep.c
CommitLineData
805e021f
CE
1/*
2 * $Id: osi_sleep.c,v 1.9 2005/07/26 15:25:43 rees Exp $
3 */
4
5/*
6copyright 2002
7the regents of the university of michigan
8all rights reserved
9
10permission is granted to use, copy, create derivative works
11and redistribute this software and such derivative works
12for any purpose, so long as the name of the university of
13michigan is not used in any advertising or publicity
14pertaining to the use or distribution of this software
15without specific, written prior authorization. if the
16above copyright notice or any other identification of the
17university of michigan is included in any copy of any
18portion of this software, then the disclaimer below must
19also be included.
20
21this software is provided as is, without representation
22from the university of michigan as to its fitness for any
23purpose, and without warranty by the university of
24michigan of any kind, either express or implied, including
25without limitation the implied warranties of
26merchantability and fitness for a particular purpose. the
27regents of the university of michigan shall not be liable
28for any damages, including special, indirect, incidental, or
29consequential damages, with respect to any claim arising
30out of or in connection with the use of the software, even
31if it has been or is hereafter advised of the possibility of
32such damages.
33*/
34
35/*
36 * Copyright 2000, International Business Machines Corporation and others.
37 * All Rights Reserved.
38 *
39 * This software has been released under the terms of the IBM Public
40 * License. For details, see the LICENSE file in the top-level source
41 * directory or online at http://www.openafs.org/dl/license10.html
42 */
43
44#include <afsconfig.h>
45#include "afs/param.h"
46
47#include "afs/sysincludes.h" /* Standard vendor system headers */
48#include "afs/afsincludes.h" /* Afs-based standard headers */
49#include "afs/afs_stats.h" /* afs statistics */
50
51#if !defined(AFS_NBSD50_ENV)
52static char waitV;
53
54/* cancel osi_Wait */
55void
56afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
57{
58 caddr_t proc;
59
60 AFS_STATCNT(osi_CancelWait);
61 proc = achandle->proc;
62 if (proc == NULL)
63 return;
64 achandle->proc = NULL;
65 wakeup(&waitV);
66}
67
68/* afs_osi_Wait
69 * Waits for data on ahandle, or ams ms later. ahandle may be null.
70 * Returns 0 if timeout and EINTR if signalled.
71 */
72int
73afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
74{
75 int timo, code = 0;
76 struct timeval atv, time_now, endTime;
77 const struct timeval timezero = { 0, 0 };
78
79 AFS_STATCNT(osi_Wait);
80
81 atv.tv_sec = ams / 1000;
82 atv.tv_usec = (ams % 1000) * 1000;
83 getmicrouptime(&time_now);
84 timeradd(&atv, &time_now, &endTime);
85
86 if (ahandle)
87 ahandle->proc = (caddr_t) osi_curproc();
88 AFS_ASSERT_GLOCK();
89 AFS_GUNLOCK();
90
91 do {
92 timersub(&endTime, &time_now, &atv);
93 if (timercmp(&atv, &timezero, <))
94 break;
95 timo = tvtohz(&atv);
96 if (aintok) {
97 code = tsleep(&waitV, PCATCH | PVFS, "afs_W1", timo);
98 } else {
99 code = tsleep(&waitV, PVFS, "afs_W2", timo);
100 }
101 if (code)
102 code = (code == EWOULDBLOCK) ? 0 : EINTR;
103
104 getmicrouptime(&time_now);
105
106 /* if we were cancelled, quit now */
107 if (ahandle && (ahandle->proc == NULL)) {
108 /* we've been signalled */
109 break;
110 }
111 } while (timercmp(&time_now, &endTime, <));
112
113 AFS_GLOCK();
114
115 return code;
116}
117
118void
119afs_osi_Sleep(void *event)
120{
121 AFS_ASSERT_GLOCK();
122 AFS_GUNLOCK();
123 tsleep(event, PVFS, "afsslp", 0);
124 AFS_GLOCK();
125}
126
127int
128afs_osi_SleepSig(void *event)
129{
130 afs_osi_Sleep(event);
131 return 0;
132}
133
134int
135afs_osi_Wakeup(void *event)
136{
137 wakeup(event);
138 return 1;
139}
140#else
141static char waitV;
142
143void
144afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
145{
146 AFS_STATCNT(osi_InitWaitHandle);
147 achandle->proc = (caddr_t) 0;
148}
149
150/* cancel osi_Wait */
151void
152afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
153{
154 caddr_t proc;
155
156 AFS_STATCNT(osi_CancelWait);
157 proc = achandle->proc;
158 if (proc == 0)
159 return;
160 achandle->proc = (caddr_t) 0; /* so dude can figure out he was signalled */
161 afs_osi_Wakeup(&waitV);
162}
163
164/* afs_osi_Wait
165 * Waits for data on ahandle, or ams ms later. ahandle may be null.
166 * Returns 0 if timeout and EINTR if signalled.
167 */
168int
169afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
170{
171 int code;
172 afs_int32 endTime;
173
174 AFS_STATCNT(osi_Wait);
175 endTime = osi_Time() + (ams / 1000);
176 if (ahandle)
177 ahandle->proc = (caddr_t) osi_curproc();
178 do {
179 AFS_ASSERT_GLOCK();
180 code = afs_osi_TimedSleep(&waitV, ams, aintok);
181
182 if (code)
183 break; /* if something happened, quit now */
184 /* if we we're cancelled, quit now */
185 if (ahandle && (ahandle->proc == (caddr_t) 0)) {
186 /* we've been signalled */
187 break;
188 }
189 } while (osi_Time() < endTime);
190 return code;
191}
192
193
194
195
196afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
197#define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
198int afs_evhashcnt = 0;
199
200/* Get and initialize event structure corresponding to lwp event (i.e. address)
201 * */
202static afs_event_t *
203afs_getevent(char *event)
204{
205 afs_event_t *evp, *newp = 0;
206 int hashcode;
207
208 AFS_ASSERT_GLOCK();
209 hashcode = afs_evhash(event);
210 evp = afs_evhasht[hashcode];
211 while (evp) {
212 if (evp->event == event) {
213 evp->refcount++;
214 return evp;
215 }
216 if (evp->refcount == 0)
217 newp = evp;
218 evp = evp->next;
219 }
220 if (!newp) {
221 newp = osi_AllocSmallSpace(sizeof(afs_event_t));
222 afs_evhashcnt++;
223 newp->next = afs_evhasht[hashcode];
224 afs_evhasht[hashcode] = newp;
225 cv_init(&newp->cond, "afsevent");
226 newp->seq = 0;
227 }
228 newp->event = event;
229 newp->refcount = 1;
230 return newp;
231}
232
233/* Release the specified event */
234#define relevent(evp) ((evp)->refcount--)
235
236
237void
238afs_osi_Sleep(void *event)
239{
240 struct afs_event *evp;
241 int seq;
242
243 evp = afs_getevent(event);
244 seq = evp->seq;
245 while (seq == evp->seq) {
246 AFS_ASSERT_GLOCK();
247 cv_wait(&evp->cond, &afs_global_mtx);
248 }
249 relevent(evp);
250}
251
252int
253afs_osi_SleepSig(void *event)
254{
255 struct afs_event *evp;
256 int seq, code = 0;
257
258 evp = afs_getevent(event);
259 seq = evp->seq;
260 while (seq == evp->seq) {
261 AFS_ASSERT_GLOCK();
262 code = cv_wait_sig(&evp->cond, &afs_global_mtx);
263 if (code) {
264 code = (code == EWOULDBLOCK) ? 0 : EINTR;
265 break;
266 }
267 }
268 relevent(evp);
269 return code;
270}
271
272/* afs_osi_TimedSleep
273 *
274 * Arguments:
275 * event - event to sleep on
276 * ams --- max sleep time in milliseconds
277 * aintok - 1 if should sleep interruptibly
278 *
279 * Returns 0 if timeout and EINTR if signalled.
280 */
281int
282afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
283{
284 int code;
285 struct afs_event *evp;
286 int ticks;
287
288 ticks = mstohz(ams);
289 ticks = ticks ? ticks : 1;
290 evp = afs_getevent(event);
291
292 AFS_ASSERT_GLOCK();
293 if (aintok) {
294 code = cv_timedwait_sig(&evp->cond, &afs_global_mtx, ticks);
295 } else {
296 code = cv_timedwait(&evp->cond, &afs_global_mtx, ticks);
297 }
298
299 switch (code) {
300 default:
301 code = EINTR;
302 break;
303 case EWOULDBLOCK:
304 code = 0;
305 break;
306 }
307
308 relevent(evp);
309 return code;
310}
311
312
313int
314afs_osi_Wakeup(void *event)
315{
316 int ret = 1;
317 struct afs_event *evp;
318
319 evp = afs_getevent(event);
320 if (evp->refcount > 1) {
321 evp->seq++;
322 cv_broadcast(&evp->cond);
323 ret = 0;
324 }
325 relevent(evp);
326 return 0;
327}
328#endif