]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_synch.c
   2  * Copyright (c) 2000-2020 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29  * Mach Operating System 
  30  * Copyright (c) 1987 Carnegie-Mellon University 
  31  * All rights reserved.  The CMU software License Agreement specifies 
  32  * the terms and conditions for use and redistribution. 
  35 #include <sys/param.h> 
  36 #include <sys/systm.h> 
  37 #include <sys/proc_internal.h> 
  39 #include <sys/file_internal.h> 
  40 #include <sys/vnode.h> 
  41 #include <sys/kernel.h> 
  43 #include <kern/queue.h> 
  45 #include <kern/thread.h> 
  46 #include <kern/sched_prim.h> 
  49 #include <kern/cpu_number.h> 
  50 #include <vm/vm_kern.h> 
  52 #include <kern/task.h> 
  53 #include <mach/time_value.h> 
  54 #include <kern/locks.h> 
  55 #include <kern/policy_internal.h> 
  57 #include <sys/systm.h>                  /* for unix_syscall_return() */ 
  58 #include <libkern/OSAtomic.h> 
  60 extern void compute_averunnable(void *);        /* XXX */ 
  62 __attribute__((noreturn
)) 
  64 _sleep_continue( __unused 
void *parameter
, wait_result_t wresult
) 
  66         struct proc 
*p 
= current_proc(); 
  67         thread_t self  
= current_thread(); 
  71         int dropmutex
, spinmutex
; 
  73         ut 
= get_bsdthread_info(self
); 
  74         catch     = ut
->uu_pri 
& PCATCH
; 
  75         dropmutex 
= ut
->uu_pri 
& PDROP
; 
  76         spinmutex 
= ut
->uu_pri 
& PSPIN
; 
  79         case THREAD_TIMED_OUT
: 
  84                  * Posix implies any signal should be delivered 
  85                  * first, regardless of whether awakened due 
  92         case THREAD_INTERRUPTED
