2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "afs/param.h"
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 */
21 afs_osi_InitWaitHandle(struct afs_osi_WaitHandle
*achandle
)
23 AFS_STATCNT(osi_InitWaitHandle
);
24 achandle
->proc
= (caddr_t
) 0;
29 afs_osi_CancelWait(struct afs_osi_WaitHandle
*achandle
)
33 AFS_STATCNT(osi_CancelWait
);
34 proc
= achandle
->proc
;
37 achandle
->proc
= (caddr_t
) 0; /* so dude can figure out he was signalled */
38 afs_osi_Wakeup(&waitV
);
42 * Waits for data on ahandle, or ams ms later. ahandle may be null.
43 * Returns 0 if timeout and EINTR if signalled.
46 afs_osi_Wait(afs_int32 ams
, struct afs_osi_WaitHandle
*ahandle
, int aintok
)
49 afs_int32 endTime
, tid
;
50 struct proc
*p
= current_proc();
52 AFS_STATCNT(osi_Wait
);
53 endTime
= osi_Time() + (ams
/ 1000);
55 ahandle
->proc
= (caddr_t
) p
;
59 code
= afs_osi_TimedSleep(&waitV
, ams
, aintok
);
62 break; /* if something happened, quit now */
63 /* if we we're cancelled, quit now */
64 if (ahandle
&& (ahandle
->proc
== (caddr_t
) 0)) {
65 /* we've been signalled */
68 } while (osi_Time() < endTime
);
74 #ifdef AFS_DARWIN80_ENV
75 #define EVTLOCK_INIT(e) \
77 (e)->lck = lck_mtx_alloc_init(openafs_lck_grp, 0); \
80 #define EVTLOCK_LOCK(e) \
82 osi_Assert((e)->owner != current_thread()); \
83 lck_mtx_lock((e)->lck); \
84 osi_Assert((e)->owner == 0); \
85 (e)->owner = current_thread(); \
87 #define EVTLOCK_UNLOCK(e) \
89 osi_Assert((e)->owner == current_thread()); \
91 lck_mtx_unlock((e)->lck); \
93 #define EVTLOCK_DESTROY(e) lck_mtx_free((e)->lck, openafs_lck_grp)
95 #define EVTLOCK_INIT(e)
96 #define EVTLOCK_LOCK(e)
97 #define EVTLOCK_UNLOCK(e)
98 #define EVTLOCK_DESTROY(e)
100 afs_event_t
*afs_evhasht
[AFS_EVHASHSIZE
]; /* Hash table for events */
101 #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (AFS_EVHASHSIZE-1))
102 int afs_evhashcnt
= 0;
104 /* Get and initialize event structure corresponding to lwp event (i.e. address)
107 afs_getevent(char *event
)
109 afs_event_t
*evp
, *oevp
, *newp
= 0;
113 hashcode
= afs_evhash(event
);
114 evp
= afs_evhasht
[hashcode
];
117 if (evp
->event
== event
) {
121 if (evp
->refcount
== 0)
127 newp
= osi_AllocSmallSpace(sizeof(afs_event_t
));
129 newp
->next
= afs_evhasht
[hashcode
];
130 afs_evhasht
[hashcode
] = newp
;
140 /* Release the specified event */
141 #ifdef AFS_DARWIN80_ENV
142 #define relevent(evp) \
144 osi_Assert((evp)->owner == current_thread()); \
147 lck_mtx_unlock((evp)->lck); \
150 #define relevent(evp) ((evp)->refcount--)
155 afs_osi_Sleep(void *event
)
157 struct afs_event
*evp
;
160 evp
= afs_getevent(event
);
161 #ifdef AFS_DARWIN80_ENV
166 while (seq
== evp
->seq
) {
167 #ifdef AFS_DARWIN80_ENV
169 msleep(event
, evp
->lck
, PVFS
, "afs_osi_Sleep", NULL
);
170 evp
->owner
= current_thread();
174 /* this is probably safe for all versions, but testing is hard */
180 #ifdef AFS_DARWIN80_ENV
186 afs_osi_fullSigMask()
188 #ifndef AFS_DARWIN80_ENV
189 struct uthread
*user_thread
= (struct uthread
*)get_bsdthread_info(current_act());
191 /* Protect original sigmask */
192 if (!user_thread
->uu_oldmask
) {
193 /* Back up current sigmask */
194 user_thread
->uu_oldmask
= user_thread
->uu_sigmask
;
195 /* Mask all signals */
196 user_thread
->uu_sigmask
= ~(sigset_t
)0;
202 afs_osi_fullSigRestore()
204 #ifndef AFS_DARWIN80_ENV
205 struct uthread
*user_thread
= (struct uthread
*)get_bsdthread_info(current_act());
207 /* Protect original sigmask */
208 if (user_thread
->uu_oldmask
) {
209 /* Restore original sigmask */
210 user_thread
->uu_sigmask
= user_thread
->uu_oldmask
;
211 /* Clear the oldmask */
212 user_thread
->uu_oldmask
= (sigset_t
)0;
218 afs_osi_SleepSig(void *event
)
220 afs_osi_Sleep(event
);
224 /* afs_osi_TimedSleep
227 * event - event to sleep on
228 * ams --- max sleep time in milliseconds
229 * aintok - 1 if should sleep interruptibly
231 * Returns 0 if timeout and EINTR if signalled.
234 afs_osi_TimedSleep(void *event
, afs_int32 ams
, int aintok
)
237 struct afs_event
*evp
;
240 #ifdef AFS_DARWIN80_ENV
248 evp
= afs_getevent(event
);
251 #ifdef AFS_DARWIN80_ENV
253 prio
= PCATCH
| PPAUSE
;
256 ts
.tv_sec
= ams
/ 1000;
257 ts
.tv_nsec
= (ams
% 1000) * 1000000;
259 code
= msleep(event
, evp
->lck
, prio
, "afs_osi_TimedSleep", &ts
);
260 evp
->owner
= current_thread();
262 ticks
= (ams
* afs_hz
) / 1000;
263 /* this is probably safe for all versions, but testing is hard. */
264 /* using tsleep instead of assert_wait/thread_set_timer/thread_block
265 * allows shutdown to work in 1.4 */
266 /* lack of PCATCH does *not* prevent signal delivery, neither does
267 * a low priority. We would need to deal with ERESTART here if we
268 * wanted to mess with p->p_sigmask, and messing with p_sigignore is
269 * not the way to go.... (someone correct me if I'm wrong)
272 prio
= PCATCH
| PPAUSE
;
275 code
= tsleep(event
, prio
, "afs_osi_TimedSleep", ticks
);
282 #ifdef AFS_DARWIN80_ENV
290 afs_osi_Wakeup(void *event
)
292 struct afs_event
*evp
;
295 evp
= afs_getevent(event
);
296 if (evp
->refcount
> 1) {
298 /* this is probably safe for all versions, but testing is hard. */
307 shutdown_osisleep(void) {
308 struct afs_event
*evp
, *nevp
, **pevpp
;
310 for (i
=0; i
< AFS_EVHASHSIZE
; i
++) {
311 evp
= afs_evhasht
[i
];
312 pevpp
= &afs_evhasht
[i
];
316 if (evp
->refcount
== 0) {
317 EVTLOCK_DESTROY(evp
);
319 osi_FreeSmallSpace(evp
);
322 afs_warn("nonzero refcount in shutdown_osisleep()\n");