]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_synch.c
2 * Copyright (c) 2000-2001 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>
43 #include <kern/sched_prim.h>
46 #include <kern/cpu_number.h>
47 #include <vm/vm_kern.h>
49 #include <kern/task.h>
50 #include <mach/time_value.h>
54 #include <sys/ktrace.h>
60 register struct proc
*p
;
61 register thread_t self
= current_act();
66 ut
= get_bsdthread_info(self
);
67 catch = ut
->uu_pri
& PCATCH
;
70 switch (get_thread_waitresult(self
)) {
71 case THREAD_TIMED_OUT
:
76 * Posix implies any signal should be delivered
77 * first, regardless of whether awakened due
82 /* else fall through */
83 case THREAD_INTERRUPTED
:
85 if (thread_should_abort(self
)) {
87 } else if (SHOULDissignal(p
,ut
)) {
88 if (sig
= CURSIG(p
)) {
89 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
94 if (thread_should_abort(self
)) {
103 if (error
== EINTR
|| error
== ERESTART
)
104 act_set_astbsd(self
);
107 thread_cancel_timer();
110 if (KTRPOINT(p
, KTR_CSW
))
111 ktrcsw(p
->p_tracep
, 0, 0, -1);
114 unix_syscall_return((*ut
->uu_continuation
)(error
));
118 * Give up the processor till a wakeup occurs
119 * on chan, at which time the process
120 * enters the scheduling queue at priority pri.
121 * The most important effect of pri is that when
122 * pri<=PZERO a signal cannot disturb the sleep;
123 * if pri>PZERO signals will be processed.
124 * If pri&PCATCH is set, signals will cause sleep
125 * to return 1, rather than longjmp.
126 * Callers of this routine must be prepared for
127 * premature return, and check that the reason for
128 * sleeping has gone away.
137 int (*continuation
)(int))
139 register struct proc
*p
;
140 register thread_t self
= current_act();
142 int sig
, catch = pri
& PCATCH
;
143 int sigttblock
= pri
& PTTYBLOCK
;
150 ut
= get_bsdthread_info(self
);
154 if (KTRPOINT(p
, KTR_CSW
))
155 ktrcsw(p
->p_tracep
, 1, 0, -1);
157 p
->p_priority
= pri
& PRIMASK
;
160 assert_wait_prim(chan
, NULL
, abstime
,
161 (catch) ? THREAD_ABORTSAFE
: THREAD_UNINT
);
164 thread_set_timer_deadline(abstime
);
167 * We start our timeout
168 * before calling CURSIG, as we could stop there, and a wakeup
169 * or a SIGCONT (or both) could occur while we were stopped.
170 * A SIGCONT would cause us to be marked as SSLEEP
171 * without resuming us, thus we must be ready for sleep
172 * when CURSIG is called. If the wakeup happens while we're
173 * stopped, p->p_wchan will be 0 upon return from CURSIG.
176 if (SHOULDissignal(p
,ut
)) {
177 if (sig
= CURSIG(p
)) {
178 if (clear_wait(self
, THREAD_INTERRUPTED
) == KERN_FAILURE
)
180 /* if SIGTTOU or SIGTTIN then block till SIGCONT */
181 if (sigttblock
&& ((sig
== SIGTTOU
) || (sig
== SIGTTIN
))) {
182 p
->p_flag
|= P_TTYSLEEP
;
183 /* reset signal bits */
184 clear_procsiglist(p
, sig
);
185 assert_wait(&p
->p_siglist
, THREAD_ABORTSAFE
);
186 /* assert wait can block and SIGCONT should be checked */
187 if (p
->p_flag
& P_TTYSLEEP
)
188 thread_block(THREAD_CONTINUE_NULL
);
189 /* return with success */
193 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
200 if (thread_should_abort(self
)) {
201 if (clear_wait(self
, THREAD_INTERRUPTED
) == KERN_FAILURE
)
206 if (get_thread_waitresult(self
) != THREAD_WAITING
) {
207 /*already happened */
215 p
->p_stats
->p_ru
.ru_nvcsw
++;
217 if ((thread_continue_t
)continuation
!= THREAD_CONTINUE_NULL
) {
218 ut
->uu_continuation
= continuation
;
220 ut
->uu_timo
= abstime
? 1: 0;
221 (void) thread_block(_sleep_continue
);
225 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
227 switch (wait_result
) {
228 case THREAD_TIMED_OUT
:
231 case THREAD_AWAKENED
:
233 * Posix implies any signal should be delivered
234 * first, regardless of whether awakened due
235 * to receiving event.
239 /* else fall through */
240 case THREAD_INTERRUPTED
:
242 if (thread_should_abort(self
)) {
244 } else if (SHOULDissignal(p
,ut
)) {
245 if (sig
= CURSIG(p
)) {
246 if (p
->p_sigacts
->ps_sigintr
& sigmask(sig
))
251 if (thread_should_abort(self
)) {
260 if (error
== EINTR
|| error
== ERESTART
)
261 act_set_astbsd(self
);
263 thread_cancel_timer();
266 if (KTRPOINT(p
, KTR_CSW
))
267 ktrcsw(p
->p_tracep
, 0, 0, -1);
277 return _sleep((caddr_t
)chan
, pri
, (char *)NULL
, 0, (int (*)(int))0);
287 u_int64_t abstime
= 0;
290 clock_interval_to_deadline(timo
, NSEC_PER_SEC
/ hz
, &abstime
);
291 return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, (int (*)(int))0);
300 int (*continuation
)(int))
302 u_int64_t abstime
= 0;
305 clock_interval_to_deadline(timo
, NSEC_PER_SEC
/ hz
, &abstime
);
306 return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, continuation
);
315 int (*continuation
)(int))
317 return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, 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.
338 register caddr_t chan
;
340 thread_wakeup_prim((caddr_t
)chan
, TRUE
, THREAD_AWAKENED
);
344 * Compute the priority of a process when running in user mode.
345 * Arrange to reschedule if the resulting priority is better
346 * than that of the current process.
350 register struct proc
*p
;
352 (void)task_importance(p
->task
, -p
->p_nice
);
355 struct loadavg averunnable
=
356 { {0, 0, 0}, FSCALE
}; /* load average, of runnable procs */
358 * Constants for averages over 1, 5, and 15 minutes
359 * when sampling at 5 second intervals.
361 static fixpt_t cexp
[3] = {
362 (fixpt_t
)(0.9200444146293232 * FSCALE
), /* exp(-1/12) */
363 (fixpt_t
)(0.9834714538216174 * FSCALE
), /* exp(-1/60) */
364 (fixpt_t
)(0.9944598480048967 * FSCALE
), /* exp(-1/180) */
372 struct loadavg
*avg
= &averunnable
;
374 for (i
= 0; i
< 3; i
++)
375 avg
->ldavg
[i
] = (cexp
[i
] * avg
->ldavg
[i
] +
376 nrun
* FSCALE
* (FSCALE
- cexp
[i
])) >> FSHIFT
;