Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / afs / NBSD / osi_sleep.c
blob191a7e016fef6c081aee17059ffa4cd49b405271
1 /*
2 * $Id: osi_sleep.c,v 1.9 2005/07/26 15:25:43 rees Exp $
3 */
5 /*
6 copyright 2002
7 the regents of the university of michigan
8 all rights reserved
10 permission is granted to use, copy, create derivative works
11 and redistribute this software and such derivative works
12 for any purpose, so long as the name of the university of
13 michigan is not used in any advertising or publicity
14 pertaining to the use or distribution of this software
15 without specific, written prior authorization. if the
16 above copyright notice or any other identification of the
17 university of michigan is included in any copy of any
18 portion of this software, then the disclaimer below must
19 also be included.
21 this software is provided as is, without representation
22 from the university of michigan as to its fitness for any
23 purpose, and without warranty by the university of
24 michigan of any kind, either express or implied, including
25 without limitation the implied warranties of
26 merchantability and fitness for a particular purpose. the
27 regents of the university of michigan shall not be liable
28 for any damages, including special, indirect, incidental, or
29 consequential damages, with respect to any claim arising
30 out of or in connection with the use of the software, even
31 if it has been or is hereafter advised of the possibility of
32 such damages.
36 * Copyright 2000, International Business Machines Corporation and others.
37 * All Rights Reserved.
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
44 #include <afsconfig.h>
45 #include "afs/param.h"
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 */
51 #if !defined(AFS_NBSD50_ENV)
52 static char waitV;
54 /* cancel osi_Wait */
55 void
56 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
58 caddr_t proc;
60 AFS_STATCNT(osi_CancelWait);
61 proc = achandle->proc;
62 if (proc == NULL)
63 return;
64 achandle->proc = NULL;
65 wakeup(&waitV);
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.
72 int
73 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
75 int timo, code = 0;
76 struct timeval atv, time_now, endTime;
77 const struct timeval timezero = { 0, 0 };
79 AFS_STATCNT(osi_Wait);
81 atv.tv_sec = ams / 1000;
82 atv.tv_usec = (ams % 1000) * 1000;
83 getmicrouptime(&time_now);
84 timeradd(&atv, &time_now, &endTime);
86 if (ahandle)
87 ahandle->proc = (caddr_t) osi_curproc();
88 AFS_ASSERT_GLOCK();
89 AFS_GUNLOCK();
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);
101 if (code)
102 code = (code == EWOULDBLOCK) ? 0 : EINTR;
104 getmicrouptime(&time_now);
106 /* if we were cancelled, quit now */
107 if (ahandle && (ahandle->proc == NULL)) {
108 /* we've been signalled */
109 break;
111 } while (timercmp(&time_now, &endTime, <));
113 AFS_GLOCK();
115 return code;
118 void
119 afs_osi_Sleep(void *event)
121 AFS_ASSERT_GLOCK();
122 AFS_GUNLOCK();
123 tsleep(event, PVFS, "afsslp", 0);
124 AFS_GLOCK();
128 afs_osi_SleepSig(void *event)
130 afs_osi_Sleep(event);
131 return 0;
135 afs_osi_Wakeup(void *event)
137 wakeup(event);
138 return 1;
140 #else
141 static char waitV;
143 void
144 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
146 AFS_STATCNT(osi_InitWaitHandle);
147 achandle->proc = (caddr_t) 0;
150 /* cancel osi_Wait */
151 void
152 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
154 caddr_t proc;
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);
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.
169 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
171 int code;
172 afs_int32 endTime;
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);
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;
189 } while (osi_Time() < endTime);
190 return code;
196 afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
197 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
198 int afs_evhashcnt = 0;
200 /* Get and initialize event structure corresponding to lwp event (i.e. address)
201 * */
202 static afs_event_t *
203 afs_getevent(char *event)
205 afs_event_t *evp, *newp = 0;
206 int hashcode;
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;
216 if (evp->refcount == 0)
217 newp = evp;
218 evp = evp->next;
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;
228 newp->event = event;
229 newp->refcount = 1;
230 return newp;
233 /* Release the specified event */
234 #define relevent(evp) ((evp)->refcount--)
237 void
238 afs_osi_Sleep(void *event)
240 struct afs_event *evp;
241 int seq;
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);
249 relevent(evp);
253 afs_osi_SleepSig(void *event)
255 struct afs_event *evp;
256 int seq, code = 0;
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;
268 relevent(evp);
269 return code;
272 /* afs_osi_TimedSleep
274 * Arguments:
275 * event - event to sleep on
276 * ams --- max sleep time in milliseconds
277 * aintok - 1 if should sleep interruptibly
279 * Returns 0 if timeout and EINTR if signalled.
282 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
284 int code;
285 struct afs_event *evp;
286 int ticks;
288 ticks = mstohz(ams);
289 ticks = ticks ? ticks : 1;
290 evp = afs_getevent(event);
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);
299 switch (code) {
300 default:
301 code = EINTR;
302 break;
303 case EWOULDBLOCK:
304 code = 0;
305 break;
308 relevent(evp);
309 return code;
314 afs_osi_Wakeup(void *event)
316 int ret = 1;
317 struct afs_event *evp;
319 evp = afs_getevent(event);
320 if (evp->refcount > 1) {
321 evp->seq++;
322 cv_broadcast(&evp->cond);
323 ret = 0;
325 relevent(evp);
326 return 0;
328 #endif