Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / AIX / 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#include <afsconfig.h>
11#include "afs/param.h"
12
13
14#include "afs/sysincludes.h" /* Standard vendor system headers */
15#include "afsincludes.h" /* Afs-based standard headers */
16#include "afs/afs_stats.h" /* afs statistics */
17
18static char waitV;
19
20static void
21AfsWaitHack(struct trb *trb)
22{
23#if 0
24/* this gets called at interrupt context; let's not tempt fate... */
25 AFS_STATCNT(WaitHack);
26#endif
27
28 e_clear_wait(trb->func_data, THREAD_TIMED_OUT);
29}
30
31void
32afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
33{
34 AFS_STATCNT(osi_InitWaitHandle);
35 achandle->proc = (caddr_t) 0;
36}
37
38/* cancel osi_Wait */
39void
40afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle)
41{
42 caddr_t proc;
43
44 AFS_STATCNT(osi_CancelWait);
45 proc = achandle->proc;
46 if (proc == 0)
47 return;
48 achandle->proc = (caddr_t) 0; /* so dude can figure out he was signalled */
49 afs_osi_Wakeup(&waitV);
50}
51
52/* afs_osi_Wait
53 * Waits for data on ahandle, or ams ms later. ahandle may be null.
54 * Returns 0 if timeout and EINTR if signalled.
55 */
56int
57afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
58{
59 int code;
60 afs_int32 endTime, tid;
61
62 AFS_STATCNT(osi_Wait);
63 endTime = osi_Time() + (ams / 1000);
64 if (ahandle)
65 ahandle->proc = (caddr_t) thread_self();
66 do {
67 AFS_ASSERT_GLOCK();
68 code = 0;
69 code = afs_osi_TimedSleep(&waitV, ams, aintok);
70
71 if (code)
72 break; /* if something happened, quit now */
73 /* if we we're cancelled, quit now */
74 if (ahandle && (ahandle->proc == (caddr_t) 0)) {
75 /* we've been signalled */
76 break;
77 }
78 } while (osi_Time() < endTime);
79 return code;
80}
81
82
83
84
85afs_event_t *afs_evhasht[AFS_EVHASHSIZE]; /* Hash table for events */
86#define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
87int afs_evhashcnt = 0;
88
89/* Get and initialize event structure corresponding to lwp event (i.e. address)
90 * */
91static afs_event_t *
92afs_getevent(char *event)
93{
94 afs_event_t *evp, *newp = 0;
95 int hashcode;
96
97 AFS_ASSERT_GLOCK();
98 hashcode = afs_evhash(event);
99 evp = afs_evhasht[hashcode];
100 while (evp) {
101 if (evp->event == event) {
102 evp->refcount++;
103 return evp;
104 }
105 if (evp->refcount == 0)
106 newp = evp;
107 evp = evp->next;
108 }
109 if (!newp) {
110 newp = (afs_event_t *) xmalloc(sizeof(afs_event_t), 5, pinned_heap);
111 afs_evhashcnt++;
112 newp->next = afs_evhasht[hashcode];
113 afs_evhasht[hashcode] = newp;
114 newp->cond = EVENT_NULL;
115 newp->seq = 0;
116 }
117 newp->event = event;
118 newp->refcount = 1;
119 return newp;
120}
121
122/* Release the specified event */
123#define relevent(evp) ((evp)->refcount--)
124
125
126void
127afs_osi_Sleep(void *event)
128{
129 struct afs_event *evp;
130 int seq;
131
132 evp = afs_getevent(event);
133 seq = evp->seq;
134 while (seq == evp->seq) {
135 AFS_ASSERT_GLOCK();
136 e_assert_wait(&evp->cond, 0);
137 AFS_GUNLOCK();
138 e_block_thread();
139 AFS_GLOCK();
140 }
141 relevent(evp);
142}
143
144int
145afs_osi_SleepSig(void *event)
146{
147 afs_osi_Sleep(event);
148 return 0;
149}
150
151/* afs_osi_TimedSleep
152 *
153 * Arguments:
154 * event - event to sleep on
155 * ams --- max sleep time in milliseconds
156 * aintok - 1 if should sleep interruptibly
157 *
158 * Returns 0 if timeout and EINTR if signalled.
159 */
160int
161afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
162{
163 int code = 0;
164 struct afs_event *evp;
165 struct timestruc_t ticks;
166 struct trb *trb;
167 int rc;
168
169 ticks.tv_sec = ams / 1000;
170 ticks.tv_nsec = (ams - (ticks.tv_sec * 1000)) * 1000000;
171
172
173 evp = afs_getevent(event);
174
175 trb = talloc();
176 if (trb == NULL)
177 osi_Panic("talloc returned NULL");
178 trb->flags = 0;
179 trb->func = AfsWaitHack;
180 trb->eventlist = EVENT_NULL;
181 trb->ipri = INTTIMER;
182 trb->func_data = thread_self();
183 trb->timeout.it_value = ticks;
184
185 e_assert_wait(&evp->cond, aintok);
186 AFS_GUNLOCK();
187 tstart(trb);
188 rc = e_block_thread();
189 while (tstop(trb));
190 if (rc == THREAD_INTERRUPTED)
191 code = EINTR;
192 tfree(trb);
193 AFS_GLOCK();
194
195 relevent(evp);
196 return code;
197}
198
199
200int
201afs_osi_Wakeup(void *event)
202{
203 int ret = 1;
204 struct afs_event *evp;
205
206 evp = afs_getevent(event);
207 if (evp->refcount > 1) {
208 evp->seq++;
209 e_wakeup(&evp->cond);
210 ret = 0;
211 }
212 relevent(evp);
213 return ret;
214}