: 
  94                         if (thread_should_abort(self
)) { 
  96                         } else if (SHOULDissignal(p
, ut
)) { 
  97                                 if ((sig 
= CURSIG(p
)) != 0) { 
  98                                         if (p
->p_sigacts
->ps_sigintr 
& sigmask(sig
)) { 
 104                                 if (thread_should_abort(self
)) { 
 107                         } else if ((ut
->uu_flag 
& (UT_CANCELDISABLE 
| UT_CANCEL 
| UT_CANCELED
)) == UT_CANCEL
) { 
 108                                 /* due to thread cancel */ 
 117         if (error 
== EINTR 
|| error 
== ERESTART
) { 
 118                 act_set_astbsd(self
); 
 121         if (ut
->uu_mtx 
&& !dropmutex
) { 
 123                         lck_mtx_lock_spin(ut
->uu_mtx
); 
 125                         lck_mtx_lock(ut
->uu_mtx
); 
 131         unix_syscall_return((*ut
->uu_continuation
)(error
)); 
 135  * Give up the processor till a wakeup occurs 
 136  * on chan, at which time the process 
 137  * enters the scheduling queue at priority pri. 
 138  * The most important effect of pri is that when 
 139  * pri<=PZERO a signal cannot disturb the sleep; 
 140  * if pri>PZERO signals will be processed. 
 141  * If pri&PCATCH is set, signals will cause sleep 
 142  * to return 1, rather than longjmp. 
 143  * Callers of this routine must be prepared for 
 144  * premature return, and check that the reason for 
 145  * sleeping has gone away. 
 147  * if msleep was the entry point, than we have a mutex to deal with 
 149  * The mutex is unlocked before the caller is blocked, and 
 150  * relocked before msleep returns unless the priority includes the PDROP 
 151  * flag... if PDROP is specified, _sleep returns with the mutex unlocked 
 152  * regardless of whether it actually blocked or not. 
 161         int             (*continuation
)(int), 
 165         thread_t self 
= current_thread(); 
 168         int dropmutex  
= pri 
& PDROP
; 
 169         int spinmutex  
= pri 
& PSPIN
; 
 173         ut 
= get_bsdthread_info(self
); 
 176         p
->p_priority 
= pri 
& PRIMASK
; 
 177         /* It can still block in proc_exit() after the teardown. */ 
 178         if (p
->p_stats 
!= NULL
) { 
 179                 OSIncrementAtomicLong(&p
->p_stats
->p_ru
.ru_nvcsw
); 
 183                 catch = THREAD_ABORTSAFE
; 
 185                 catch = THREAD_UNINT
; 
 188         /* set wait message & channel */ 
 190         ut
->uu_wmesg 
= wmsg 
? wmsg 
: "unknown"; 
 192         if (mtx 
!= NULL 
&& chan 
!= NULL 
&& (thread_continue_t
)continuation 
== THREAD_CONTINUE_NULL
) { 
 196                         flags 
= LCK_SLEEP_UNLOCK
; 
 198                         flags 
= LCK_SLEEP_DEFAULT
; 
 202                         flags 
|= LCK_SLEEP_SPIN
; 
 206                         wait_result 
= lck_mtx_sleep_deadline(mtx
, flags
, chan
, catch, abstime
); 
 208                         wait_result 
= lck_mtx_sleep(mtx
, flags
, chan
, catch); 
 212                         assert_wait_deadline(chan
, catch, abstime
); 
 218                 if (catch == THREAD_ABORTSAFE
) { 
 219                         if (SHOULDissignal(p
, ut
)) { 
 220                                 if ((sig 
= CURSIG(p
)) != 0) { 
 221                                         if (clear_wait(self
, THREAD_INTERRUPTED
) == KERN_FAILURE
) { 
 224                                         if (p
->p_sigacts
->ps_sigintr 
& sigmask(sig
)) { 
 229                                         if (mtx 
&& !dropmutex
) { 
 231                                                         lck_mtx_lock_spin(mtx
); 
 239                         if (thread_should_abort(self
)) { 
 240                                 if (clear_wait(self
, THREAD_INTERRUPTED
) == KERN_FAILURE
) { 
 245                                 if (mtx 
&& !dropmutex
) { 
 247                                                 lck_mtx_lock_spin(mtx
); 
 258                 if ((thread_continue_t
)continuation 
!= THREAD_CONTINUE_NULL
) { 
 259                         ut
->uu_continuation 
= continuation
; 
 260                         ut
->uu_pri  
= (uint16_t)pri
; 
 262                         (void) thread_block(_sleep_continue
); 
 266                 wait_result 
= thread_block(THREAD_CONTINUE_NULL
); 
 268                 if (mtx 
&& !dropmutex
) { 
 270                                 lck_mtx_lock_spin(mtx
); 
 277         switch (wait_result
) { 
 278         case THREAD_TIMED_OUT
: 
 281         case THREAD_AWAKENED
: 
 284                  * Posix implies any signal should be delivered 
 285                  * first, regardless of whether awakened due 
 286                  * to receiving event. 
 288                 if (catch != THREAD_ABORTSAFE
) { 
 292         case THREAD_INTERRUPTED
: 
 293                 if (catch == THREAD_ABORTSAFE
) { 
 294                         if (thread_should_abort(self
)) { 
 296                         } else if (SHOULDissignal(p
, ut
)) { 
 297                                 if ((sig 
= CURSIG(p
)) != 0) { 
 298                                         if (p
->p_sigacts
->ps_sigintr 
& sigmask(sig
)) { 
 304                                 if (thread_should_abort(self
)) { 
 307                         } else if ((ut
->uu_flag 
& (UT_CANCELDISABLE 
| UT_CANCEL 
| UT_CANCELED
)) == UT_CANCEL
) { 
 308                                 /* due to thread cancel */ 
 317         if (error 
== EINTR 
|| error 
== ERESTART
) { 
 318                 act_set_astbsd(self
); 
 331         return _sleep((caddr_t
)chan
, pri
, (char *)NULL
, 0, (int (*)(int))0, (lck_mtx_t 
*)0); 
 341         int             (*continuation
)(int)) 
 343         u_int64_t       abstime 
= 0; 
 346                 clock_interval_to_deadline(timo
, NSEC_PER_SEC 
/ hz
, &abstime
); 
 349         return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, continuation
, mtx
); 
 360         u_int64_t       abstime 
= 0; 
 362         if (ts 
&& (ts
->tv_sec 
|| ts
->tv_nsec
)) { 
 363                 nanoseconds_to_absolutetime((uint64_t)ts
->tv_sec 
* NSEC_PER_SEC 
+ ts
->tv_nsec
, &abstime 
); 
 364                 clock_absolutetime_interval_to_deadline( abstime
, &abstime 
); 
 367         return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, (int (*)(int))0, mtx
); 
 378         return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, (int (*)(int))0, mtx
); 
 388         u_int64_t       abstime 
= 0; 
 391                 clock_interval_to_deadline(timo
, NSEC_PER_SEC 
/ hz
, &abstime
); 
 393         return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, (int (*)(int))0, (lck_mtx_t 
*)0); 
 402         int             (*continuation
)(int)) 
 404         u_int64_t       abstime 
= 0; 
 407                 clock_interval_to_deadline(timo
, NSEC_PER_SEC 
/ hz
, &abstime
); 
 409         return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, continuation
, (lck_mtx_t 
*)0); 
 418         int             (*continuation
)(int)) 
 420         return _sleep((caddr_t
)chan
, pri
, wmsg
, abstime
, continuation
, (lck_mtx_t 
*)0); 
 424  * Wake up all processes sleeping on chan. 
 429         thread_wakeup((caddr_t
)chan
); 
 433  * Wake up the first process sleeping on chan. 
 435  * Be very sure that the first process is really 
 436  * the right one to wakeup. 
 439 wakeup_one(caddr_t chan
) 
 441         thread_wakeup_one((caddr_t
)chan
); 
 445  * Compute the priority of a process when running in user mode. 
 446  * Arrange to reschedule if the resulting priority is better 
 447  * than that of the current process. 
 450 resetpriority(struct proc 
*p
) 
 452         (void)task_importance(p
->task
, -p
->p_nice
); 
 455 struct loadavg averunnable 
= 
 456 { {0, 0, 0}, FSCALE 
};                  /* load average, of runnable procs */ 
 458  * Constants for averages over 1, 5, and 15 minutes 
 459  * when sampling at 5 second intervals. 
 461 static fixpt_t cexp
[3] = { 
 462         (fixpt_t
)(0.9200444146293232 * FSCALE
), /* exp(-1/12) */ 
 463         (fixpt_t
)(0.9834714538216174 * FSCALE
), /* exp(-1/60) */ 
 464         (fixpt_t
)(0.9944598480048967 * FSCALE
), /* exp(-1/180) */ 
 468 compute_averunnable(void *arg
) 
 470         unsigned int            nrun 
= *(unsigned int *)arg
; 
 471         struct loadavg          
*avg 
= &averunnable
; 
 474         for (i 
= 0; i 
< 3; i
++) { 
 475                 avg
->ldavg
[i
] = (cexp
[i
] * avg
->ldavg
[i
] + 
 476                     nrun 
* FSCALE 
* (FSCALE 
- cexp
[i
])) >> FSHIFT
;