Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / FBSD / osi_sleep.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10
11 #include <afsconfig.h>
12 #include "afs/param.h"
13
14
15 #include "afs/sysincludes.h" /* Standard vendor system headers */
16 #include "afsincludes.h" /* Afs-based standard headers */
17 #include "afs/afs_stats.h" /* afs statistics */
18
19 void
20 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
21 {
22 AFS_STATCNT(osi_InitWaitHandle);
23 cv_init(&achandle->wh_condvar, "afscondvar");
24 achandle->wh_inited = 1;
25 }
26
27 /* cancel osi_Wait */
28 /* XXX
29 * I can't tell -- is this supposed to be cv_signal() or cv_waitq_remove()?
30 * Or perhaps cv_broadcast()?
31 * Assuming cv_signal() is the desired meaning. -GAW
32 */
33 void
34 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
35 {
36 AFS_STATCNT(osi_CancelWait);
37
38 /* XXX should not be necessary */
39 if (!achandle->wh_inited)
40 return;
41 AFS_ASSERT_GLOCK();
42 cv_signal(&achandle->wh_condvar);
43 }
44
45 /* afs_osi_Wait
46 * Waits for data on ahandle, or ams ms later. ahandle may be null.
47 * Returns 0 if timeout and EINTR if signalled.
48 */
49 int
50 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
51 {
52 int code;
53 struct timeval tv;
54 int ticks;
55
56 AFS_STATCNT(osi_Wait);
57 tv.tv_sec = ams / 1000;
58 tv.tv_usec = (ams % 1000) * 1000;
59 ticks = tvtohz(&tv);
60
61 AFS_ASSERT_GLOCK();
62 if (ahandle == NULL) {
63 /* This is nasty and evil and rude. */
64 code = msleep(&tv, &afs_global_mtx, (aintok ? PPAUSE|PCATCH : PVFS),
65 "afswait", ticks);
66 } else {
67 if (!ahandle->wh_inited)
68 afs_osi_InitWaitHandle(ahandle); /* XXX should not be needed */
69 if (aintok)
70 code = cv_timedwait_sig(&ahandle->wh_condvar, &afs_global_mtx,
71 ticks);
72 else
73 code = cv_timedwait(&ahandle->wh_condvar, &afs_global_mtx, ticks);
74 }
75 return code;
76 }
77
78 afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
79 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
80 int afs_evhashcnt = 0;
81
82 /* Get and initialize event structure corresponding to lwp event (i.e. address)
83 * */
84 static afs_event_t *
85 afs_getevent(char *event)
86 {
87 afs_event_t *evp, *newp = 0;
88 int hashcode;
89
90 AFS_ASSERT_GLOCK();
91 hashcode = afs_evhash(event);
92 evp = afs_evhasht[hashcode];
93 while (evp) {
94 if (evp->event == event) {
95 evp->refcount++;
96 return evp;
97 }
98 if (evp->refcount == 0)
99 newp = evp;
100 evp = evp->next;
101 }
102 if (!newp) {
103 newp = (afs_event_t *) afs_osi_Alloc_NoSleep(sizeof(afs_event_t));
104 afs_evhashcnt++;
105 newp->next = afs_evhasht[hashcode];
106 afs_evhasht[hashcode] = newp;
107 newp->seq = 0;
108 }
109 newp->event = event;
110 newp->refcount = 1;
111 return newp;
112 }
113
114 /* Release the specified event */
115 #define relevent(evp) ((evp)->refcount--)
116
117
118 void
119 afs_osi_Sleep(void *event)
120 {
121 struct afs_event *evp;
122 int seq;
123
124 evp = afs_getevent(event);
125 seq = evp->seq;
126 while (seq == evp->seq) {
127 AFS_ASSERT_GLOCK();
128 msleep(event, &afs_global_mtx, PVFS, "afsslp", 0);
129 }
130 relevent(evp);
131 }
132
133 int
134 afs_osi_SleepSig(void *event)
135 {
136 afs_osi_Sleep(event);
137 return 0;
138 }
139
140 /* osi_TimedSleep
141 *
142 * Arguments:
143 * event - event to sleep on
144 * ams --- max sleep time in milliseconds
145 * aintok - 1 if should sleep interruptibly
146 *
147 * Returns 0 if timeout and EINTR if signalled.
148 */
149 int
150 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
151 {
152 struct afs_event *evp;
153 int seq, code;
154 struct timeval tv;
155 int ticks;
156
157 tv.tv_sec = ams / 1000;
158 tv.tv_usec = (ams % 1000) * 1000;
159 ticks = tvtohz(&tv);
160
161 evp = afs_getevent(event);
162 seq = evp->seq;
163 while (seq == evp->seq) {
164 AFS_ASSERT_GLOCK();
165 code = msleep(event, &afs_global_mtx, (aintok ? PPAUSE|PCATCH : PVFS),
166 "afstslp", ticks);
167 if (code == EINTR)
168 break;
169 }
170 relevent(evp);
171 return code;
172 }
173
174 int
175 afs_osi_Wakeup(void *event)
176 {
177 int ret = 1;
178 struct afs_event *evp;
179
180 evp = afs_getevent(event);
181 if (evp->refcount > 1) {
182 evp->seq++;
183 wakeup(event);
184 ret = 0;
185 }
186 relevent(evp);
187 return ret;
188 }