Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / OBSD / osi_sleep.c
1 /*
2 * $Id$
3 */
4
5 /*
6 copyright 2002
7 the regents of the university of michigan
8 all rights reserved
9
10 permission is granted to use, copy, create derivative works
11 and redistribute this software and such derivative works
12 for any purpose, so long as the name of the university of
13 michigan is not used in any advertising or publicity
14 pertaining to the use or distribution of this software
15 without specific, written prior authorization. if the
16 above copyright notice or any other identification of the
17 university of michigan is included in any copy of any
18 portion of this software, then the disclaimer below must
19 also be included.
20
21 this software is provided as is, without representation
22 from the university of michigan as to its fitness for any
23 purpose, and without warranty by the university of
24 michigan of any kind, either express or implied, including
25 without limitation the implied warranties of
26 merchantability and fitness for a particular purpose. the
27 regents of the university of michigan shall not be liable
28 for any damages, including special, indirect, incidental, or
29 consequential damages, with respect to any claim arising
30 out of or in connection with the use of the software, even
31 if it has been or is hereafter advised of the possibility of
32 such damages.
33 */
34
35 /*
36 * Copyright 2000, International Business Machines Corporation and others.
37 * All Rights Reserved.
38 *
39 * This software has been released under the terms of the IBM Public
40 * License. For details, see the LICENSE file in the top-level source
41 * directory or online at http://www.openafs.org/dl/license10.html
42 */
43
44 #include <afsconfig.h>
45 #include "afs/param.h"
46
47
48 #include "afs/sysincludes.h" /* Standard vendor system headers */
49 #include "afs/afsincludes.h" /* Afs-based standard headers */
50 #include "afs/afs_stats.h" /* afs statistics */
51
52 static char waitV;
53
54
55 time_t
56 osi_Time()
57 {
58 struct timeval now;
59
60 getmicrotime(&now);
61 return now.tv_sec;
62 }
63
64 /* cancel osi_Wait */
65 void
66 afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
67 {
68 caddr_t proc;
69
70 AFS_STATCNT(osi_CancelWait);
71 proc = achandle->proc;
72 if (proc == NULL)
73 return;
74 achandle->proc = NULL;
75 wakeup(&waitV);
76 }
77
78 /* afs_osi_Wait
79 * Waits for data on ahandle, or ams ms later. ahandle may be null.
80 * Returns 0 if timeout and EINTR if signalled.
81 */
82 int
83 afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
84 {
85 int timo, code = 0;
86 struct timeval atv, now, endTime;
87
88 AFS_STATCNT(osi_Wait);
89
90 atv.tv_sec = ams / 1000;
91 atv.tv_usec = (ams % 1000) * 1000;
92 getmicrotime(&now);
93 timeradd(&atv, &now, &endTime);
94
95 if (ahandle)
96 ahandle->proc = (caddr_t) curproc;
97 AFS_ASSERT_GLOCK();
98 AFS_GUNLOCK();
99
100 do {
101 timersub(&endTime, &now, &atv);
102 timo = atv.tv_sec * hz + atv.tv_usec * hz / 1000000 + 1;
103 if (aintok) {
104 code = tsleep(&waitV, PCATCH | PVFS, "afs_W1", timo);
105 if (code)
106 code = (code == EWOULDBLOCK) ? 0 : EINTR;
107 } else
108 tsleep(&waitV, PVFS, "afs_W2", timo);
109
110 /* if we were cancelled, quit now */
111 if (ahandle && (ahandle->proc == NULL)) {
112 /* we've been signalled */
113 break;
114 }
115 getmicrotime(&now);
116 } while (timercmp(&now, &endTime, <));
117
118 AFS_GLOCK();
119 return code;
120 }
121
122 afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
123 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
124 int afs_evhashcnt = 0;
125
126 /* Get and initialize event structure corresponding to lwp event (i.e. address)
127 * */
128 static afs_event_t *
129 afs_getevent(char *event)
130 {
131 afs_event_t *evp, *newp = 0;
132 int hashcode;
133
134 AFS_ASSERT_GLOCK();
135 hashcode = afs_evhash(event);
136 evp = afs_evhasht[hashcode];
137 while (evp) {
138 if (evp->event == event) {
139 evp->refcount++;
140 return evp;
141 }
142 if (evp->refcount == 0)
143 newp = evp;
144 evp = evp->next;
145 }
146 if (!newp) {
147 newp = osi_AllocSmallSpace(sizeof(afs_event_t));
148 afs_evhashcnt++;
149 newp->next = afs_evhasht[hashcode];
150 afs_evhasht[hashcode] = newp;
151 newp->seq = 0;
152 }
153 newp->event = event;
154 newp->refcount = 1;
155 return newp;
156 }
157
158 /* Release the specified event */
159 #define relevent(evp) ((evp)->refcount--)
160
161 int
162 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
163 {
164 int code = 0;
165 struct afs_event *evp;
166 int seq, prio;
167 int ticks;
168
169 evp = afs_getevent(event);
170 seq = evp->seq;
171 AFS_GUNLOCK();
172 if (aintok)
173 prio = PCATCH | PPAUSE;
174 else
175 prio = PVFS;
176 ticks = (ams * afs_hz) / 1000;
177 code = tsleep(event, prio, "afs_osi_TimedSleep", ticks);
178 if (seq == evp->seq)
179 code = EINTR;
180 relevent(evp);
181 AFS_GLOCK();
182 return code;
183 }
184
185 void
186 afs_osi_Sleep(void *event)
187 {
188 AFS_ASSERT_GLOCK();
189 AFS_GUNLOCK();
190 tsleep(event, PVFS, "afsslp", 0);
191 AFS_GLOCK();
192 }
193
194 int
195 afs_osi_SleepSig(void *event)
196 {
197 afs_osi_Sleep(event);
198 return 0;
199 }
200
201 int
202 afs_osi_Wakeup(void *event)
203 {
204 wakeup(event);
205 return 1;
206 }