]>
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
)) {
105 thread_apc_set(th_act
, bsd_ast
);
107 thread_ast_set(th_act
, AST_BSD
);
112 thread_cancel_timer();
115 /* We should never get here without funnel, so we should not grab again */
116 thread_funnel_set(kernel_flock
, TRUE
);
118 unix_syscall_return((*ut
->uu_continuation
)(error
));
122 * Give up the processor till a wakeup occurs
123 * on chan, at which time the process
124 * enters the scheduling queue at priority pri.
125 * The most important effect of pri is that when
126 * pri<=PZERO a signal cannot disturb the sleep;
127 * if pri>PZERO signals will be processed.
128 * If pri&PCATCH is set, signals will cause sleep
129 * to return 1, rather than longjmp.
130 * Callers of this routine must be prepared for
131 * premature return, and check that the reason for
132 * sleeping has gone away.
139 _sleep(chan
, pri
, wmsg
, timo
, continuation
)
144 int (*continuation
)();
146 register struct proc
*p
;
147 register thread_t thread
= current_thread();
150 int sig
, catch = pri
& PCATCH
;
151 int sigttblock
= pri
& PTTYBLOCK
;
157 th_act
= current_act();
158 ut
= get_bsdthread_info(th_act
);
162 if (KTRPOINT(p
, KTR_CSW
))
163 ktrcsw(p
->p_tracep
, 1, 0);
165 p
->p_priority
= pri
& PRIMASK
;
168 assert_wait(chan
, (catch) ? THREAD_ABORTSAFE
: THREAD_UNINT
);
171 thread_set_timer(timo
, NSEC_PER_SEC
/ hz
);
173 * We start our timeout
174 * before calling CURSIG, as we could stop there, and a wakeup
175 * or a SIGCONT (or both) could occur while we were stopped.
176 * A SIGCONT would cause us to be marked as SSLEEP
177 * without resuming us, thus we must be ready for sleep
178 * when CURSIG is called. If the wakeup happens while we're
179 * stopped, p->p_wchan will be 0 upon return from CURSIG.
183 if (SHOULDissignal(p
,ut
)) {
184 if (sig
= CURSIG(p
)) {
185 clear_wait(thread
, THREAD_INTERRUPTED
);
186 /* if SIGTTOU or SIGTTIN then block till SIGCONT */
187 if (sigttblock
&& ((sig
== SIGTTOU
) || (sig
== SIGTTIN
))) {
188 p
->p_flag
|= P_TTYSLEEP
;
189 /* reset signal bits */
190 clear_sigbits(p
, sig
);
191 assert_wait(&p
->p_siglist
, THREAD_ABORTSAFE
);
192 /* assert wait can block and SIGCONT should be checked */
193 if (p
->p_flag
& P_TTYSLEEP
)
195 /* return with success */
199 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
207 if (thread_should_abort(current_thread())) {
208 clear_wait(thread
, THREAD_INTERRUPTED
);
213 if (get_thread_waitevent(thread
) == 0) { /*already happened */
221 thread
->wait_mesg
= wmsg
;
224 p
->p_stats
->p_ru
.ru_nvcsw
++;
226 if (continuation
!= (int (*)()) 0 ) {
227 ut
->uu_continuation
= continuation
;
230 thread_block(_sleep_continue
);
237 thread
->wait_mesg
= NULL
;
239 switch (get_thread_waitresult(thread
)) {
240 case THREAD_TIMED_OUT
:
243 case THREAD_AWAKENED
:
245 * Posix implies any signal should be delivered
246 * first, regardless of whether awakened due
247 * to receiving event.
251 /* else fall through */
252 case THREAD_INTERRUPTED
:
255 if (thread_should_abort(current_thread())) {
257 } else if (SHOULDissignal(p
,ut
)) {
258 if (sig
= CURSIG(p
)) {
259 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
264 if (thread_should_abort(current_thread())) {
274 if ((error
== EINTR
) || (error
== ERESTART
)) {
276 thread_apc_set(th_act
, bsd_ast
);
278 thread_ast_set(th_act
, AST_BSD
);
283 thread_cancel_timer();
293 return (_sleep((caddr_t
)chan
, pri
, (char *)NULL
, 0, (void (*)())0 ));
297 int tsleep(chan
, pri
, wmsg
, timo
)
303 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, (void (*)())0 ));
306 int tsleep0(chan
, pri
, wmsg
, timo
, continuation
)
311 int (*continuation
)();
313 #if defined (__i386__)
314 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, (void (*)())0 ));
316 return(_sleep((caddr_t
)chan
, pri
, wmsg
, timo
, continuation
));
321 * Wake up all processes sleeping on chan.
327 thread_wakeup_prim((caddr_t
)chan
,FALSE
, THREAD_AWAKENED
);
331 * Wake up the first process sleeping on chan.
333 * Be very sure that the first process is really
334 * the right one to wakeup.
337 register caddr_t chan
;
339 thread_wakeup_prim((caddr_t
)chan
, TRUE
, THREAD_AWAKENED
);
343 * Compute the priority of a process when running in user mode.
344 * Arrange to reschedule if the resulting priority is better
345 * than that of the current process.
349 register struct proc
*p
;
354 newpri
= BASEPRI_USER
+
355 (p
->p_nice
* (MAXPRI_USER
- BASEPRI_USER
)) / PRIO_MIN
;
357 newpri
= BASEPRI_USER
-
358 (p
->p_nice
* BASEPRI_USER
) / PRIO_MAX
;
360 (void)task_priority(p
->task
, newpri
, TRUE
);