Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / FBSD / osi_sleep.c
CommitLineData
805e021f
CE
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
19void
20afs_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 */
33void
34afs_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 */
49int
50afs_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
78afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
79#define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
80int afs_evhashcnt = 0;
81
82/* Get and initialize event structure corresponding to lwp event (i.e. address)
83 * */
84static afs_event_t *
85afs_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
118void
119afs_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
133int
134afs_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 */
149int
150afs_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
174int
175afs_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}