Fix build for FreeBSD 10.0
[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 }