include-afsconfig-before-param-h-20010712
[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 RCSID("$Header$");
15
16 #include "../afs/sysincludes.h" /* Standard vendor system headers */
17 #include "../afs/afsincludes.h" /* Afs-based standard headers */
18 #include "../afs/afs_stats.h"   /* afs statistics */
19
20
21
22 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
23 void afs_osi_Wakeup(char *event);
24 void afs_osi_Sleep(char *event);
25
26 static char waitV;
27
28
29 void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
30 {
31     AFS_STATCNT(osi_InitWaitHandle);
32     achandle->proc = (caddr_t) 0;
33 }
34
35 /* cancel osi_Wait */
36 void afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
37 {
38     caddr_t proc;
39
40     AFS_STATCNT(osi_CancelWait);
41     proc = achandle->proc;
42     if (proc == 0) return;
43     achandle->proc = (caddr_t) 0;   /* so dude can figure out he was signalled */
44     afs_osi_Wakeup(&waitV);
45 }
46
47 /* afs_osi_Wait
48  * Waits for data on ahandle, or ams ms later.  ahandle may be null.
49  * Returns 0 if timeout and EINTR if signalled.
50  */
51 int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
52 {
53     int code;
54     afs_int32 endTime, tid;
55
56     AFS_STATCNT(osi_Wait);
57     endTime = osi_Time() + (ams/1000);
58     if (ahandle)
59       ahandle->proc = (caddr_t) curproc;
60     do {
61         AFS_ASSERT_GLOCK();
62         code = 0;
63         code = osi_TimedSleep(&waitV, ams, aintok);
64
65         if (code) break;        /* if something happened, quit now */
66         /* if we we're cancelled, quit now */
67         if (ahandle && (ahandle->proc == (caddr_t) 0)) {
68             /* we've been signalled */
69             break;
70         }
71     } while (osi_Time() < endTime);
72     return code;
73 }
74
75
76
77
78 typedef struct afs_event {
79     struct afs_event *next;     /* next in hash chain */
80     char *event;                /* lwp event: an address */
81     int refcount;               /* Is it in use? */
82     int seq;                    /* Sequence number: this is incremented
83                                    by wakeup calls; wait will not return until
84                                    it changes */
85     int cond;
86 } afs_event_t;
87
88 #define HASHSIZE 128
89 afs_event_t *afs_evhasht[HASHSIZE];/* Hash table for events */
90 #define afs_evhash(event)       (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
91 int afs_evhashcnt = 0;
92
93 /* Get and initialize event structure corresponding to lwp event (i.e. address)
94  * */
95 static afs_event_t *afs_getevent(char *event)
96 {
97     afs_event_t *evp, *newp = 0;
98     int hashcode;
99
100     AFS_ASSERT_GLOCK();
101     hashcode = afs_evhash(event);
102     evp = afs_evhasht[hashcode];
103     while (evp) {
104         if (evp->event == event) {
105             evp->refcount++;
106             return evp;
107         }
108         if (evp->refcount == 0)
109             newp = evp;
110         evp = evp->next;
111     }
112     if (!newp) {
113         newp = (afs_event_t *) osi_AllocSmallSpace(sizeof (afs_event_t));
114         afs_evhashcnt++;
115         newp->next = afs_evhasht[hashcode];
116         afs_evhasht[hashcode] = newp;
117         newp->seq = 0;
118     }
119     newp->event = event;
120     newp->refcount = 1;
121     return newp;
122 }
123
124 /* Release the specified event */
125 #define relevent(evp) ((evp)->refcount--)
126
127
128 void afs_osi_Sleep(char *event)
129 {
130     struct afs_event *evp;
131     int seq;
132
133     evp = afs_getevent(event);
134     seq = evp->seq;
135     while (seq == evp->seq) {
136         AFS_ASSERT_GLOCK();
137         assert_wait((vm_offset_t)(&evp->cond), 0);
138         AFS_GUNLOCK();
139         thread_block();
140         AFS_GLOCK();
141     }
142     relevent(evp);
143 }
144
145 /* osi_TimedSleep
146  * 
147  * Arguments:
148  * event - event to sleep on
149  * ams --- max sleep time in milliseconds
150  * aintok - 1 if should sleep interruptibly
151  *
152  * Returns 0 if timeout and EINTR if signalled.
153  */
154 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok)
155 {
156     int code = 0;
157     struct afs_event *evp;
158     int ticks;
159
160     ticks = ( ams * afs_hz )/1000;
161
162
163     evp = afs_getevent(event);
164
165     assert_wait((vm_offset_t)(&evp->cond), aintok);
166     AFS_GUNLOCK();
167     thread_set_timeout(ticks);
168     thread_block();
169     AFS_GLOCK();
170     /*    if (current_thread()->wait_result != THREAD_AWAKENED)
171           code = EINTR; */
172     
173     relevent(evp);
174     return code;
175 }
176
177
178 void afs_osi_Wakeup(char *event)
179 {
180     struct afs_event *evp;
181
182     evp = afs_getevent(event);
183     if (evp->refcount > 1) {
184         evp->seq++;    
185         thread_wakeup((vm_offset_t)(&evp->cond));
186     }
187     relevent(evp);
188 }