2 * Copyright (c) 2000-2015 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 * @OSF_FREE_COPYRIGHT@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub
63 * Thread management primitives implementation.
66 * Copyright (c) 1993 The University of Utah and
67 * the Computer Systems Laboratory (CSL). All rights reserved.
69 * Permission to use, copy, modify and distribute this software and its
70 * documentation is hereby granted, provided that both the copyright
71 * notice and this permission notice appear in all copies of the
72 * software, derivative works or modified versions, and any portions
73 * thereof, and that both notices appear in supporting documentation.
75 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
76 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
77 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
79 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
80 * improvements that they make and grant CSL redistribution rights.
84 #include <mach/mach_types.h>
85 #include <mach/boolean.h>
86 #include <mach/policy.h>
87 #include <mach/thread_info.h>
88 #include <mach/thread_special_ports.h>
89 #include <mach/thread_status.h>
90 #include <mach/time_value.h>
91 #include <mach/vm_param.h>
93 #include <machine/thread.h>
94 #include <machine/pal_routines.h>
95 #include <machine/limits.h>
97 #include <kern/kern_types.h>
98 #include <kern/kalloc.h>
99 #include <kern/cpu_data.h>
100 #include <kern/counters.h>
101 #include <kern/extmod_statistics.h>
102 #include <kern/ipc_mig.h>
103 #include <kern/ipc_tt.h>
104 #include <kern/mach_param.h>
105 #include <kern/machine.h>
106 #include <kern/misc_protos.h>
107 #include <kern/processor.h>
108 #include <kern/queue.h>
109 #include <kern/sched.h>
110 #include <kern/sched_prim.h>
111 #include <kern/sync_lock.h>
112 #include <kern/syscall_subr.h>
113 #include <kern/task.h>
114 #include <kern/thread.h>
115 #include <kern/host.h>
116 #include <kern/zalloc.h>
117 #include <kern/assert.h>
118 #include <kern/exc_resource.h>
119 #include <kern/telemetry.h>
120 #include <kern/policy_internal.h>
122 #include <corpses/task_corpse.h>
124 #include <kern/kpc.h>
127 #include <ipc/ipc_kmsg.h>
128 #include <ipc/ipc_port.h>
129 #include <bank/bank_types.h>
131 #include <vm/vm_kern.h>
132 #include <vm/vm_pageout.h>
134 #include <sys/kdebug.h>
135 #include <sys/bsdtask_info.h>
136 #include <mach/sdt.h>
139 * Exported interfaces
141 #include <mach/task_server.h>
142 #include <mach/thread_act_server.h>
143 #include <mach/mach_host_server.h>
144 #include <mach/host_priv_server.h>
145 #include <mach/mach_voucher_server.h>
146 #include <kern/policy_internal.h>
148 static struct zone
*thread_zone
;
149 static lck_grp_attr_t thread_lck_grp_attr
;
150 lck_attr_t thread_lck_attr
;
151 lck_grp_t thread_lck_grp
;
153 struct zone
*thread_qos_override_zone
;
155 decl_simple_lock_data(static,thread_stack_lock
)
156 static queue_head_t thread_stack_queue
;
158 decl_simple_lock_data(static,thread_terminate_lock
)
159 static queue_head_t thread_terminate_queue
;
161 static queue_head_t crashed_threads_queue
;
163 decl_simple_lock_data(static,thread_exception_lock
)
164 static queue_head_t thread_exception_queue
;
166 struct thread_exception_elt
{
168 task_t exception_task
;
169 thread_t exception_thread
;
172 static struct thread thread_template
, init_thread
;
174 static void sched_call_null(
179 extern void proc_exit(void *);
180 extern mach_exception_data_type_t
proc_encode_exit_exception_code(void *);
181 extern uint64_t get_dispatchqueue_offset_from_proc(void *);
182 extern int proc_selfpid(void);
183 extern char * proc_name_address(void *p
);
184 #endif /* MACH_BSD */
186 extern int disable_exc_resource
;
187 extern int audio_active
;
188 extern int debug_task
;
189 int thread_max
= CONFIG_THREAD_MAX
; /* Max number of threads */
190 int task_threadmax
= CONFIG_THREAD_MAX
;
192 static uint64_t thread_unique_id
= 100;
194 struct _thread_ledger_indices thread_ledgers
= { -1 };
195 static ledger_template_t thread_ledger_template
= NULL
;
196 static void init_thread_ledgers(void);
199 void jetsam_on_ledger_cpulimit_exceeded(void);
203 * Level (in terms of percentage of the limit) at which the CPU usage monitor triggers telemetry.
205 * (ie when any thread's CPU consumption exceeds 70% of the limit, start taking user
206 * stacktraces, aka micro-stackshots)
208 #define CPUMON_USTACKSHOTS_TRIGGER_DEFAULT_PCT 70
210 int cpumon_ustackshots_trigger_pct
; /* Percentage. Level at which we start gathering telemetry. */
211 void __attribute__((noinline
)) SENDING_NOTIFICATION__THIS_THREAD_IS_CONSUMING_TOO_MUCH_CPU(void);
214 * The smallest interval over which we support limiting CPU consumption is 1ms
216 #define MINIMUM_CPULIMIT_INTERVAL_MS 1
219 thread_bootstrap(void)
222 * Fill in a template thread for fast initialization.
226 thread_template
.thread_magic
= THREAD_MAGIC
;
227 #endif /* MACH_ASSERT */
229 thread_template
.runq
= PROCESSOR_NULL
;
231 thread_template
.ref_count
= 2;
233 thread_template
.reason
= AST_NONE
;
234 thread_template
.at_safe_point
= FALSE
;
235 thread_template
.wait_event
= NO_EVENT64
;
236 thread_template
.waitq
= NULL
;
237 thread_template
.wait_result
= THREAD_WAITING
;
238 thread_template
.options
= THREAD_ABORTSAFE
;
239 thread_template
.state
= TH_WAIT
| TH_UNINT
;
240 thread_template
.wake_active
= FALSE
;
241 thread_template
.continuation
= THREAD_CONTINUE_NULL
;
242 thread_template
.parameter
= NULL
;
244 thread_template
.importance
= 0;
245 thread_template
.sched_mode
= TH_MODE_NONE
;
246 thread_template
.sched_flags
= 0;
247 thread_template
.saved_mode
= TH_MODE_NONE
;
248 thread_template
.safe_release
= 0;
249 thread_template
.th_sched_bucket
= TH_BUCKET_RUN
;
251 thread_template
.sfi_class
= SFI_CLASS_UNSPECIFIED
;
252 thread_template
.sfi_wait_class
= SFI_CLASS_UNSPECIFIED
;
254 thread_template
.active
= 0;
255 thread_template
.started
= 0;
256 thread_template
.static_param
= 0;
257 thread_template
.policy_reset
= 0;
259 thread_template
.base_pri
= BASEPRI_DEFAULT
;
260 thread_template
.sched_pri
= 0;
261 thread_template
.max_priority
= 0;
262 thread_template
.task_priority
= 0;
263 thread_template
.promotions
= 0;
264 thread_template
.pending_promoter_index
= 0;
265 thread_template
.pending_promoter
[0] = NULL
;
266 thread_template
.pending_promoter
[1] = NULL
;
267 thread_template
.rwlock_count
= 0;
270 thread_template
.realtime
.deadline
= UINT64_MAX
;
272 thread_template
.quantum_remaining
= 0;
273 thread_template
.last_run_time
= 0;
274 thread_template
.last_made_runnable_time
= 0;
276 thread_template
.computation_metered
= 0;
277 thread_template
.computation_epoch
= 0;
279 #if defined(CONFIG_SCHED_TIMESHARE_CORE)
280 thread_template
.sched_stamp
= 0;
281 thread_template
.pri_shift
= INT8_MAX
;
282 thread_template
.sched_usage
= 0;
283 thread_template
.cpu_usage
= thread_template
.cpu_delta
= 0;
285 thread_template
.c_switch
= thread_template
.p_switch
= thread_template
.ps_switch
= 0;
287 thread_template
.bound_processor
= PROCESSOR_NULL
;
288 thread_template
.last_processor
= PROCESSOR_NULL
;
290 thread_template
.sched_call
= sched_call_null
;
292 timer_init(&thread_template
.user_timer
);
293 timer_init(&thread_template
.system_timer
);
294 thread_template
.user_timer_save
= 0;
295 thread_template
.system_timer_save
= 0;
296 thread_template
.vtimer_user_save
= 0;
297 thread_template
.vtimer_prof_save
= 0;
298 thread_template
.vtimer_rlim_save
= 0;
299 thread_template
.vtimer_qos_save
= 0;
302 thread_template
.wait_sfi_begin_time
= 0;
305 thread_template
.wait_timer_is_set
= FALSE
;
306 thread_template
.wait_timer_active
= 0;
308 thread_template
.depress_timer_active
= 0;
310 thread_template
.recover
= (vm_offset_t
)NULL
;
312 thread_template
.map
= VM_MAP_NULL
;
315 thread_template
.t_dtrace_predcache
= 0;
316 thread_template
.t_dtrace_vtime
= 0;
317 thread_template
.t_dtrace_tracing
= 0;
318 #endif /* CONFIG_DTRACE */
321 thread_template
.kperf_flags
= 0;
322 thread_template
.kperf_pet_gen
= 0;
323 thread_template
.kperf_c_switch
= 0;
324 thread_template
.kperf_pet_cnt
= 0;
328 thread_template
.kpc_buf
= NULL
;
332 thread_template
.hv_thread_target
= NULL
;
333 #endif /* HYPERVISOR */
335 #if (DEVELOPMENT || DEBUG)
336 thread_template
.t_page_creation_throttled_hard
= 0;
337 thread_template
.t_page_creation_throttled_soft
= 0;
338 #endif /* DEVELOPMENT || DEBUG */
339 thread_template
.t_page_creation_throttled
= 0;
340 thread_template
.t_page_creation_count
= 0;
341 thread_template
.t_page_creation_time
= 0;
343 thread_template
.affinity_set
= NULL
;
345 thread_template
.syscalls_unix
= 0;
346 thread_template
.syscalls_mach
= 0;
348 thread_template
.t_ledger
= LEDGER_NULL
;
349 thread_template
.t_threadledger
= LEDGER_NULL
;
351 thread_template
.t_bankledger
= LEDGER_NULL
;
352 thread_template
.t_deduct_bank_ledger_time
= 0;
355 thread_template
.requested_policy
= (struct thread_requested_policy
) {};
356 thread_template
.effective_policy
= (struct thread_effective_policy
) {};
358 bzero(&thread_template
.overrides
, sizeof(thread_template
.overrides
));
360 thread_template
.iotier_override
= THROTTLE_LEVEL_NONE
;
361 thread_template
.thread_io_stats
= NULL
;
362 thread_template
.thread_callout_interrupt_wakeups
= thread_template
.thread_callout_platform_idle_wakeups
= 0;
364 thread_template
.thread_timer_wakeups_bin_1
= thread_template
.thread_timer_wakeups_bin_2
= 0;
365 thread_template
.callout_woken_from_icontext
= thread_template
.callout_woken_from_platform_idle
= 0;
367 thread_template
.thread_tag
= 0;
369 thread_template
.ith_voucher_name
= MACH_PORT_NULL
;
370 thread_template
.ith_voucher
= IPC_VOUCHER_NULL
;
372 thread_template
.work_interval_id
= 0;
374 init_thread
= thread_template
;
375 machine_set_current_thread(&init_thread
);
378 extern boolean_t allow_qos_policy_set
;
384 sizeof(struct thread
),
385 thread_max
* sizeof(struct thread
),
386 THREAD_CHUNK
* sizeof(struct thread
),
389 thread_qos_override_zone
= zinit(
390 sizeof(struct thread_qos_override
),
391 4 * thread_max
* sizeof(struct thread_qos_override
),
393 "thread qos override");
394 zone_change(thread_qos_override_zone
, Z_EXPAND
, TRUE
);
395 zone_change(thread_qos_override_zone
, Z_COLLECT
, TRUE
);
396 zone_change(thread_qos_override_zone
, Z_CALLERACCT
, FALSE
);
397 zone_change(thread_qos_override_zone
, Z_NOENCRYPT
, TRUE
);
399 lck_grp_attr_setdefault(&thread_lck_grp_attr
);
400 lck_grp_init(&thread_lck_grp
, "thread", &thread_lck_grp_attr
);
401 lck_attr_setdefault(&thread_lck_attr
);
405 thread_policy_init();
408 * Initialize any machine-dependent
409 * per-thread structures necessary.
411 machine_thread_init();
413 if (!PE_parse_boot_argn("cpumon_ustackshots_trigger_pct", &cpumon_ustackshots_trigger_pct
,
414 sizeof (cpumon_ustackshots_trigger_pct
))) {
415 cpumon_ustackshots_trigger_pct
= CPUMON_USTACKSHOTS_TRIGGER_DEFAULT_PCT
;
418 PE_parse_boot_argn("-qos-policy-allow", &allow_qos_policy_set
, sizeof(allow_qos_policy_set
));
420 init_thread_ledgers();
424 thread_corpse_continue(void)
426 thread_t thread
= current_thread();
428 thread_terminate_internal(thread
);
429 ml_set_interrupts_enabled(FALSE
);
430 ast_taken(AST_APC
, TRUE
);
432 panic("thread_corpse_continue");
437 thread_terminate_continue(void)
439 panic("thread_terminate_continue");
444 * thread_terminate_self:
447 thread_terminate_self(void)
449 thread_t thread
= current_thread();
454 pal_thread_terminate_self(thread
);
456 DTRACE_PROC(lwp__exit
);
458 thread_mtx_lock(thread
);
460 ipc_thread_disable(thread
);
462 thread_mtx_unlock(thread
);
468 * Cancel priority depression, wait for concurrent expirations
469 * on other processors.
471 if (thread
->sched_flags
& TH_SFLAG_DEPRESSED_MASK
) {
472 thread
->sched_flags
&= ~TH_SFLAG_DEPRESSED_MASK
;
474 /* If our priority was low because of a depressed yield, restore it in case we block below */
475 thread_recompute_sched_pri(thread
, FALSE
);
477 if (timer_call_cancel(&thread
->depress_timer
))
478 thread
->depress_timer_active
--;
481 while (thread
->depress_timer_active
> 0) {
482 thread_unlock(thread
);
491 thread_sched_call(thread
, NULL
);
493 thread_unlock(thread
);
497 thread_mtx_lock(thread
);
499 thread_policy_reset(thread
);
501 thread_mtx_unlock(thread
);
504 uthread_cleanup(task
, thread
->uthread
, task
->bsd_info
);
505 threadcnt
= hw_atomic_sub(&task
->active_thread_count
, 1);
507 if (task
->bsd_info
) {
508 /* trace out pid before we sign off */
511 kdbg_trace_data(thread
->task
->bsd_info
, &dbg_arg1
);
513 KERNEL_DEBUG_CONSTANT(TRACE_DATA_THREAD_TERMINATE_PID
| DBG_FUNC_NONE
,
514 dbg_arg1
, 0, 0, 0, 0);
518 * If we are the last thread to terminate and the task is
519 * associated with a BSD process, perform BSD process exit.
521 if (threadcnt
== 0 && task
->bsd_info
!= NULL
) {
522 mach_exception_data_type_t subcode
= 0;
524 /* since we're the last thread in this process, trace out the command name too */
525 long dbg_arg1
= 0, dbg_arg2
= 0, dbg_arg3
= 0, dbg_arg4
= 0;
527 kdbg_trace_string(thread
->task
->bsd_info
, &dbg_arg1
, &dbg_arg2
, &dbg_arg3
, &dbg_arg4
);
529 KERNEL_DEBUG_CONSTANT(TRACE_STRING_PROC_EXIT
| DBG_FUNC_NONE
,
530 dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
, 0);
533 /* Get the exit reason before proc_exit */
534 subcode
= proc_encode_exit_exception_code(task
->bsd_info
);
535 proc_exit(task
->bsd_info
);
537 * if there is crash info in task
538 * then do the deliver action since this is
539 * last thread for this task.
541 if (task
->corpse_info
) {
542 task_deliver_crash_notification(task
, current_thread(), subcode
);
546 if (threadcnt
== 0) {
548 if (task_is_a_corpse_fork(task
)) {
549 thread_wakeup((event_t
)&task
->active_thread_count
);
554 uthread_cred_free(thread
->uthread
);
560 * Cancel wait timer, and wait for
561 * concurrent expirations.
563 if (thread
->wait_timer_is_set
) {
564 thread
->wait_timer_is_set
= FALSE
;
566 if (timer_call_cancel(&thread
->wait_timer
))
567 thread
->wait_timer_active
--;
570 while (thread
->wait_timer_active
> 0) {
571 thread_unlock(thread
);
581 * If there is a reserved stack, release it.
583 if (thread
->reserved_stack
!= 0) {
584 stack_free_reserved(thread
);
585 thread
->reserved_stack
= 0;
589 * Mark thread as terminating, and block.
591 thread
->state
|= TH_TERMINATE
;
592 thread_mark_wait_locked(thread
, THREAD_UNINT
);
593 assert((thread
->sched_flags
& TH_SFLAG_PROMOTED
) == 0);
594 assert(thread
->promotions
== 0);
595 assert(!(thread
->sched_flags
& TH_SFLAG_WAITQ_PROMOTED
));
596 assert(thread
->rwlock_count
== 0);
597 thread_unlock(thread
);
600 thread_block((thread_continue_t
)thread_terminate_continue
);
604 /* Drop a thread refcount that definitely isn't the last one. */
606 thread_deallocate_safe(thread_t thread
)
608 assert_thread_magic(thread
);
610 uint32_t old_refcount
= hw_atomic_sub(&(thread
)->ref_count
, 1) + 1;
612 if (__improbable(old_refcount
<= 1))
613 panic("bad thread refcount: %d", old_refcount
);
622 if (thread
== THREAD_NULL
)
625 assert_thread_magic(thread
);
626 assert(thread
->ref_count
> 0);
628 if (__probable(hw_atomic_sub(&(thread
)->ref_count
, 1) > 0))
631 if(!(thread
->state
& TH_TERMINATE2
))
632 panic("thread_deallocate: thread not properly terminated\n");
634 assert(thread
->runq
== PROCESSOR_NULL
);
636 assert(thread
->user_promotions
== 0);
639 kpc_thread_destroy(thread
);
642 ipc_thread_terminate(thread
);
644 proc_thread_qos_deallocate(thread
);
650 void *ut
= thread
->uthread
;
652 thread
->uthread
= NULL
;
653 uthread_zone_free(ut
);
655 #endif /* MACH_BSD */
657 if (thread
->t_ledger
)
658 ledger_dereference(thread
->t_ledger
);
659 if (thread
->t_threadledger
)
660 ledger_dereference(thread
->t_threadledger
);
662 if (IPC_VOUCHER_NULL
!= thread
->ith_voucher
)
663 ipc_voucher_release(thread
->ith_voucher
);
665 if (thread
->thread_io_stats
)
666 kfree(thread
->thread_io_stats
, sizeof(struct io_stat_info
));
668 if (thread
->kernel_stack
!= 0)
671 lck_mtx_destroy(&thread
->mutex
, &thread_lck_grp
);
672 machine_thread_destroy(thread
);
674 task_deallocate(task
);
677 assert_thread_magic(thread
);
678 thread
->thread_magic
= 0;
679 #endif /* MACH_ASSERT */
681 zfree(thread_zone
, thread
);
685 * thread_exception_daemon:
687 * Deliver EXC_RESOURCE exception
690 thread_exception_daemon(void)
692 struct thread_exception_elt
*elt
;
696 simple_lock(&thread_exception_lock
);
697 while ((elt
= (struct thread_exception_elt
*)dequeue_head(&thread_exception_queue
)) != NULL
) {
698 simple_unlock(&thread_exception_lock
);
700 task
= elt
->exception_task
;
701 thread
= elt
->exception_thread
;
702 assert_thread_magic(thread
);
704 kfree(elt
, sizeof(struct thread_exception_elt
));
706 /* wait for all the threads in the task to terminate */
708 task_wait_till_threads_terminate_locked(task
);
711 /* Consumes the task ref returned by task_generate_corpse_internal */
712 task_deallocate(task
);
713 /* Consumes the thread ref returned by task_generate_corpse_internal */
714 thread_deallocate(thread
);
716 /* Deliver the EXC_RESOURCE notification, also clears the corpse. */
717 task_deliver_crash_notification(task
, thread
, 0);
719 simple_lock(&thread_exception_lock
);
722 assert_wait((event_t
)&thread_exception_queue
, THREAD_UNINT
);
723 simple_unlock(&thread_exception_lock
);
725 thread_block((thread_continue_t
)thread_exception_daemon
);
729 * thread_exception_enqueue:
731 * Enqueue a corpse port to be delivered an EXC_RESOURCE.
734 thread_exception_enqueue(
738 struct thread_exception_elt
*elt
= (struct thread_exception_elt
*) kalloc(
739 sizeof(struct thread_exception_elt
));
741 elt
->exception_task
= task
;
742 elt
->exception_thread
= thread
;
744 simple_lock(&thread_exception_lock
);
745 enqueue_tail(&thread_exception_queue
, (queue_entry_t
)elt
);
746 simple_unlock(&thread_exception_lock
);
748 thread_wakeup((event_t
)&thread_exception_queue
);
752 * thread_copy_resource_info
754 * Copy the resource info counters from source
755 * thread to destination thread.
758 thread_copy_resource_info(
762 dst_thread
->thread_tag
= src_thread
->thread_tag
;
763 dst_thread
->c_switch
= src_thread
->c_switch
;
764 dst_thread
->p_switch
= src_thread
->p_switch
;
765 dst_thread
->ps_switch
= src_thread
->ps_switch
;
766 dst_thread
->precise_user_kernel_time
= src_thread
->precise_user_kernel_time
;
767 dst_thread
->user_timer
= src_thread
->user_timer
;
768 dst_thread
->user_timer_save
= src_thread
->user_timer_save
;
769 dst_thread
->system_timer_save
= src_thread
->system_timer_save
;
770 dst_thread
->syscalls_unix
= src_thread
->syscalls_unix
;
771 dst_thread
->syscalls_mach
= src_thread
->syscalls_mach
;
772 ledger_rollup(dst_thread
->t_threadledger
, src_thread
->t_threadledger
);
773 *dst_thread
->thread_io_stats
= *src_thread
->thread_io_stats
;
778 * thread_terminate_daemon:
780 * Perform final clean up for terminating threads.
783 thread_terminate_daemon(void)
785 thread_t self
, thread
;
788 self
= current_thread();
789 self
->options
|= TH_OPT_SYSTEM_CRITICAL
;
792 simple_lock(&thread_terminate_lock
);
794 while ((thread
= qe_dequeue_head(&thread_terminate_queue
, struct thread
, runq_links
)) != THREAD_NULL
) {
795 assert_thread_magic(thread
);
798 * if marked for crash reporting, skip reaping.
799 * The corpse delivery thread will clear bit and enqueue
800 * for reaping when done
802 if (thread
->inspection
){
803 enqueue_tail(&crashed_threads_queue
, &thread
->runq_links
);
807 simple_unlock(&thread_terminate_lock
);
813 task
->total_user_time
+= timer_grab(&thread
->user_timer
);
814 if (thread
->precise_user_kernel_time
) {
815 task
->total_system_time
+= timer_grab(&thread
->system_timer
);
817 task
->total_user_time
+= timer_grab(&thread
->system_timer
);
820 task
->c_switch
+= thread
->c_switch
;
821 task
->p_switch
+= thread
->p_switch
;
822 task
->ps_switch
+= thread
->ps_switch
;
824 task
->syscalls_unix
+= thread
->syscalls_unix
;
825 task
->syscalls_mach
+= thread
->syscalls_mach
;
827 task
->task_timer_wakeups_bin_1
+= thread
->thread_timer_wakeups_bin_1
;
828 task
->task_timer_wakeups_bin_2
+= thread
->thread_timer_wakeups_bin_2
;
829 task
->task_gpu_ns
+= ml_gpu_stat(thread
);
830 task
->task_energy
+= ml_energy_stat(thread
);
832 thread_update_qos_cpu_time(thread
);
834 queue_remove(&task
->threads
, thread
, thread_t
, task_threads
);
835 task
->thread_count
--;
838 * If the task is being halted, and there is only one thread
839 * left in the task after this one, then wakeup that thread.
841 if (task
->thread_count
== 1 && task
->halting
)
842 thread_wakeup((event_t
)&task
->halting
);
846 lck_mtx_lock(&tasks_threads_lock
);
847 queue_remove(&threads
, thread
, thread_t
, threads
);
849 lck_mtx_unlock(&tasks_threads_lock
);
851 thread_deallocate(thread
);
854 simple_lock(&thread_terminate_lock
);
857 assert_wait((event_t
)&thread_terminate_queue
, THREAD_UNINT
);
858 simple_unlock(&thread_terminate_lock
);
861 self
->options
&= ~TH_OPT_SYSTEM_CRITICAL
;
862 thread_block((thread_continue_t
)thread_terminate_daemon
);
867 * thread_terminate_enqueue:
869 * Enqueue a terminating thread for final disposition.
871 * Called at splsched.
874 thread_terminate_enqueue(
877 KERNEL_DEBUG_CONSTANT(TRACE_DATA_THREAD_TERMINATE
| DBG_FUNC_NONE
, thread
->thread_id
, 0, 0, 0, 0);
879 simple_lock(&thread_terminate_lock
);
880 enqueue_tail(&thread_terminate_queue
, &thread
->runq_links
);
881 simple_unlock(&thread_terminate_lock
);
883 thread_wakeup((event_t
)&thread_terminate_queue
);
887 * thread_terminate_crashed_threads:
888 * walk the list of crashed threads and put back set of threads
889 * who are no longer being inspected.
892 thread_terminate_crashed_threads()
895 boolean_t should_wake_terminate_queue
= FALSE
;
897 simple_lock(&thread_terminate_lock
);
899 * loop through the crashed threads queue
900 * to put any threads that are not being inspected anymore
903 qe_foreach_element_safe(th_remove
, &crashed_threads_queue
, runq_links
) {
904 /* make sure current_thread is never in crashed queue */
905 assert(th_remove
!= current_thread());
907 if (th_remove
->inspection
== FALSE
) {
908 re_queue_tail(&thread_terminate_queue
, &th_remove
->runq_links
);
909 should_wake_terminate_queue
= TRUE
;
913 simple_unlock(&thread_terminate_lock
);
914 if (should_wake_terminate_queue
== TRUE
) {
915 thread_wakeup((event_t
)&thread_terminate_queue
);
920 * thread_stack_daemon:
922 * Perform stack allocation as required due to
926 thread_stack_daemon(void)
932 simple_lock(&thread_stack_lock
);
934 while ((thread
= qe_dequeue_head(&thread_stack_queue
, struct thread
, runq_links
)) != THREAD_NULL
) {
935 assert_thread_magic(thread
);
937 simple_unlock(&thread_stack_lock
);
940 /* allocate stack with interrupts enabled so that we can call into VM */
943 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_WAIT
) | DBG_FUNC_END
, thread_tid(thread
), 0, 0, 0, 0);
947 thread_setrun(thread
, SCHED_PREEMPT
| SCHED_TAILQ
);
948 thread_unlock(thread
);
950 simple_lock(&thread_stack_lock
);
953 assert_wait((event_t
)&thread_stack_queue
, THREAD_UNINT
);
954 simple_unlock(&thread_stack_lock
);
957 thread_block((thread_continue_t
)thread_stack_daemon
);
962 * thread_stack_enqueue:
964 * Enqueue a thread for stack allocation.
966 * Called at splsched.
969 thread_stack_enqueue(
972 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED
,MACH_STACK_WAIT
) | DBG_FUNC_START
, thread_tid(thread
), 0, 0, 0, 0);
973 assert_thread_magic(thread
);
975 simple_lock(&thread_stack_lock
);
976 enqueue_tail(&thread_stack_queue
, &thread
->runq_links
);
977 simple_unlock(&thread_stack_lock
);
979 thread_wakeup((event_t
)&thread_stack_queue
);
983 thread_daemon_init(void)
985 kern_return_t result
;
986 thread_t thread
= NULL
;
988 simple_lock_init(&thread_terminate_lock
, 0);
989 queue_init(&thread_terminate_queue
);
990 queue_init(&crashed_threads_queue
);
992 result
= kernel_thread_start_priority((thread_continue_t
)thread_terminate_daemon
, NULL
, MINPRI_KERNEL
, &thread
);
993 if (result
!= KERN_SUCCESS
)
994 panic("thread_daemon_init: thread_terminate_daemon");
996 thread_deallocate(thread
);
998 simple_lock_init(&thread_stack_lock
, 0);
999 queue_init(&thread_stack_queue
);
1001 result
= kernel_thread_start_priority((thread_continue_t
)thread_stack_daemon
, NULL
, BASEPRI_PREEMPT
, &thread
);
1002 if (result
!= KERN_SUCCESS
)
1003 panic("thread_daemon_init: thread_stack_daemon");
1005 thread_deallocate(thread
);
1007 simple_lock_init(&thread_exception_lock
, 0);
1008 queue_init(&thread_exception_queue
);
1010 result
= kernel_thread_start_priority((thread_continue_t
)thread_exception_daemon
, NULL
, MINPRI_KERNEL
, &thread
);
1011 if (result
!= KERN_SUCCESS
)
1012 panic("thread_daemon_init: thread_exception_daemon");
1014 thread_deallocate(thread
);
1017 #define TH_OPTION_NONE 0x00
1018 #define TH_OPTION_NOCRED 0x01
1019 #define TH_OPTION_NOSUSP 0x02
1022 * Create a new thread.
1023 * Doesn't start the thread running.
1025 * Task and tasks_threads_lock are returned locked on success.
1027 static kern_return_t
1028 thread_create_internal(
1031 thread_continue_t continuation
,
1033 thread_t
*out_thread
)
1035 thread_t new_thread
;
1036 static thread_t first_thread
;
1039 * Allocate a thread and initialize static fields
1041 if (first_thread
== THREAD_NULL
)
1042 new_thread
= first_thread
= current_thread();
1044 new_thread
= (thread_t
)zalloc(thread_zone
);
1045 if (new_thread
== THREAD_NULL
)
1046 return (KERN_RESOURCE_SHORTAGE
);
1048 if (new_thread
!= first_thread
)
1049 *new_thread
= thread_template
;
1052 new_thread
->uthread
= uthread_alloc(parent_task
, new_thread
, (options
& TH_OPTION_NOCRED
) != 0);
1053 if (new_thread
->uthread
== NULL
) {
1055 new_thread
->thread_magic
= 0;
1056 #endif /* MACH_ASSERT */
1058 zfree(thread_zone
, new_thread
);
1059 return (KERN_RESOURCE_SHORTAGE
);
1061 #endif /* MACH_BSD */
1063 if (machine_thread_create(new_thread
, parent_task
) != KERN_SUCCESS
) {
1065 void *ut
= new_thread
->uthread
;
1067 new_thread
->uthread
= NULL
;
1068 /* cred free may not be necessary */
1069 uthread_cleanup(parent_task
, ut
, parent_task
->bsd_info
);
1070 uthread_cred_free(ut
);
1071 uthread_zone_free(ut
);
1072 #endif /* MACH_BSD */
1075 new_thread
->thread_magic
= 0;
1076 #endif /* MACH_ASSERT */
1078 zfree(thread_zone
, new_thread
);
1079 return (KERN_FAILURE
);
1082 new_thread
->task
= parent_task
;
1084 thread_lock_init(new_thread
);
1085 wake_lock_init(new_thread
);
1087 lck_mtx_init(&new_thread
->mutex
, &thread_lck_grp
, &thread_lck_attr
);
1089 ipc_thread_init(new_thread
);
1091 new_thread
->continuation
= continuation
;
1093 /* Allocate I/O Statistics structure */
1094 new_thread
->thread_io_stats
= (io_stat_info_t
)kalloc(sizeof(struct io_stat_info
));
1095 assert(new_thread
->thread_io_stats
!= NULL
);
1096 bzero(new_thread
->thread_io_stats
, sizeof(struct io_stat_info
));
1099 /* Clear out the I/O Scheduling info for AppleFSCompression */
1100 new_thread
->decmp_upl
= NULL
;
1101 #endif /* CONFIG_IOSCHED */
1103 lck_mtx_lock(&tasks_threads_lock
);
1104 task_lock(parent_task
);
1107 * Fail thread creation if parent task is being torn down or has too many threads
1108 * If the caller asked for TH_OPTION_NOSUSP, also fail if the parent task is suspended
1110 if (parent_task
->active
== 0 || parent_task
->halting
||
1111 (parent_task
->suspend_count
> 0 && (options
& TH_OPTION_NOSUSP
) != 0) ||
1112 (parent_task
->thread_count
>= task_threadmax
&& parent_task
!= kernel_task
)) {
1113 task_unlock(parent_task
);
1114 lck_mtx_unlock(&tasks_threads_lock
);
1118 void *ut
= new_thread
->uthread
;
1120 new_thread
->uthread
= NULL
;
1121 uthread_cleanup(parent_task
, ut
, parent_task
->bsd_info
);
1122 /* cred free may not be necessary */
1123 uthread_cred_free(ut
);
1124 uthread_zone_free(ut
);
1126 #endif /* MACH_BSD */
1127 ipc_thread_disable(new_thread
);
1128 ipc_thread_terminate(new_thread
);
1129 kfree(new_thread
->thread_io_stats
, sizeof(struct io_stat_info
));
1130 lck_mtx_destroy(&new_thread
->mutex
, &thread_lck_grp
);
1131 machine_thread_destroy(new_thread
);
1132 zfree(thread_zone
, new_thread
);
1133 return (KERN_FAILURE
);
1136 /* New threads inherit any default state on the task */
1137 machine_thread_inherit_taskwide(new_thread
, parent_task
);
1139 task_reference_internal(parent_task
);
1141 if (new_thread
->task
->rusage_cpu_flags
& TASK_RUSECPU_FLAGS_PERTHR_LIMIT
) {
1143 * This task has a per-thread CPU limit; make sure this new thread
1144 * gets its limit set too, before it gets out of the kernel.
1146 set_astledger(new_thread
);
1149 /* Instantiate a thread ledger. Do not fail thread creation if ledger creation fails. */
1150 if ((new_thread
->t_threadledger
= ledger_instantiate(thread_ledger_template
,
1151 LEDGER_CREATE_INACTIVE_ENTRIES
)) != LEDGER_NULL
) {
1153 ledger_entry_setactive(new_thread
->t_threadledger
, thread_ledgers
.cpu_time
);
1157 new_thread
->t_bankledger
= LEDGER_NULL
;
1158 new_thread
->t_deduct_bank_ledger_time
= 0;
1161 new_thread
->t_ledger
= new_thread
->task
->ledger
;
1162 if (new_thread
->t_ledger
)
1163 ledger_reference(new_thread
->t_ledger
);
1165 #if defined(CONFIG_SCHED_MULTIQ)
1166 /* Cache the task's sched_group */
1167 new_thread
->sched_group
= parent_task
->sched_group
;
1168 #endif /* defined(CONFIG_SCHED_MULTIQ) */
1170 /* Cache the task's map */
1171 new_thread
->map
= parent_task
->map
;
1173 timer_call_setup(&new_thread
->wait_timer
, thread_timer_expire
, new_thread
);
1174 timer_call_setup(&new_thread
->depress_timer
, thread_depress_expire
, new_thread
);
1177 kpc_thread_create(new_thread
);
1180 /* Set the thread's scheduling parameters */
1181 new_thread
->sched_mode
= SCHED(initial_thread_sched_mode
)(parent_task
);
1182 new_thread
->max_priority
= parent_task
->max_priority
;
1183 new_thread
->task_priority
= parent_task
->priority
;
1185 int new_priority
= (priority
< 0) ? parent_task
->priority
: priority
;
1186 new_priority
= (priority
< 0)? parent_task
->priority
: priority
;
1187 if (new_priority
> new_thread
->max_priority
)
1188 new_priority
= new_thread
->max_priority
;
1190 new_thread
->importance
= new_priority
- new_thread
->task_priority
;
1192 sched_set_thread_base_priority(new_thread
, new_priority
);
1194 #if defined(CONFIG_SCHED_TIMESHARE_CORE)
1195 new_thread
->sched_stamp
= sched_tick
;
1196 new_thread
->pri_shift
= sched_pri_shifts
[new_thread
->th_sched_bucket
];
1197 #endif /* defined(CONFIG_SCHED_TIMESHARE_CORE) */
1200 thread_policy_create(new_thread
);
1202 /* Chain the thread onto the task's list */
1203 queue_enter(&parent_task
->threads
, new_thread
, thread_t
, task_threads
);
1204 parent_task
->thread_count
++;
1206 /* So terminating threads don't need to take the task lock to decrement */
1207 hw_atomic_add(&parent_task
->active_thread_count
, 1);
1209 /* Protected by the tasks_threads_lock */
1210 new_thread
->thread_id
= ++thread_unique_id
;
1212 queue_enter(&threads
, new_thread
, thread_t
, threads
);
1215 new_thread
->active
= TRUE
;
1216 if (task_is_a_corpse_fork(parent_task
)) {
1217 /* Set the inspection bit if the task is a corpse fork */
1218 new_thread
->inspection
= TRUE
;
1220 new_thread
->inspection
= FALSE
;
1222 new_thread
->corpse_dup
= FALSE
;
1223 *out_thread
= new_thread
;
1226 long dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
;
1228 kdbg_trace_data(parent_task
->bsd_info
, &dbg_arg2
);
1230 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
1231 TRACE_DATA_NEWTHREAD
| DBG_FUNC_NONE
,
1232 (vm_address_t
)(uintptr_t)thread_tid(new_thread
), dbg_arg2
, 0, 0, 0);
1234 kdbg_trace_string(parent_task
->bsd_info
,
1235 &dbg_arg1
, &dbg_arg2
, &dbg_arg3
, &dbg_arg4
);
1237 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
1238 TRACE_STRING_NEWTHREAD
| DBG_FUNC_NONE
,
1239 dbg_arg1
, dbg_arg2
, dbg_arg3
, dbg_arg4
, 0);
1242 DTRACE_PROC1(lwp__create
, thread_t
, *out_thread
);
1244 return (KERN_SUCCESS
);
1247 static kern_return_t
1248 thread_create_internal2(
1250 thread_t
*new_thread
,
1251 boolean_t from_user
,
1252 thread_continue_t continuation
)
1254 kern_return_t result
;
1257 if (task
== TASK_NULL
|| task
== kernel_task
)
1258 return (KERN_INVALID_ARGUMENT
);
1260 result
= thread_create_internal(task
, -1, continuation
, TH_OPTION_NONE
, &thread
);
1261 if (result
!= KERN_SUCCESS
)
1264 thread
->user_stop_count
= 1;
1265 thread_hold(thread
);
1266 if (task
->suspend_count
> 0)
1267 thread_hold(thread
);
1270 extmod_statistics_incr_thread_create(task
);
1273 lck_mtx_unlock(&tasks_threads_lock
);
1275 *new_thread
= thread
;
1277 return (KERN_SUCCESS
);
1280 /* No prototype, since task_server.h has the _from_user version if KERNEL_SERVER */
1284 thread_t
*new_thread
);
1289 thread_t
*new_thread
)
1291 return thread_create_internal2(task
, new_thread
, FALSE
, (thread_continue_t
)thread_bootstrap_return
);
1295 thread_create_from_user(
1297 thread_t
*new_thread
)
1299 return thread_create_internal2(task
, new_thread
, TRUE
, (thread_continue_t
)thread_bootstrap_return
);
1303 thread_create_with_continuation(
1305 thread_t
*new_thread
,
1306 thread_continue_t continuation
)
1308 return thread_create_internal2(task
, new_thread
, FALSE
, continuation
);
1311 static kern_return_t
1312 thread_create_running_internal2(
1315 thread_state_t new_state
,
1316 mach_msg_type_number_t new_state_count
,
1317 thread_t
*new_thread
,
1318 boolean_t from_user
)
1320 kern_return_t result
;
1323 if (task
== TASK_NULL
|| task
== kernel_task
)
1324 return (KERN_INVALID_ARGUMENT
);
1326 result
= thread_create_internal(task
, -1, (thread_continue_t
)thread_bootstrap_return
, TH_OPTION_NONE
, &thread
);
1327 if (result
!= KERN_SUCCESS
)
1330 if (task
->suspend_count
> 0)
1331 thread_hold(thread
);
1333 result
= machine_thread_set_state(thread
, flavor
, new_state
, new_state_count
);
1334 if (result
!= KERN_SUCCESS
) {
1336 lck_mtx_unlock(&tasks_threads_lock
);
1338 thread_terminate(thread
);
1339 thread_deallocate(thread
);
1343 thread_mtx_lock(thread
);
1344 thread_start(thread
);
1345 thread_mtx_unlock(thread
);
1348 extmod_statistics_incr_thread_create(task
);
1351 lck_mtx_unlock(&tasks_threads_lock
);
1353 *new_thread
= thread
;
1358 /* Prototype, see justification above */
1360 thread_create_running(
1363 thread_state_t new_state
,
1364 mach_msg_type_number_t new_state_count
,
1365 thread_t
*new_thread
);
1368 thread_create_running(
1371 thread_state_t new_state
,
1372 mach_msg_type_number_t new_state_count
,
1373 thread_t
*new_thread
)
1375 return thread_create_running_internal2(
1376 task
, flavor
, new_state
, new_state_count
,
1381 thread_create_running_from_user(
1384 thread_state_t new_state
,
1385 mach_msg_type_number_t new_state_count
,
1386 thread_t
*new_thread
)
1388 return thread_create_running_internal2(
1389 task
, flavor
, new_state
, new_state_count
,
1394 thread_create_workq(
1396 thread_continue_t thread_return
,
1397 thread_t
*new_thread
)
1399 kern_return_t result
;
1402 if (task
== TASK_NULL
|| task
== kernel_task
)
1403 return (KERN_INVALID_ARGUMENT
);
1405 result
= thread_create_internal(task
, -1, thread_return
, TH_OPTION_NOCRED
| TH_OPTION_NOSUSP
, &thread
);
1406 if (result
!= KERN_SUCCESS
)
1409 thread
->user_stop_count
= 1;
1410 thread_hold(thread
);
1411 if (task
->suspend_count
> 0)
1412 thread_hold(thread
);
1415 lck_mtx_unlock(&tasks_threads_lock
);
1417 *new_thread
= thread
;
1419 return (KERN_SUCCESS
);
1423 thread_create_workq_waiting(
1425 thread_continue_t thread_return
,
1427 thread_t
*new_thread
)
1430 kern_return_t result
;
1432 if (task
== TASK_NULL
|| task
== kernel_task
)
1433 return KERN_INVALID_ARGUMENT
;
1435 result
= thread_create_internal(task
, -1, thread_return
, TH_OPTION_NOCRED
| TH_OPTION_NOSUSP
, &thread
);
1437 if (result
!= KERN_SUCCESS
)
1440 if (task
->suspend_count
> 0)
1441 thread_hold(thread
);
1443 thread_mtx_lock(thread
);
1444 thread_start_in_assert_wait(thread
, event
, THREAD_INTERRUPTIBLE
);
1445 thread_mtx_unlock(thread
);
1448 lck_mtx_unlock(&tasks_threads_lock
);
1450 *new_thread
= thread
;
1456 * kernel_thread_create:
1458 * Create a thread in the kernel task
1459 * to execute in kernel context.
1462 kernel_thread_create(
1463 thread_continue_t continuation
,
1466 thread_t
*new_thread
)
1468 kern_return_t result
;
1470 task_t task
= kernel_task
;
1472 result
= thread_create_internal(task
, priority
, continuation
, TH_OPTION_NONE
, &thread
);
1473 if (result
!= KERN_SUCCESS
)
1477 lck_mtx_unlock(&tasks_threads_lock
);
1479 stack_alloc(thread
);
1480 assert(thread
->kernel_stack
!= 0);
1481 thread
->reserved_stack
= thread
->kernel_stack
;
1483 thread
->parameter
= parameter
;
1486 kprintf("kernel_thread_create: thread = %p continuation = %p\n", thread
, continuation
);
1487 *new_thread
= thread
;
1493 kernel_thread_start_priority(
1494 thread_continue_t continuation
,
1497 thread_t
*new_thread
)
1499 kern_return_t result
;
1502 result
= kernel_thread_create(continuation
, parameter
, priority
, &thread
);
1503 if (result
!= KERN_SUCCESS
)
1506 *new_thread
= thread
;
1508 thread_mtx_lock(thread
);
1509 thread_start(thread
);
1510 thread_mtx_unlock(thread
);
1516 kernel_thread_start(
1517 thread_continue_t continuation
,
1519 thread_t
*new_thread
)
1521 return kernel_thread_start_priority(continuation
, parameter
, -1, new_thread
);
1524 /* Separated into helper function so it can be used by THREAD_BASIC_INFO and THREAD_EXTENDED_INFO */
1525 /* it is assumed that the thread is locked by the caller */
1527 retrieve_thread_basic_info(thread_t thread
, thread_basic_info_t basic_info
)
1533 thread_read_times(thread
, &basic_info
->user_time
,
1534 &basic_info
->system_time
);
1537 * Update lazy-evaluated scheduler info because someone wants it.
1539 if (SCHED(can_update_priority
)(thread
))
1540 SCHED(update_priority
)(thread
);
1542 basic_info
->sleep_time
= 0;
1545 * To calculate cpu_usage, first correct for timer rate,
1546 * then for 5/8 ageing. The correction factor [3/5] is
1549 basic_info
->cpu_usage
= 0;
1550 #if defined(CONFIG_SCHED_TIMESHARE_CORE)
1551 if (sched_tick_interval
) {
1552 basic_info
->cpu_usage
= (integer_t
)(((uint64_t)thread
->cpu_usage
1553 * TH_USAGE_SCALE
) / sched_tick_interval
);
1554 basic_info
->cpu_usage
= (basic_info
->cpu_usage
* 3) / 5;
1558 if (basic_info
->cpu_usage
> TH_USAGE_SCALE
)
1559 basic_info
->cpu_usage
= TH_USAGE_SCALE
;
1561 basic_info
->policy
= ((thread
->sched_mode
== TH_MODE_TIMESHARE
)?
1562 POLICY_TIMESHARE
: POLICY_RR
);
1565 if (thread
->options
& TH_OPT_IDLE_THREAD
)
1566 flags
|= TH_FLAGS_IDLE
;
1568 if (thread
->options
& TH_OPT_GLOBAL_FORCED_IDLE
) {
1569 flags
|= TH_FLAGS_GLOBAL_FORCED_IDLE
;
1572 if (!thread
->kernel_stack
)
1573 flags
|= TH_FLAGS_SWAPPED
;
1576 if (thread
->state
& TH_TERMINATE
)
1577 state
= TH_STATE_HALTED
;
1579 if (thread
->state
& TH_RUN
)
1580 state
= TH_STATE_RUNNING
;
1582 if (thread
->state
& TH_UNINT
)
1583 state
= TH_STATE_UNINTERRUPTIBLE
;
1585 if (thread
->state
& TH_SUSP
)
1586 state
= TH_STATE_STOPPED
;
1588 if (thread
->state
& TH_WAIT
)
1589 state
= TH_STATE_WAITING
;
1591 basic_info
->run_state
= state
;
1592 basic_info
->flags
= flags
;
1594 basic_info
->suspend_count
= thread
->user_stop_count
;
1600 thread_info_internal(
1602 thread_flavor_t flavor
,
1603 thread_info_t thread_info_out
, /* ptr to OUT array */
1604 mach_msg_type_number_t
*thread_info_count
) /*IN/OUT*/
1608 if (thread
== THREAD_NULL
)
1609 return (KERN_INVALID_ARGUMENT
);
1611 if (flavor
== THREAD_BASIC_INFO
) {
1613 if (*thread_info_count
< THREAD_BASIC_INFO_COUNT
)
1614 return (KERN_INVALID_ARGUMENT
);
1617 thread_lock(thread
);
1619 retrieve_thread_basic_info(thread
, (thread_basic_info_t
) thread_info_out
);
1621 thread_unlock(thread
);
1624 *thread_info_count
= THREAD_BASIC_INFO_COUNT
;
1626 return (KERN_SUCCESS
);
1629 if (flavor
== THREAD_IDENTIFIER_INFO
) {
1630 thread_identifier_info_t identifier_info
;
1632 if (*thread_info_count
< THREAD_IDENTIFIER_INFO_COUNT
)
1633 return (KERN_INVALID_ARGUMENT
);
1635 identifier_info
= (thread_identifier_info_t
) thread_info_out
;
1638 thread_lock(thread
);
1640 identifier_info
->thread_id
= thread
->thread_id
;
1641 identifier_info
->thread_handle
= thread
->machine
.cthread_self
;
1642 identifier_info
->dispatch_qaddr
= thread_dispatchqaddr(thread
);
1644 thread_unlock(thread
);
1646 return KERN_SUCCESS
;
1649 if (flavor
== THREAD_SCHED_TIMESHARE_INFO
) {
1650 policy_timeshare_info_t ts_info
;
1652 if (*thread_info_count
< POLICY_TIMESHARE_INFO_COUNT
)
1653 return (KERN_INVALID_ARGUMENT
);
1655 ts_info
= (policy_timeshare_info_t
)thread_info_out
;
1658 thread_lock(thread
);
1660 if (thread
->sched_mode
!= TH_MODE_TIMESHARE
) {
1661 thread_unlock(thread
);
1663 return (KERN_INVALID_POLICY
);
1666 ts_info
->depressed
= (thread
->sched_flags
& TH_SFLAG_DEPRESSED_MASK
) != 0;
1667 if (ts_info
->depressed
) {
1668 ts_info
->base_priority
= DEPRESSPRI
;
1669 ts_info
->depress_priority
= thread
->base_pri
;
1672 ts_info
->base_priority
= thread
->base_pri
;
1673 ts_info
->depress_priority
= -1;
1676 ts_info
->cur_priority
= thread
->sched_pri
;
1677 ts_info
->max_priority
= thread
->max_priority
;
1679 thread_unlock(thread
);
1682 *thread_info_count
= POLICY_TIMESHARE_INFO_COUNT
;
1684 return (KERN_SUCCESS
);
1687 if (flavor
== THREAD_SCHED_FIFO_INFO
) {
1688 if (*thread_info_count
< POLICY_FIFO_INFO_COUNT
)
1689 return (KERN_INVALID_ARGUMENT
);
1691 return (KERN_INVALID_POLICY
);
1694 if (flavor
== THREAD_SCHED_RR_INFO
) {
1695 policy_rr_info_t rr_info
;
1696 uint32_t quantum_time
;
1697 uint64_t quantum_ns
;
1699 if (*thread_info_count
< POLICY_RR_INFO_COUNT
)
1700 return (KERN_INVALID_ARGUMENT
);
1702 rr_info
= (policy_rr_info_t
) thread_info_out
;
1705 thread_lock(thread
);
1707 if (thread
->sched_mode
== TH_MODE_TIMESHARE
) {
1708 thread_unlock(thread
);
1711 return (KERN_INVALID_POLICY
);
1714 rr_info
->depressed
= (thread
->sched_flags
& TH_SFLAG_DEPRESSED_MASK
) != 0;
1715 if (rr_info
->depressed
) {
1716 rr_info
->base_priority
= DEPRESSPRI
;
1717 rr_info
->depress_priority
= thread
->base_pri
;
1720 rr_info
->base_priority
= thread
->base_pri
;
1721 rr_info
->depress_priority
= -1;
1724 quantum_time
= SCHED(initial_quantum_size
)(THREAD_NULL
);
1725 absolutetime_to_nanoseconds(quantum_time
, &quantum_ns
);
1727 rr_info
->max_priority
= thread
->max_priority
;
1728 rr_info
->quantum
= (uint32_t)(quantum_ns
/ 1000 / 1000);
1730 thread_unlock(thread
);
1733 *thread_info_count
= POLICY_RR_INFO_COUNT
;
1735 return (KERN_SUCCESS
);
1738 if (flavor
== THREAD_EXTENDED_INFO
) {
1739 thread_basic_info_data_t basic_info
;
1740 thread_extended_info_t extended_info
= (thread_extended_info_t
) thread_info_out
;
1742 if (*thread_info_count
< THREAD_EXTENDED_INFO_COUNT
) {
1743 return (KERN_INVALID_ARGUMENT
);
1747 thread_lock(thread
);
1749 /* NOTE: This mimics fill_taskthreadinfo(), which is the function used by proc_pidinfo() for
1750 * the PROC_PIDTHREADINFO flavor (which can't be used on corpses)
1752 retrieve_thread_basic_info(thread
, &basic_info
);
1753 extended_info
->pth_user_time
= ((basic_info
.user_time
.seconds
* (integer_t
)NSEC_PER_SEC
) + (basic_info
.user_time
.microseconds
* (integer_t
)NSEC_PER_USEC
));
1754 extended_info
->pth_system_time
= ((basic_info
.system_time
.seconds
* (integer_t
)NSEC_PER_SEC
) + (basic_info
.system_time
.microseconds
* (integer_t
)NSEC_PER_USEC
));
1756 extended_info
->pth_cpu_usage
= basic_info
.cpu_usage
;
1757 extended_info
->pth_policy
= basic_info
.policy
;
1758 extended_info
->pth_run_state
= basic_info
.run_state
;
1759 extended_info
->pth_flags
= basic_info
.flags
;
1760 extended_info
->pth_sleep_time
= basic_info
.sleep_time
;
1761 extended_info
->pth_curpri
= thread
->sched_pri
;
1762 extended_info
->pth_priority
= thread
->base_pri
;
1763 extended_info
->pth_maxpriority
= thread
->max_priority
;
1765 bsd_getthreadname(thread
->uthread
,extended_info
->pth_name
);
1767 thread_unlock(thread
);
1770 *thread_info_count
= THREAD_EXTENDED_INFO_COUNT
;
1772 return (KERN_SUCCESS
);
1775 if (flavor
== THREAD_DEBUG_INFO_INTERNAL
) {
1776 #if DEVELOPMENT || DEBUG
1777 thread_debug_info_internal_t dbg_info
;
1778 if (*thread_info_count
< THREAD_DEBUG_INFO_INTERNAL_COUNT
)
1779 return (KERN_NOT_SUPPORTED
);
1781 if (thread_info_out
== NULL
)
1782 return (KERN_INVALID_ARGUMENT
);
1784 dbg_info
= (thread_debug_info_internal_t
) thread_info_out
;
1785 dbg_info
->page_creation_count
= thread
->t_page_creation_count
;
1787 *thread_info_count
= THREAD_DEBUG_INFO_INTERNAL_COUNT
;
1788 return (KERN_SUCCESS
);
1789 #endif /* DEVELOPMENT || DEBUG */
1790 return (KERN_NOT_SUPPORTED
);
1793 return (KERN_INVALID_ARGUMENT
);
1799 time_value_t
*user_time
,
1800 time_value_t
*system_time
)
1804 uint64_t tval_user
, tval_system
;
1806 tval_user
= timer_grab(&thread
->user_timer
);
1807 tval_system
= timer_grab(&thread
->system_timer
);
1809 if (thread
->precise_user_kernel_time
) {
1810 absolutetime_to_microtime(tval_user
, &secs
, &usecs
);
1811 user_time
->seconds
= (typeof(user_time
->seconds
))secs
;
1812 user_time
->microseconds
= usecs
;
1814 absolutetime_to_microtime(tval_system
, &secs
, &usecs
);
1815 system_time
->seconds
= (typeof(system_time
->seconds
))secs
;
1816 system_time
->microseconds
= usecs
;
1818 /* system_timer may represent either sys or user */
1819 tval_user
+= tval_system
;
1820 absolutetime_to_microtime(tval_user
, &secs
, &usecs
);
1821 user_time
->seconds
= (typeof(user_time
->seconds
))secs
;
1822 user_time
->microseconds
= usecs
;
1824 system_time
->seconds
= 0;
1825 system_time
->microseconds
= 0;
1829 uint64_t thread_get_runtime_self(void)
1831 boolean_t interrupt_state
;
1833 thread_t thread
= NULL
;
1834 processor_t processor
= NULL
;
1836 thread
= current_thread();
1838 /* Not interrupt safe, as the scheduler may otherwise update timer values underneath us */
1839 interrupt_state
= ml_set_interrupts_enabled(FALSE
);
1840 processor
= current_processor();
1841 timer_switch(PROCESSOR_DATA(processor
, thread_timer
), mach_absolute_time(), PROCESSOR_DATA(processor
, thread_timer
));
1842 runtime
= (timer_grab(&thread
->user_timer
) + timer_grab(&thread
->system_timer
));
1843 ml_set_interrupts_enabled(interrupt_state
);
1850 __unused thread_t thread
,
1851 __unused processor_set_t new_pset
)
1853 return (KERN_FAILURE
);
1857 * thread_assign_default:
1859 * Special version of thread_assign for assigning threads to default
1863 thread_assign_default(
1866 return (thread_assign(thread
, &pset0
));
1870 * thread_get_assignment
1872 * Return current assignment for this thread.
1875 thread_get_assignment(
1877 processor_set_t
*pset
)
1880 return (KERN_INVALID_ARGUMENT
);
1884 return (KERN_SUCCESS
);
1888 * thread_wire_internal:
1890 * Specify that the target thread must always be able
1891 * to run and to allocate memory.
1894 thread_wire_internal(
1895 host_priv_t host_priv
,
1898 boolean_t
*prev_state
)
1900 if (host_priv
== NULL
|| thread
!= current_thread())
1901 return (KERN_INVALID_ARGUMENT
);
1903 assert(host_priv
== &realhost
);
1906 *prev_state
= (thread
->options
& TH_OPT_VMPRIV
) != 0;
1909 if (!(thread
->options
& TH_OPT_VMPRIV
))
1910 vm_page_free_reserve(1); /* XXX */
1911 thread
->options
|= TH_OPT_VMPRIV
;
1914 if (thread
->options
& TH_OPT_VMPRIV
)
1915 vm_page_free_reserve(-1); /* XXX */
1916 thread
->options
&= ~TH_OPT_VMPRIV
;
1919 return (KERN_SUCCESS
);
1926 * User-api wrapper for thread_wire_internal()
1930 host_priv_t host_priv
,
1934 return (thread_wire_internal(host_priv
, thread
, wired
, NULL
));
1939 is_vm_privileged(void)
1941 return current_thread()->options
& TH_OPT_VMPRIV
? TRUE
: FALSE
;
1945 set_vm_privilege(boolean_t privileged
)
1947 boolean_t was_vmpriv
;
1949 if (current_thread()->options
& TH_OPT_VMPRIV
)
1954 if (privileged
!= FALSE
)
1955 current_thread()->options
|= TH_OPT_VMPRIV
;
1957 current_thread()->options
&= ~TH_OPT_VMPRIV
;
1959 return (was_vmpriv
);
1963 set_thread_rwlock_boost(void)
1965 current_thread()->rwlock_count
++;
1969 clear_thread_rwlock_boost(void)
1971 thread_t thread
= current_thread();
1973 if ((thread
->rwlock_count
-- == 1) && (thread
->sched_flags
& TH_SFLAG_RW_PROMOTED
)) {
1975 lck_rw_clear_promotion(thread
);
1980 * XXX assuming current thread only, for now...
1983 thread_guard_violation(thread_t thread
, unsigned type
)
1985 assert(thread
== current_thread());
1987 spl_t s
= splsched();
1989 * Use the saved state area of the thread structure
1990 * to store all info required to handle the AST when
1991 * returning to userspace
1993 thread
->guard_exc_info
.type
= type
;
1994 thread_ast_set(thread
, AST_GUARD
);
1995 ast_propagate(thread
->ast
);
2003 * Handle AST_GUARD for a thread. This routine looks at the
2004 * state saved in the thread structure to determine the cause
2005 * of this exception. Based on this value, it invokes the
2006 * appropriate routine which determines other exception related
2007 * info and raises the exception.
2010 guard_ast(thread_t thread
)
2012 if (thread
->guard_exc_info
.type
== GUARD_TYPE_MACH_PORT
)
2013 mach_port_guard_ast(thread
);
2015 fd_guard_ast(thread
);
2019 thread_cputime_callback(int warning
, __unused
const void *arg0
, __unused
const void *arg1
)
2021 if (warning
== LEDGER_WARNING_ROSE_ABOVE
) {
2022 #if CONFIG_TELEMETRY
2024 * This thread is in danger of violating the CPU usage monitor. Enable telemetry
2025 * on the entire task so there are micro-stackshots available if and when
2026 * EXC_RESOURCE is triggered. We could have chosen to enable micro-stackshots
2027 * for this thread only; but now that this task is suspect, knowing what all of
2028 * its threads are up to will be useful.
2030 telemetry_task_ctl(current_task(), TF_CPUMON_WARNING
, 1);
2035 #if CONFIG_TELEMETRY
2037 * If the balance has dipped below the warning level (LEDGER_WARNING_DIPPED_BELOW) or
2038 * exceeded the limit, turn telemetry off for the task.
2040 telemetry_task_ctl(current_task(), TF_CPUMON_WARNING
, 0);
2044 SENDING_NOTIFICATION__THIS_THREAD_IS_CONSUMING_TOO_MUCH_CPU();
2048 void __attribute__((noinline
))
2049 SENDING_NOTIFICATION__THIS_THREAD_IS_CONSUMING_TOO_MUCH_CPU(void)
2052 task_t task
= current_task();
2053 thread_t thread
= current_thread();
2054 uint64_t tid
= thread
->thread_id
;
2055 const char *procname
= "unknown";
2056 time_value_t thread_total_time
= {0, 0};
2057 time_value_t thread_system_time
;
2058 time_value_t thread_user_time
;
2061 uint32_t usage_percent
= 0;
2062 uint32_t interval_sec
;
2063 uint64_t interval_ns
;
2064 uint64_t balance_ns
;
2065 boolean_t fatal
= FALSE
;
2066 boolean_t send_exc_resource
= TRUE
; /* in addition to RESOURCE_NOTIFY */
2069 #ifdef EXC_RESOURCE_MONITORS
2070 mach_exception_data_type_t code
[EXCEPTION_CODE_MAX
];
2071 #endif /* EXC_RESOURCE_MONITORS */
2072 struct ledger_entry_info lei
;
2074 assert(thread
->t_threadledger
!= LEDGER_NULL
);
2077 * Extract the fatal bit and suspend the monitor (which clears the bit).
2080 if (task
->rusage_cpu_flags
& TASK_RUSECPU_FLAGS_FATAL_CPUMON
) {
2082 send_exc_resource
= TRUE
;
2084 /* Only one thread can be here at a time. Whichever makes it through
2085 first will successfully suspend the monitor and proceed to send the
2086 notification. Other threads will get an error trying to suspend the
2087 monitor and give up on sending the notification. In the first release,
2088 the monitor won't be resumed for a number of seconds, but we may
2089 eventually need to handle low-latency resume.
2091 kr
= task_suspend_cpumon(task
);
2093 if (kr
== KERN_INVALID_ARGUMENT
) return;
2096 pid
= proc_selfpid();
2097 if (task
->bsd_info
!= NULL
) {
2098 procname
= proc_name_address(task
->bsd_info
);
2102 thread_get_cpulimit(&action
, &percentage
, &interval_ns
);
2104 interval_sec
= (uint32_t)(interval_ns
/ NSEC_PER_SEC
);
2106 thread_read_times(thread
, &thread_user_time
, &thread_system_time
);
2107 time_value_add(&thread_total_time
, &thread_user_time
);
2108 time_value_add(&thread_total_time
, &thread_system_time
);
2109 ledger_get_entry_info(thread
->t_threadledger
, thread_ledgers
.cpu_time
, &lei
);
2111 /* credit/debit/balance/limit are in absolute time units;
2112 the refill info is in nanoseconds. */
2113 absolutetime_to_nanoseconds(lei
.lei_balance
, &balance_ns
);
2114 if (lei
.lei_last_refill
> 0) {
2115 usage_percent
= (uint32_t)((balance_ns
*100ULL) / lei
.lei_last_refill
);
2118 /* TODO: show task total runtime (via TASK_ABSOLUTETIME_INFO)? */
2119 printf("process %s[%d] thread %llu caught burning CPU! "
2120 "It used more than %d%% CPU over %u seconds "
2121 "(actual recent usage: %d%% over ~%llu seconds). "
2122 "Thread lifetime cpu usage %d.%06ds, (%d.%06d user, %d.%06d sys) "
2123 "ledger balance: %lld mabs credit: %lld mabs debit: %lld mabs "
2124 "limit: %llu mabs period: %llu ns last refill: %llu ns%s.\n",
2126 percentage
, interval_sec
,
2128 (lei
.lei_last_refill
+ NSEC_PER_SEC
/2) / NSEC_PER_SEC
,
2129 thread_total_time
.seconds
, thread_total_time
.microseconds
,
2130 thread_user_time
.seconds
, thread_user_time
.microseconds
,
2131 thread_system_time
.seconds
,thread_system_time
.microseconds
,
2132 lei
.lei_balance
, lei
.lei_credit
, lei
.lei_debit
,
2133 lei
.lei_limit
, lei
.lei_refill_period
, lei
.lei_last_refill
,
2134 (fatal
? " [fatal violation]" : ""));
2137 For now, send RESOURCE_NOTIFY in parallel with EXC_RESOURCE. Once
2138 we have logging parity, we will stop sending EXC_RESOURCE (24508922).
2141 /* RESOURCE_NOTIFY MIG specifies nanoseconds of CPU time */
2142 lei
.lei_balance
= balance_ns
;
2143 absolutetime_to_nanoseconds(lei
.lei_limit
, &lei
.lei_limit
);
2144 trace_resource_violation(RMON_CPUUSAGE_VIOLATED
, &lei
);
2145 kr
= send_resource_violation(send_cpu_usage_violation
, task
, &lei
,
2146 fatal
? kRNFatalLimitFlag
: 0);
2148 printf("send_resource_violation(CPU usage, ...): error %#x\n", kr
);
2151 #ifdef EXC_RESOURCE_MONITORS
2152 if (send_exc_resource
) {
2153 if (disable_exc_resource
) {
2154 printf("process %s[%d] thread %llu caught burning CPU! "
2155 "EXC_RESOURCE%s supressed by a boot-arg\n",
2156 procname
, pid
, tid
, fatal
? " (and termination)" : "");
2161 printf("process %s[%d] thread %llu caught burning CPU! "
2162 "EXC_RESOURCE & termination supressed due to audio playback\n",
2163 procname
, pid
, tid
);
2169 if (send_exc_resource
) {
2170 code
[0] = code
[1] = 0;
2171 EXC_RESOURCE_ENCODE_TYPE(code
[0], RESOURCE_TYPE_CPU
);
2173 EXC_RESOURCE_ENCODE_FLAVOR(code
[0], FLAVOR_CPU_MONITOR_FATAL
);
2175 EXC_RESOURCE_ENCODE_FLAVOR(code
[0], FLAVOR_CPU_MONITOR
);
2177 EXC_RESOURCE_CPUMONITOR_ENCODE_INTERVAL(code
[0], interval_sec
);
2178 EXC_RESOURCE_CPUMONITOR_ENCODE_PERCENTAGE(code
[0], percentage
);
2179 EXC_RESOURCE_CPUMONITOR_ENCODE_PERCENTAGE(code
[1], usage_percent
);
2180 exception_triage(EXC_RESOURCE
, code
, EXCEPTION_CODE_MAX
);
2182 #endif /* EXC_RESOURCE_MONITORS */
2186 jetsam_on_ledger_cpulimit_exceeded();
2188 task_terminate_internal(task
);
2193 void thread_update_io_stats(thread_t thread
, int size
, int io_flags
)
2197 if (thread
->thread_io_stats
== NULL
|| thread
->task
->task_io_stats
== NULL
)
2200 if (io_flags
& DKIO_READ
) {
2201 UPDATE_IO_STATS(thread
->thread_io_stats
->disk_reads
, size
);
2202 UPDATE_IO_STATS_ATOMIC(thread
->task
->task_io_stats
->disk_reads
, size
);
2205 if (io_flags
& DKIO_META
) {
2206 UPDATE_IO_STATS(thread
->thread_io_stats
->metadata
, size
);
2207 UPDATE_IO_STATS_ATOMIC(thread
->task
->task_io_stats
->metadata
, size
);
2210 if (io_flags
& DKIO_PAGING
) {
2211 UPDATE_IO_STATS(thread
->thread_io_stats
->paging
, size
);
2212 UPDATE_IO_STATS_ATOMIC(thread
->task
->task_io_stats
->paging
, size
);
2215 io_tier
= ((io_flags
& DKIO_TIER_MASK
) >> DKIO_TIER_SHIFT
);
2216 assert (io_tier
< IO_NUM_PRIORITIES
);
2218 UPDATE_IO_STATS(thread
->thread_io_stats
->io_priority
[io_tier
], size
);
2219 UPDATE_IO_STATS_ATOMIC(thread
->task
->task_io_stats
->io_priority
[io_tier
], size
);
2221 /* Update Total I/O Counts */
2222 UPDATE_IO_STATS(thread
->thread_io_stats
->total_io
, size
);
2223 UPDATE_IO_STATS_ATOMIC(thread
->task
->task_io_stats
->total_io
, size
);
2225 if (!(io_flags
& DKIO_READ
)) {
2226 DTRACE_IO3(physical_writes
, struct task
*, thread
->task
, uint32_t, size
, int, io_flags
);
2227 ledger_credit(thread
->task
->ledger
, task_ledgers
.physical_writes
, size
);
2232 init_thread_ledgers(void) {
2233 ledger_template_t t
;
2236 assert(thread_ledger_template
== NULL
);
2238 if ((t
= ledger_template_create("Per-thread ledger")) == NULL
)
2239 panic("couldn't create thread ledger template");
2241 if ((idx
= ledger_entry_add(t
, "cpu_time", "sched", "ns")) < 0) {
2242 panic("couldn't create cpu_time entry for thread ledger template");
2245 if (ledger_set_callback(t
, idx
, thread_cputime_callback
, NULL
, NULL
) < 0) {
2246 panic("couldn't set thread ledger callback for cpu_time entry");
2249 thread_ledgers
.cpu_time
= idx
;
2251 thread_ledger_template
= t
;
2255 * Returns currently applied CPU usage limit, or 0/0 if none is applied.
2258 thread_get_cpulimit(int *action
, uint8_t *percentage
, uint64_t *interval_ns
)
2260 int64_t abstime
= 0;
2261 uint64_t limittime
= 0;
2262 thread_t thread
= current_thread();
2268 if (thread
->t_threadledger
== LEDGER_NULL
) {
2270 * This thread has no per-thread ledger, so it can't possibly
2271 * have a CPU limit applied.
2273 return (KERN_SUCCESS
);
2276 ledger_get_period(thread
->t_threadledger
, thread_ledgers
.cpu_time
, interval_ns
);
2277 ledger_get_limit(thread
->t_threadledger
, thread_ledgers
.cpu_time
, &abstime
);
2279 if ((abstime
== LEDGER_LIMIT_INFINITY
) || (*interval_ns
== 0)) {
2281 * This thread's CPU time ledger has no period or limit; so it
2282 * doesn't have a CPU limit applied.
2284 return (KERN_SUCCESS
);
2288 * This calculation is the converse to the one in thread_set_cpulimit().
2290 absolutetime_to_nanoseconds(abstime
, &limittime
);
2291 *percentage
= (limittime
* 100ULL) / *interval_ns
;
2292 assert(*percentage
<= 100);
2294 if (thread
->options
& TH_OPT_PROC_CPULIMIT
) {
2295 assert((thread
->options
& TH_OPT_PRVT_CPULIMIT
) == 0);
2297 *action
= THREAD_CPULIMIT_BLOCK
;
2298 } else if (thread
->options
& TH_OPT_PRVT_CPULIMIT
) {
2299 assert((thread
->options
& TH_OPT_PROC_CPULIMIT
) == 0);
2301 *action
= THREAD_CPULIMIT_EXCEPTION
;
2303 *action
= THREAD_CPULIMIT_DISABLE
;
2306 return (KERN_SUCCESS
);
2310 * Set CPU usage limit on a thread.
2312 * Calling with percentage of 0 will unset the limit for this thread.
2315 thread_set_cpulimit(int action
, uint8_t percentage
, uint64_t interval_ns
)
2317 thread_t thread
= current_thread();
2319 uint64_t limittime
= 0;
2320 uint64_t abstime
= 0;
2322 assert(percentage
<= 100);
2324 if (action
== THREAD_CPULIMIT_DISABLE
) {
2326 * Remove CPU limit, if any exists.
2328 if (thread
->t_threadledger
!= LEDGER_NULL
) {
2329 l
= thread
->t_threadledger
;
2330 ledger_set_limit(l
, thread_ledgers
.cpu_time
, LEDGER_LIMIT_INFINITY
, 0);
2331 ledger_set_action(l
, thread_ledgers
.cpu_time
, LEDGER_ACTION_IGNORE
);
2332 thread
->options
&= ~(TH_OPT_PROC_CPULIMIT
| TH_OPT_PRVT_CPULIMIT
);
2338 if (interval_ns
< MINIMUM_CPULIMIT_INTERVAL_MS
* NSEC_PER_MSEC
) {
2339 return (KERN_INVALID_ARGUMENT
);
2342 l
= thread
->t_threadledger
;
2343 if (l
== LEDGER_NULL
) {
2345 * This thread doesn't yet have a per-thread ledger; so create one with the CPU time entry active.
2347 if ((l
= ledger_instantiate(thread_ledger_template
, LEDGER_CREATE_INACTIVE_ENTRIES
)) == LEDGER_NULL
)
2348 return (KERN_RESOURCE_SHORTAGE
);
2351 * We are the first to create this thread's ledger, so only activate our entry.
2353 ledger_entry_setactive(l
, thread_ledgers
.cpu_time
);
2354 thread
->t_threadledger
= l
;
2358 * The limit is specified as a percentage of CPU over an interval in nanoseconds.
2359 * Calculate the amount of CPU time that the thread needs to consume in order to hit the limit.
2361 limittime
= (interval_ns
* percentage
) / 100;
2362 nanoseconds_to_absolutetime(limittime
, &abstime
);
2363 ledger_set_limit(l
, thread_ledgers
.cpu_time
, abstime
, cpumon_ustackshots_trigger_pct
);
2365 * Refill the thread's allotted CPU time every interval_ns nanoseconds.
2367 ledger_set_period(l
, thread_ledgers
.cpu_time
, interval_ns
);
2369 if (action
== THREAD_CPULIMIT_EXCEPTION
) {
2371 * We don't support programming the CPU usage monitor on a task if any of its
2372 * threads have a per-thread blocking CPU limit configured.
2374 if (thread
->options
& TH_OPT_PRVT_CPULIMIT
) {
2375 panic("CPU usage monitor activated, but blocking thread limit exists");
2379 * Make a note that this thread's CPU limit is being used for the task-wide CPU
2380 * usage monitor. We don't have to arm the callback which will trigger the
2381 * exception, because that was done for us in ledger_instantiate (because the
2382 * ledger template used has a default callback).
2384 thread
->options
|= TH_OPT_PROC_CPULIMIT
;
2387 * We deliberately override any CPU limit imposed by a task-wide limit (eg
2388 * CPU usage monitor).
2390 thread
->options
&= ~TH_OPT_PROC_CPULIMIT
;
2392 thread
->options
|= TH_OPT_PRVT_CPULIMIT
;
2393 /* The per-thread ledger template by default has a callback for CPU time */
2394 ledger_disable_callback(l
, thread_ledgers
.cpu_time
);
2395 ledger_set_action(l
, thread_ledgers
.cpu_time
, LEDGER_ACTION_BLOCK
);
2404 __unused thread_t thread
)
2414 thread
->sched_call
= (call
!= NULL
)? call
: sched_call_null
;
2418 thread_disable_sched_call(
2423 spl_t s
= splsched();
2424 thread_lock(thread
);
2425 if (thread
->sched_call
== call
) {
2426 thread
->sched_call
= sched_call_null
;
2430 thread_unlock(thread
);
2437 thread_reenable_sched_call(
2442 spl_t s
= splsched();
2443 thread_lock(thread
);
2444 thread_sched_call(thread
, call
);
2445 thread_unlock(thread
);
2451 thread_static_param(
2455 thread_mtx_lock(thread
);
2456 thread
->static_param
= state
;
2457 thread_mtx_unlock(thread
);
2464 return (thread
!= THREAD_NULL
? thread
->thread_id
: 0);
2467 uint16_t thread_set_tag(thread_t th
, uint16_t tag
) {
2468 return thread_set_tag_internal(th
, tag
);
2470 uint16_t thread_get_tag(thread_t th
) {
2471 return thread_get_tag_internal(th
);
2475 thread_dispatchqaddr(
2478 uint64_t dispatchqueue_addr
;
2479 uint64_t thread_handle
;
2481 if (thread
== THREAD_NULL
)
2484 thread_handle
= thread
->machine
.cthread_self
;
2485 if (thread_handle
== 0)
2488 if (thread
->inspection
== TRUE
)
2489 dispatchqueue_addr
= thread_handle
+ get_task_dispatchqueue_offset(thread
->task
);
2490 else if (thread
->task
->bsd_info
)
2491 dispatchqueue_addr
= thread_handle
+ get_dispatchqueue_offset_from_proc(thread
->task
->bsd_info
);
2493 dispatchqueue_addr
= 0;
2495 return dispatchqueue_addr
;
2499 * Export routines to other components for things that are done as macros
2500 * within the osfmk component.
2503 #undef thread_reference
2504 void thread_reference(thread_t thread
);
2509 if (thread
!= THREAD_NULL
)
2510 thread_reference_internal(thread
);
2513 #undef thread_should_halt
2519 return (thread_should_halt_fast(th
));
2523 * thread_set_voucher_name - reset the voucher port name bound to this thread
2525 * Conditions: nothing locked
2527 * If we already converted the previous name to a cached voucher
2528 * reference, then we discard that reference here. The next lookup
2529 * will cache it again.
2533 thread_set_voucher_name(mach_port_name_t voucher_name
)
2535 thread_t thread
= current_thread();
2536 ipc_voucher_t new_voucher
= IPC_VOUCHER_NULL
;
2537 ipc_voucher_t voucher
;
2539 ledger_t bankledger
= NULL
;
2542 if (MACH_PORT_DEAD
== voucher_name
)
2543 return KERN_INVALID_RIGHT
;
2546 * agressively convert to voucher reference
2548 if (MACH_PORT_VALID(voucher_name
)) {
2549 new_voucher
= convert_port_name_to_voucher(voucher_name
);
2550 if (IPC_VOUCHER_NULL
== new_voucher
)
2551 return KERN_INVALID_ARGUMENT
;
2554 bankledger
= bank_get_voucher_ledger(new_voucher
);
2557 thread_mtx_lock(thread
);
2558 voucher
= thread
->ith_voucher
;
2559 thread
->ith_voucher_name
= voucher_name
;
2560 thread
->ith_voucher
= new_voucher
;
2562 bank_swap_thread_bank_ledger(thread
, bankledger
);
2564 thread_mtx_unlock(thread
);
2566 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
2567 MACHDBG_CODE(DBG_MACH_IPC
,MACH_THREAD_SET_VOUCHER
) | DBG_FUNC_NONE
,
2568 (uintptr_t)thread_tid(thread
),
2569 (uintptr_t)voucher_name
,
2570 VM_KERNEL_ADDRPERM((uintptr_t)new_voucher
),
2573 if (IPC_VOUCHER_NULL
!= voucher
)
2574 ipc_voucher_release(voucher
);
2576 return KERN_SUCCESS
;
2580 * thread_get_mach_voucher - return a voucher reference for the specified thread voucher
2582 * Conditions: nothing locked
2584 * A reference to the voucher may be lazily pending, if someone set the voucher name
2585 * but nobody has done a lookup yet. In that case, we'll have to do the equivalent
2588 * NOTE: At the moment, there is no distinction between the current and effective
2589 * vouchers because we only set them at the thread level currently.
2592 thread_get_mach_voucher(
2593 thread_act_t thread
,
2594 mach_voucher_selector_t __unused which
,
2595 ipc_voucher_t
*voucherp
)
2597 ipc_voucher_t voucher
;
2598 mach_port_name_t voucher_name
;
2600 if (THREAD_NULL
== thread
)
2601 return KERN_INVALID_ARGUMENT
;
2603 thread_mtx_lock(thread
);
2604 voucher
= thread
->ith_voucher
;
2606 /* if already cached, just return a ref */
2607 if (IPC_VOUCHER_NULL
!= voucher
) {
2608 ipc_voucher_reference(voucher
);
2609 thread_mtx_unlock(thread
);
2610 *voucherp
= voucher
;
2611 return KERN_SUCCESS
;
2614 voucher_name
= thread
->ith_voucher_name
;
2616 /* convert the name to a port, then voucher reference */
2617 if (MACH_PORT_VALID(voucher_name
)) {
2621 ipc_object_copyin(thread
->task
->itk_space
, voucher_name
,
2622 MACH_MSG_TYPE_COPY_SEND
, (ipc_object_t
*)&port
)) {
2623 thread
->ith_voucher_name
= MACH_PORT_NULL
;
2624 thread_mtx_unlock(thread
);
2625 *voucherp
= IPC_VOUCHER_NULL
;
2626 return KERN_SUCCESS
;
2629 /* convert to a voucher ref to return, and cache a ref on thread */
2630 voucher
= convert_port_to_voucher(port
);
2631 ipc_voucher_reference(voucher
);
2632 thread
->ith_voucher
= voucher
;
2633 thread_mtx_unlock(thread
);
2635 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
2636 MACHDBG_CODE(DBG_MACH_IPC
,MACH_THREAD_SET_VOUCHER
) | DBG_FUNC_NONE
,
2637 (uintptr_t)thread_tid(thread
),
2639 VM_KERNEL_ADDRPERM((uintptr_t)voucher
),
2643 ipc_port_release_send(port
);
2645 thread_mtx_unlock(thread
);
2647 *voucherp
= voucher
;
2648 return KERN_SUCCESS
;
2652 * thread_set_mach_voucher - set a voucher reference for the specified thread voucher
2654 * Conditions: callers holds a reference on the voucher.
2657 * We grab another reference to the voucher and bind it to the thread. Any lazy
2658 * binding is erased. The old voucher reference associated with the thread is
2662 thread_set_mach_voucher(
2664 ipc_voucher_t voucher
)
2666 ipc_voucher_t old_voucher
;
2668 ledger_t bankledger
= NULL
;
2671 if (THREAD_NULL
== thread
)
2672 return KERN_INVALID_ARGUMENT
;
2674 if (thread
!= current_thread() || thread
->started
)
2675 return KERN_INVALID_ARGUMENT
;
2678 ipc_voucher_reference(voucher
);
2680 bankledger
= bank_get_voucher_ledger(voucher
);
2682 thread_mtx_lock(thread
);
2683 old_voucher
= thread
->ith_voucher
;
2684 thread
->ith_voucher
= voucher
;
2685 thread
->ith_voucher_name
= MACH_PORT_NULL
;
2687 bank_swap_thread_bank_ledger(thread
, bankledger
);
2689 thread_mtx_unlock(thread
);
2691 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
2692 MACHDBG_CODE(DBG_MACH_IPC
,MACH_THREAD_SET_VOUCHER
) | DBG_FUNC_NONE
,
2693 (uintptr_t)thread_tid(thread
),
2694 (uintptr_t)MACH_PORT_NULL
,
2695 VM_KERNEL_ADDRPERM((uintptr_t)voucher
),
2698 ipc_voucher_release(old_voucher
);
2700 return KERN_SUCCESS
;
2704 * thread_swap_mach_voucher - swap a voucher reference for the specified thread voucher
2706 * Conditions: callers holds a reference on the new and presumed old voucher(s).
2709 * If the old voucher is still the same as passed in, replace it with new voucher
2710 * and discard the old (and the reference passed in). Otherwise, discard the new
2711 * and return an updated old voucher.
2714 thread_swap_mach_voucher(
2716 ipc_voucher_t new_voucher
,
2717 ipc_voucher_t
*in_out_old_voucher
)
2719 mach_port_name_t old_voucher_name
;
2720 ipc_voucher_t old_voucher
;
2722 ledger_t bankledger
= NULL
;
2725 if (THREAD_NULL
== thread
)
2726 return KERN_INVALID_TASK
;
2728 if (thread
!= current_thread() || thread
->started
)
2729 return KERN_INVALID_ARGUMENT
;
2732 bankledger
= bank_get_voucher_ledger(new_voucher
);
2735 thread_mtx_lock(thread
);
2737 old_voucher
= thread
->ith_voucher
;
2739 if (IPC_VOUCHER_NULL
== old_voucher
) {
2740 old_voucher_name
= thread
->ith_voucher_name
;
2742 /* perform lazy binding if needed */
2743 if (MACH_PORT_VALID(old_voucher_name
)) {
2744 old_voucher
= convert_port_name_to_voucher(old_voucher_name
);
2745 thread
->ith_voucher_name
= MACH_PORT_NULL
;
2746 thread
->ith_voucher
= old_voucher
;
2748 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
2749 MACHDBG_CODE(DBG_MACH_IPC
,MACH_THREAD_SET_VOUCHER
) | DBG_FUNC_NONE
,
2750 (uintptr_t)thread_tid(thread
),
2751 (uintptr_t)old_voucher_name
,
2752 VM_KERNEL_ADDRPERM((uintptr_t)old_voucher
),
2758 /* swap in new voucher, if old voucher matches the one supplied */
2759 if (old_voucher
== *in_out_old_voucher
) {
2760 ipc_voucher_reference(new_voucher
);
2761 thread
->ith_voucher
= new_voucher
;
2762 thread
->ith_voucher_name
= MACH_PORT_NULL
;
2764 bank_swap_thread_bank_ledger(thread
, bankledger
);
2766 thread_mtx_unlock(thread
);
2768 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
,
2769 MACHDBG_CODE(DBG_MACH_IPC
,MACH_THREAD_SET_VOUCHER
) | DBG_FUNC_NONE
,
2770 (uintptr_t)thread_tid(thread
),
2771 (uintptr_t)MACH_PORT_NULL
,
2772 VM_KERNEL_ADDRPERM((uintptr_t)new_voucher
),
2775 ipc_voucher_release(old_voucher
);
2777 *in_out_old_voucher
= IPC_VOUCHER_NULL
;
2778 return KERN_SUCCESS
;
2781 /* Otherwise, just return old voucher reference */
2782 ipc_voucher_reference(old_voucher
);
2783 thread_mtx_unlock(thread
);
2784 *in_out_old_voucher
= old_voucher
;
2785 return KERN_SUCCESS
;
2789 * thread_get_current_voucher_origin_pid - get the pid of the originator of the current voucher.
2792 thread_get_current_voucher_origin_pid(
2797 thread_t thread
= current_thread();
2799 buf_size
= sizeof(*pid
);
2800 kr
= mach_voucher_attr_command(thread
->ith_voucher
,
2801 MACH_VOUCHER_ATTR_KEY_BANK
,
2802 BANK_ORIGINATOR_PID
,
2805 (mach_voucher_attr_content_t
)pid
,
2812 thread_has_thread_name(thread_t th
)
2814 if ((th
) && (th
->uthread
)) {
2815 return bsd_hasthreadname(th
->uthread
);
2819 * This is an odd case; clients may set the thread name based on the lack of
2820 * a name, but in this context there is no uthread to attach the name to.
2826 thread_set_thread_name(thread_t th
, const char* name
)
2828 if ((th
) && (th
->uthread
) && name
) {
2829 bsd_setthreadname(th
->uthread
, name
);
2834 * thread_enable_send_importance - set/clear the SEND_IMPORTANCE thread option bit.
2836 void thread_enable_send_importance(thread_t thread
, boolean_t enable
)
2839 thread
->options
|= TH_OPT_SEND_IMPORTANCE
;
2841 thread
->options
&= ~TH_OPT_SEND_IMPORTANCE
;
2845 uint32_t dtrace_get_thread_predcache(thread_t thread
)
2847 if (thread
!= THREAD_NULL
)
2848 return thread
->t_dtrace_predcache
;
2853 int64_t dtrace_get_thread_vtime(thread_t thread
)
2855 if (thread
!= THREAD_NULL
)
2856 return thread
->t_dtrace_vtime
;
2861 int dtrace_get_thread_last_cpu_id(thread_t thread
)
2863 if ((thread
!= THREAD_NULL
) && (thread
->last_processor
!= PROCESSOR_NULL
)) {
2864 return thread
->last_processor
->cpu_id
;
2870 int64_t dtrace_get_thread_tracing(thread_t thread
)
2872 if (thread
!= THREAD_NULL
)
2873 return thread
->t_dtrace_tracing
;
2878 boolean_t
dtrace_get_thread_reentering(thread_t thread
)
2880 if (thread
!= THREAD_NULL
)
2881 return (thread
->options
& TH_OPT_DTRACE
) ? TRUE
: FALSE
;
2886 vm_offset_t
dtrace_get_kernel_stack(thread_t thread
)
2888 if (thread
!= THREAD_NULL
)
2889 return thread
->kernel_stack
;
2894 int64_t dtrace_calc_thread_recent_vtime(thread_t thread
)
2896 if (thread
!= THREAD_NULL
) {
2897 processor_t processor
= current_processor();
2898 uint64_t abstime
= mach_absolute_time();
2901 timer
= PROCESSOR_DATA(processor
, thread_timer
);
2903 return timer_grab(&(thread
->system_timer
)) + timer_grab(&(thread
->user_timer
)) +
2904 (abstime
- timer
->tstamp
); /* XXX need interrupts off to prevent missed time? */
2909 void dtrace_set_thread_predcache(thread_t thread
, uint32_t predcache
)
2911 if (thread
!= THREAD_NULL
)
2912 thread
->t_dtrace_predcache
= predcache
;
2915 void dtrace_set_thread_vtime(thread_t thread
, int64_t vtime
)
2917 if (thread
!= THREAD_NULL
)
2918 thread
->t_dtrace_vtime
= vtime
;
2921 void dtrace_set_thread_tracing(thread_t thread
, int64_t accum
)
2923 if (thread
!= THREAD_NULL
)
2924 thread
->t_dtrace_tracing
= accum
;
2927 void dtrace_set_thread_reentering(thread_t thread
, boolean_t vbool
)
2929 if (thread
!= THREAD_NULL
) {
2931 thread
->options
|= TH_OPT_DTRACE
;
2933 thread
->options
&= (~TH_OPT_DTRACE
);
2937 vm_offset_t
dtrace_set_thread_recover(thread_t thread
, vm_offset_t recover
)
2939 vm_offset_t prev
= 0;
2941 if (thread
!= THREAD_NULL
) {
2942 prev
= thread
->recover
;
2943 thread
->recover
= recover
;
2948 void dtrace_thread_bootstrap(void)
2950 task_t task
= current_task();
2952 if (task
->thread_count
== 1) {
2953 thread_t thread
= current_thread();
2954 if (thread
->t_dtrace_flags
& TH_DTRACE_EXECSUCCESS
) {
2955 thread
->t_dtrace_flags
&= ~TH_DTRACE_EXECSUCCESS
;
2956 DTRACE_PROC(exec__success
);
2957 KDBG(BSDDBG_CODE(DBG_BSD_PROC
,BSD_PROC_EXEC
),
2962 DTRACE_PROC(lwp__start
);
2967 dtrace_thread_didexec(thread_t thread
)
2969 thread
->t_dtrace_flags
|= TH_DTRACE_EXECSUCCESS
;
2971 #endif /* CONFIG_DTRACE */