]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_synch.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Mach Operating System
24 * Copyright (c) 1987 Carnegie-Mellon University
25 * All rights reserved. The CMU software License Agreement specifies
26 * the terms and conditions for use and redistribution.
29 #include <sys/param.h>
30 #include <sys/systm.h>
34 #include <sys/vnode.h>
35 #include <sys/kernel.h>
38 #include <machine/spl.h>
40 #include <kern/queue.h>
42 #include <kern/thread.h>
45 #include <kern/cpu_number.h>
46 #include <vm/vm_kern.h>
48 #include <kern/task.h>
49 #include <mach/time_value.h>
53 register struct proc
*p
;
54 register thread_t thread
= current_thread();
60 th_act
= current_act();
61 ut
= get_bsdthread_info(th_act
);
62 catch = ut
->uu_pri
& PCATCH
;
66 thread
->wait_mesg
= NULL
;
68 switch (get_thread_waitresult(thread
)) {
69 case THREAD_TIMED_OUT
:
74 * Posix implies any signal should be delivered
75 * first, regardless of whether awakened due
80 /* else fall through */
81 case THREAD_INTERRUPTED
:
84 if (thread_should_abort(current_thread())) {
86 } else if (SHOULDissignal(p
,ut
)) {
87 if (sig
= CURSIG(p
)) {
88 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
93 if (thread_should_abort(current_thread())) {
103 if ((error
== EINTR
) || (error
== ERESTART
)) {
104 thread_ast_set(th_act
, AST_BSD
);
108 thread_cancel_timer();
110 unix_syscall_return((*ut
->uu_continuation
)(error
));
114 * Give up the processor till a wakeup occurs
115 * on chan, at which time the process
116 * enters the scheduling queue at priority pri.
117 * The most important effect of pri is that when
118 * pri<=PZERO a signal cannot disturb the sleep;
119 * if pri>PZERO signals will be processed.
120 * If pri&PCATCH is set, signals will cause sleep
121 * to return 1, rather than longjmp.
122 * Callers of this routine must be prepared for
123 * premature return, and check that the reason for
124 * sleeping has gone away.
131 _sleep(chan
, pri
, wmsg
, timo
, continuation
, preassert
)
136 int (*continuation
)();
139 register struct proc
*p
;
140 register thread_t thread
= current_thread();
143 int sig
, catch = pri
& PCATCH
;
144 int sigttblock
= pri
& PTTYBLOCK
;
150 th_act
= current_act();
151 ut
= get_bsdthread_info(th_act
);
155 if (KTRPOINT(p
, KTR_CSW
))
156 ktrcsw(p
->p_tracep
, 1, 0);
158 p
->p_priority
= pri
& PRIMASK
;
161 /* it is already pre asserted */
163 assert_wait(chan
, (catch) ? THREAD_ABORTSAFE
: THREAD_UNINT
);
167 thread_set_timer(timo
, NSEC_PER_SEC
/ hz
);
170 * We start our timeout
171 * before calling CURSIG, as we could stop there, and a wakeup
172 * or a SIGCONT (or both) could occur while we were stopped.
173 * A SIGCONT would cause us to be marked as SSLEEP
174 * without resuming us, thus we must be ready for sleep
175 * when CURSIG is called. If the wakeup happens while we're
176 * stopped, p->p_wchan will be 0 upon return from CURSIG.
180 if (SHOULDissignal(p
,ut
)) {
181 if (sig
= CURSIG(p
)) {
182 clear_wait(thread
, THREAD_INTERRUPTED
);
183 /* if SIGTTOU or SIGTTIN then block till SIGCONT */
184 if (sigttblock
&& ((sig
== SIGTTOU
) || (sig
== SIGTTIN
))) {
185 p
->p_flag
|= P_TTYSLEEP
;
186 /* reset signal bits */
187 clear_sigbits(p
, sig
);
188 assert_wait(&p
->p_siglist
, THREAD_ABORTSAFE
);
189 /* assert wait can block and SIGCONT should be checked */
190 if (p
->p_flag
& P_TTYSLEEP
)
192 /* return with success */
196 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
204 if (thread_should_abort(current_thread())) {
205 clear_wait(thread
, THREAD_INTERRUPTED
);
210 if (get_thread_waitevent(thread
) == 0) { /*already happened */
218 thread
->wait_mesg
= wmsg
;
221 p
->p_stats
->p_ru
.ru_nvcsw
++;
223 if (continuation
!= (int (*)()) 0 ) {
224 ut
->uu_continuation
= continuation
;
227 thread_block(_sleep_continue
);
234 thread
->wait_mesg
= NULL
;
236 switch (get_thread_waitresult(thread
)) {
237 case THREAD_TIMED_OUT
:
240 case THREAD_AWAKENED
:
242 * Posix implies any signal should be delivered
243 * first, regardless of whether awakened due
244 * to receiving event.
248 /* else fall through */
249 case THREAD_INTERRUPTED
:
252 if (thread_should_abort(current_thread())) {
254 } else if (SHOULDissignal(p
,ut
)) {
255 if (sig
= CURSIG(p
)) {
256 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
261 if (thread_should_abort(current_thread())) {
271 if ((error
== EINTR
) || (error
== ERESTART
)) {
272 thread_ast_set(th_act
, AST_BSD
);
276 thread_cancel_timer();
286 return (_sleep((caddr_t
)chan
, pri
, (char *)NULL
, 0, (void (*)())0, 0));
290 int tsleep(chan
, pri
, wmsg
, timo
)
296 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, (void (*)())0, 0));
299 int tsleep0(chan
, pri
, wmsg
, timo
, continuation
)
304 int (*continuation
)();
306 #if defined (__i386__)
307 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, (void (*)())0, 0));
309 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, continuation
, 0));
313 /* tsleeps without assertwait or thread block */
314 int tsleep1(chan
, pri
, wmsg
, timo
, continuation
)
319 int (*continuation
)();
321 #if defined (__i386__)
322 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, (void (*)())0, 1));
324 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, continuation
, 1));
329 * Wake up all processes sleeping on chan.
335 thread_wakeup_prim((caddr_t
)chan
,FALSE
, THREAD_AWAKENED
);
339 * Wake up the first process sleeping on chan.
341 * Be very sure that the first process is really
342 * the right one to wakeup.
345 register caddr_t chan
;
347 thread_wakeup_prim((caddr_t
)chan
, TRUE
, THREAD_AWAKENED
);
351 * Compute the priority of a process when running in user mode.
352 * Arrange to reschedule if the resulting priority is better
353 * than that of the current process.
357 register struct proc
*p
;
359 (void)task_importance(p
->task
, -p
->p_nice
);