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 "../afs/param.h" /* Should be always first */
11 #include "../afs/sysincludes.h" /* Standard vendor system headers */
12 #include "../afs/afsincludes.h" /* Afs-based standard headers */
13 #include "../afs/afs_stats.h" /* afs statistics */
17 #if defined(AFS_GLOBAL_SUNLOCK)
18 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
21 void afs_osi_Wakeup(char *event);
22 void afs_osi_Sleep(char *event);
26 #if ! defined(AFS_GLOBAL_SUNLOCK)
28 /* call procedure aproc with arock as an argument, in ams milliseconds */
29 static struct timer_list *afs_osi_CallProc(void *aproc, void *arock, int ams)
31 struct timer_list *timer = NULL;
33 timer = (struct timer_list*)osi_Alloc(sizeof(struct timer_list));
36 timer->expires = (ams*afs_hz)/1000 + 1;
37 timer->data = (unsigned long)arock;
38 timer->function = aproc;
44 /* cancel a timeout, whether or not it has already occurred */
45 static int afs_osi_CancelProc(struct timer_list *timer)
49 osi_Free(timer, sizeof(struct timer_list));
56 AFS_STATCNT(WaitHack);
62 void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
64 AFS_STATCNT(osi_InitWaitHandle);
65 achandle->proc = (caddr_t) 0;
69 void afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
73 AFS_STATCNT(osi_CancelWait);
74 proc = achandle->proc;
75 if (proc == 0) return;
76 achandle->proc = (caddr_t) 0; /* so dude can figure out he was signalled */
77 afs_osi_Wakeup(&waitV);
81 * Waits for data on ahandle, or ams ms later. ahandle may be null.
82 * Returns 0 if timeout and EINTR if signalled.
84 int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
87 afs_int32 endTime, tid;
88 struct timer_list *timer = NULL;
90 AFS_STATCNT(osi_Wait);
91 endTime = osi_Time() + (ams/1000);
93 ahandle->proc = (caddr_t) current;
98 #if defined(AFS_GLOBAL_SUNLOCK)
99 code = osi_TimedSleep(&waitV, ams, 1);
102 flush_signals(current);
106 timer = afs_osi_CallProc(AfsWaitHack, (char *) current, ams);
107 afs_osi_Sleep(&waitV);
108 afs_osi_CancelProc(timer);
109 #endif /* AFS_GLOBAL_SUNLOCK */
110 if (ahandle && (ahandle->proc == (caddr_t) 0)) {
111 /* we've been signalled */
114 } while (osi_Time() < endTime);
121 typedef struct afs_event {
122 struct afs_event *next; /* next in hash chain */
123 char *event; /* lwp event: an address */
124 int refcount; /* Is it in use? */
125 int seq; /* Sequence number: this is incremented
126 by wakeup calls; wait will not return until
128 #if defined(AFS_LINUX24_ENV)
129 wait_queue_head_t cond;
131 struct wait_queue *cond;
136 afs_event_t *afs_evhasht[HASHSIZE];/* Hash table for events */
137 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
138 int afs_evhashcnt = 0;
140 /* Get and initialize event structure corresponding to lwp event (i.e. address)
142 static afs_event_t *afs_getevent(char *event)
144 afs_event_t *evp, *newp = 0;
148 hashcode = afs_evhash(event);
149 evp = afs_evhasht[hashcode];
151 if (evp->event == event) {
155 if (evp->refcount == 0)
160 newp = (afs_event_t *) osi_AllocSmallSpace(sizeof (afs_event_t));
162 newp->next = afs_evhasht[hashcode];
163 afs_evhasht[hashcode] = newp;
164 #if defined(AFS_LINUX24_ENV)
165 init_waitqueue_head(&newp->cond);
167 init_waitqueue(&newp->cond);
176 /* Release the specified event */
177 #define relevent(evp) ((evp)->refcount--)
180 void afs_osi_Sleep(char *event)
182 struct afs_event *evp;
185 evp = afs_getevent(event);
187 while (seq == evp->seq) {
190 interruptible_sleep_on(&evp->cond);
199 * event - event to sleep on
200 * ams --- max sleep time in milliseconds
201 * aintok - 1 if should sleep interruptibly
203 * Returns 0 if timeout and EINTR if signalled.
205 * While the Linux kernel still has a global lock, we can use the standard
206 * sleep calls and drop our locks early. The kernel lock will protect us
207 * until we get to sleep.
209 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok)
211 long t = ams * HZ / 1000;
212 struct afs_event *evp;
214 evp = afs_getevent(event);
218 t = interruptible_sleep_on_timeout(&evp->cond, t);
220 t = sleep_on_timeout(&evp->cond, t);
223 return t ? EINTR : 0;
227 void afs_osi_Wakeup(char *event)
229 struct afs_event *evp;
231 evp = afs_getevent(event);
232 if (evp->refcount > 1) {