2 * Copyright 2000, International Business Machines Corporation and others.
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
11 #include <afsconfig.h>
12 #include "afs/param.h"
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 */
19 #ifndef AFS_FBSD50_ENV
25 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
27 AFS_STATCNT(osi_InitWaitHandle);
29 cv_init(&achandle->wh_condvar, "afscondvar");
30 achandle->wh_inited = 1;
32 achandle->proc = NULL;
38 * I can't tell -- is this supposed to be cv_signal() or cv_waitq_remove()?
39 * Or perhaps cv_broadcast()?
40 * Assuming cv_signal() is the desired meaning. -GAW
43 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
45 #ifndef AFS_FBSD50_ENV
49 AFS_STATCNT(osi_CancelWait);
52 /* XXX should not be necessary */
53 if (!achandle->wh_inited)
56 cv_signal(&achandle->wh_condvar);
58 proc = achandle->proc;
61 achandle->proc = NULL; /* so dude can figure out he was signalled */
62 afs_osi_Wakeup(&waitV);
67 * Waits for data on ahandle, or ams ms later. ahandle may be null.
68 * Returns 0 if timeout and EINTR if signalled.
71 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
81 AFS_STATCNT(osi_Wait);
83 tv.tv_sec = ams / 1000;
84 tv.tv_usec = (ams % 1000) * 1000;
88 if (ahandle == NULL) {
89 /* This is nasty and evil and rude. */
91 code = msleep(&tv, &afs_global_mtx, (aintok ? PPAUSE|PCATCH : PVFS),
93 afs_global_owner = curthread;
95 if (!ahandle->wh_inited)
96 afs_osi_InitWaitHandle(ahandle); /* XXX should not be needed */
99 code = cv_timedwait_sig(&ahandle->wh_condvar, &afs_global_mtx,
102 code = cv_timedwait(&ahandle->wh_condvar, &afs_global_mtx, ticks);
105 endTime = osi_Time() + (ams / 1000);
107 ahandle->proc = (caddr_t) curproc;
110 code = afs_osi_TimedSleep(&waitV, ams, aintok);
112 break; /* if something happened, quit now */
113 /* if we we're cancelled, quit now */
114 if (ahandle && (ahandle->proc == NULL)) {
115 /* we've been signalled */
118 } while (osi_Time() < endTime);
124 * All this gluck should probably also be replaced with CVs.
126 typedef struct afs_event {
127 struct afs_event *next; /* next in hash chain */
128 char *event; /* lwp event: an address */
129 int refcount; /* Is it in use? */
130 int seq; /* Sequence number: this is incremented
131 * by wakeup calls; wait will not return until
133 #ifdef AFS_FBSD50_ENV
135 struct thread *owner;
142 afs_event_t *afs_evhasht[HASHSIZE]; /* Hash table for events */
143 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
144 int afs_evhashcnt = 0;
146 #ifdef AFS_FBSD50_ENV
147 #define EVTLOCK_INIT(e) \
149 mtx_init((e)->lck, "event lock", NULL, MTX_DEF); \
152 #define EVTLOCK_LOCK(e) \
154 osi_Assert((e)->owner != curthread); \
155 mtx_lock((e)->lck); \
156 osi_Assert((e)->owner == 0); \
157 (e)->owner = curthread; \
159 #define EVTLOCK_UNLOCK(e) \
161 osi_Assert((e)->owner == curthread); \
163 mtx_unlock((e)->lck); \
165 #define EVTLOCK_DESTROY(e) mtx_destroy((e)->lck)
167 #define EVTLOCK_INIT(e)
168 #define EVTLOCK_LOCK(e)
169 #define EVTLOCK_UNLOCK(e)
170 #define EVTLOCK_DESTROY(e)
174 /* Get and initialize event structure corresponding to lwp event (i.e. address)
177 afs_getevent(char *event)
179 afs_event_t *evp, *newp = 0;
183 hashcode = afs_evhash(event);
184 evp = afs_evhasht[hashcode];
187 if (evp->event == event) {
191 if (evp->refcount == 0)
197 newp = (afs_event_t *) osi_AllocSmallSpace(sizeof(afs_event_t));
199 newp->next = afs_evhasht[hashcode];
200 afs_evhasht[hashcode] = newp;
210 /* Release the specified event */
211 #ifdef AFS_FBSD50_ENV
212 #define relevent(evp) \
214 osi_Assert((evp)->owner == curthread); \
217 mtx_unlock((evp)->lck); \
220 #define relevent(evp) ((evp)->refcount--)
224 afs_osi_Sleep(void *event)
226 struct afs_event *evp;
229 evp = afs_getevent(event);
231 while (seq == evp->seq) {
233 #ifdef AFS_FBSD50_ENV
235 msleep(event, &afs_global_mtx, PVFS, "afsslp", 0);
236 evp->owner = curthread;
239 tsleep(event, PVFS, "afs_osi_Sleep", 0);
247 afs_osi_SleepSig(void *event)
249 afs_osi_Sleep(event);
253 /* afs_osi_TimedSleep
256 * event - event to sleep on
257 * ams --- max sleep time in milliseconds
258 * aintok - 1 if should sleep interruptibly
260 * Returns 0 if timeout and EINTR if signalled.
263 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
266 struct afs_event *evp;
270 evp = afs_getevent(event);
274 prio = PCATCH | PPAUSE;
277 ts.tv_sec = ams / 1000;
278 ts.tv_nsec = (ams % 1000) * 1000000;
280 code = msleep(event, evp->lck, prio, "afsslp", &ts);
281 evp->owner = curthread;
290 afs_osi_Wakeup(void *event)
293 struct afs_event *evp;
295 evp = afs_getevent(event);
296 if (evp->refcount > 1) {
306 shutdown_osisleep(void) {
307 struct afs_event *evp, *nevp, **pevpp;
309 for (i=0; i < HASHSIZE; i++) {
310 evp = afs_evhasht[i];
311 pevpp = &afs_evhasht[i];
315 if (evp->refcount == 0) {
316 EVTLOCK_DESTROY(evp);
318 osi_FreeSmallSpace(evp);