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
10 #include <afsconfig.h>
11 #include "afs/param.h"
16 #include "afs/sysincludes.h" /* Standard vendor system headers */
17 #include "afsincludes.h" /* Afs-based standard headers */
18 #include "afs/afs_stats.h" /* afs statistics */
22 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
27 AfsWaitHack(struct trb *trb)
29 AFS_STATCNT(WaitHack);
31 e_clear_wait(trb->func_data, THREAD_TIMED_OUT);
35 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
37 AFS_STATCNT(osi_InitWaitHandle);
38 achandle->proc = (caddr_t) 0;
43 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
47 AFS_STATCNT(osi_CancelWait);
48 proc = achandle->proc;
51 achandle->proc = (caddr_t) 0; /* so dude can figure out he was signalled */
52 afs_osi_Wakeup(&waitV);
56 * Waits for data on ahandle, or ams ms later. ahandle may be null.
57 * Returns 0 if timeout and EINTR if signalled.
60 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
63 afs_int32 endTime, tid;
65 AFS_STATCNT(osi_Wait);
66 endTime = osi_Time() + (ams / 1000);
68 ahandle->proc = (caddr_t) thread_self();
72 code = osi_TimedSleep(&waitV, ams, aintok);
75 break; /* if something happened, quit now */
76 /* if we we're cancelled, quit now */
77 if (ahandle && (ahandle->proc == (caddr_t) 0)) {
78 /* we've been signalled */
81 } while (osi_Time() < endTime);
88 typedef struct afs_event {
89 struct afs_event *next; /* next in hash chain */
90 char *event; /* lwp event: an address */
91 int refcount; /* Is it in use? */
92 int seq; /* Sequence number: this is incremented
93 * by wakeup calls; wait will not return until
99 afs_event_t *afs_evhasht[HASHSIZE]; /* Hash table for events */
100 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
101 int afs_evhashcnt = 0;
103 /* Get and initialize event structure corresponding to lwp event (i.e. address)
106 afs_getevent(char *event)
108 afs_event_t *evp, *newp = 0;
112 hashcode = afs_evhash(event);
113 evp = afs_evhasht[hashcode];
115 if (evp->event == event) {
119 if (evp->refcount == 0)
124 newp = (afs_event_t *) osi_AllocSmallSpace(sizeof(afs_event_t));
126 newp->next = afs_evhasht[hashcode];
127 afs_evhasht[hashcode] = newp;
128 newp->cond = EVENT_NULL;
136 /* Release the specified event */
137 #define relevent(evp) ((evp)->refcount--)
141 afs_osi_Sleep(void *event)
143 struct afs_event *evp;
146 evp = afs_getevent(event);
148 while (seq == evp->seq) {
150 e_assert_wait(&evp->cond, 0);
159 afs_osi_SleepSig(void *event)
161 afs_osi_Sleep(event);
168 * event - event to sleep on
169 * ams --- max sleep time in milliseconds
170 * aintok - 1 if should sleep interruptibly
172 * Returns 0 if timeout and EINTR if signalled.
175 osi_TimedSleep(char *event, afs_int32 ams, int aintok)
178 struct afs_event *evp;
179 struct timestruc_t ticks;
183 ticks.tv_sec = ams / 1000;
184 ticks.tv_nsec = (ams - (ticks.tv_sec * 1000)) * 1000000;
187 evp = afs_getevent(event);
191 osi_Panic("talloc returned NULL");
193 trb->func = AfsWaitHack;
194 trb->eventlist = EVENT_NULL;
195 trb->ipri = INTTIMER;
196 trb->func_data = thread_self();
197 trb->timeout.it_value = ticks;
199 e_assert_wait(&evp->cond, aintok);
202 rc = e_block_thread();
204 if (rc == THREAD_INTERRUPTED)
215 afs_osi_Wakeup(void *event)
218 struct afs_event *evp;
220 evp = afs_getevent(event);
221 if (evp->refcount > 1) {
223 e_wakeup(&evp->cond);