Free memory from afs_events
[openafs.git] / src / afs / AIX / 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 #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
18 static char waitV;
19
20 static void
21 AfsWaitHack(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
31 void
32 afs_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 */
39 void
40 afs_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  */
56 int
57 afs_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
85 afs_event_t *afs_evhasht[AFS_EVHASHSIZE];       /* Hash table for events */
86 #define afs_evhash(event)       (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1));
87 int afs_evhashcnt = 0;
88
89 /* Get and initialize event structure corresponding to lwp event (i.e. address)
90  * */
91 static afs_event_t *
92 afs_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
126 void
127 afs_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
144 int
145 afs_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  */
160 int
161 afs_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
200 int
201 afs_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 }