2 * Copyright (c) 2000-2010 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 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.
58 * Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub,
61 * Task management primitives implementation.
64 * Copyright (c) 1993 The University of Utah and
65 * the Computer Systems Laboratory (CSL). All rights reserved.
67 * Permission to use, copy, modify and distribute this software and its
68 * documentation is hereby granted, provided that both the copyright
69 * notice and this permission notice appear in all copies of the
70 * software, derivative works or modified versions, and any portions
71 * thereof, and that both notices appear in supporting documentation.
73 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
74 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
75 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
77 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
78 * improvements that they make and grant CSL redistribution rights.
82 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
83 * support for mandatory and extensible security protections. This notice
84 * is included in support of clause 2.2 (b) of the Apple Public License,
86 * Copyright (c) 2005 SPARTA, Inc.
90 #include <platforms.h>
92 #include <mach/mach_types.h>
93 #include <mach/boolean.h>
94 #include <mach/host_priv.h>
95 #include <mach/machine/vm_types.h>
96 #include <mach/vm_param.h>
97 #include <mach/semaphore.h>
98 #include <mach/task_info.h>
99 #include <mach/task_special_ports.h>
101 #include <ipc/ipc_types.h>
102 #include <ipc/ipc_space.h>
103 #include <ipc/ipc_entry.h>
105 #include <kern/kern_types.h>
106 #include <kern/mach_param.h>
107 #include <kern/misc_protos.h>
108 #include <kern/task.h>
109 #include <kern/thread.h>
110 #include <kern/zalloc.h>
111 #include <kern/kalloc.h>
112 #include <kern/processor.h>
113 #include <kern/sched_prim.h> /* for thread_wakeup */
114 #include <kern/ipc_tt.h>
115 #include <kern/host.h>
116 #include <kern/clock.h>
117 #include <kern/timer.h>
118 #include <kern/assert.h>
119 #include <kern/sync_lock.h>
120 #include <kern/affinity.h>
123 #include <vm/vm_map.h>
124 #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */
125 #include <vm/vm_pageout.h>
126 #include <vm/vm_protos.h>
129 * Exported interfaces
132 #include <mach/task_server.h>
133 #include <mach/mach_host_server.h>
134 #include <mach/host_security_server.h>
135 #include <mach/mach_port_server.h>
136 #include <mach/security_server.h>
138 #include <vm/vm_shared_region.h>
141 #include <security/mac_mach_internal.h>
146 #endif /* CONFIG_COUNTERS */
150 lck_attr_t task_lck_attr
;
151 lck_grp_t task_lck_grp
;
152 lck_grp_attr_t task_lck_grp_attr
;
154 lck_mtx_t task_watch_mtx
;
155 #endif /* CONFIG_EMBEDDED */
157 zinfo_usage_store_t tasks_tkm_private
;
158 zinfo_usage_store_t tasks_tkm_shared
;
160 /* A container to accumulate statistics for expired tasks */
161 expired_task_statistics_t dead_task_statistics
;
162 lck_spin_t dead_task_statistics_lock
;
164 static ledger_template_t task_ledger_template
= NULL
;
165 struct _task_ledger_indices task_ledgers
= {-1, -1, -1, -1, -1, -1, -1};
166 void init_task_ledgers(void);
169 int task_max
= CONFIG_TASK_MAX
; /* Max number of tasks */
171 /* externs for BSD kernel */
172 extern void proc_getexecutableuuid(void *, unsigned char *, unsigned long);
176 void task_hold_locked(
178 void task_wait_locked(
180 boolean_t until_not_runnable
);
181 void task_release_locked(
185 void task_synchronizer_destroy_all(
188 int check_for_tasksuspend(
192 task_backing_store_privileged(
196 task
->priv_flags
|= VM_BACKING_STORE_PRIV
;
207 #if defined(__i386__) || defined(__x86_64__)
209 #endif /* __i386__ */
213 if (task_has_64BitAddr(task
))
216 task_set_64BitAddr(task
);
218 if ( !task_has_64BitAddr(task
))
222 * Deallocate all memory previously allocated
223 * above the 32-bit address space, since it won't
224 * be accessible anymore.
226 /* remove regular VM map entries & pmap mappings */
227 (void) vm_map_remove(task
->map
,
228 (vm_map_offset_t
) VM_MAX_ADDRESS
,
231 /* remove the higher VM mappings */
232 (void) vm_map_remove(task
->map
,
234 0xFFFFFFFFFFFFF000ULL
,
236 task_clear_64BitAddr(task
);
238 /* FIXME: On x86, the thread save state flavor can diverge from the
239 * task's 64-bit feature flag due to the 32-bit/64-bit register save
240 * state dichotomy. Since we can be pre-empted in this interval,
241 * certain routines may observe the thread as being in an inconsistent
242 * state with respect to its task's 64-bitness.
244 #if defined(__i386__) || defined(__x86_64__)
246 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
247 thread_mtx_lock(thread
);
248 machine_thread_switch_addrmode(thread
);
249 thread_mtx_unlock(thread
);
252 #endif /* __i386__ */
257 task_set_dyld_info(task_t task
, mach_vm_address_t addr
, mach_vm_size_t size
)
260 task
->all_image_info_addr
= addr
;
261 task
->all_image_info_size
= size
;
269 lck_grp_attr_setdefault(&task_lck_grp_attr
);
270 lck_grp_init(&task_lck_grp
, "task", &task_lck_grp_attr
);
271 lck_attr_setdefault(&task_lck_attr
);
272 lck_mtx_init(&tasks_threads_lock
, &task_lck_grp
, &task_lck_attr
);
274 lck_mtx_init(&task_watch_mtx
, &task_lck_grp
, &task_lck_attr
);
275 #endif /* CONFIG_EMBEDDED */
279 task_max
* sizeof(struct task
),
280 TASK_CHUNK
* sizeof(struct task
),
283 zone_change(task_zone
, Z_NOENCRYPT
, TRUE
);
288 * Create the kernel task as the first task.
291 if (task_create_internal(TASK_NULL
, FALSE
, TRUE
, &kernel_task
) != KERN_SUCCESS
)
293 if (task_create_internal(TASK_NULL
, FALSE
, FALSE
, &kernel_task
) != KERN_SUCCESS
)
295 panic("task_init\n");
297 vm_map_deallocate(kernel_task
->map
);
298 kernel_task
->map
= kernel_map
;
299 lck_spin_init(&dead_task_statistics_lock
, &task_lck_grp
, &task_lck_attr
);
303 * Create a task running in the kernel address space. It may
304 * have its own map of size mem_size and may have ipc privileges.
308 __unused task_t parent_task
,
309 __unused vm_offset_t map_base
,
310 __unused vm_size_t map_size
,
311 __unused task_t
*child_task
)
313 return (KERN_INVALID_ARGUMENT
);
319 __unused ledger_port_array_t ledger_ports
,
320 __unused mach_msg_type_number_t num_ledger_ports
,
321 __unused boolean_t inherit_memory
,
322 __unused task_t
*child_task
) /* OUT */
324 if (parent_task
== TASK_NULL
)
325 return(KERN_INVALID_ARGUMENT
);
328 * No longer supported: too many calls assume that a task has a valid
331 return(KERN_FAILURE
);
335 host_security_create_task_token(
336 host_security_t host_security
,
338 __unused security_token_t sec_token
,
339 __unused audit_token_t audit_token
,
340 __unused host_priv_t host_priv
,
341 __unused ledger_port_array_t ledger_ports
,
342 __unused mach_msg_type_number_t num_ledger_ports
,
343 __unused boolean_t inherit_memory
,
344 __unused task_t
*child_task
) /* OUT */
346 if (parent_task
== TASK_NULL
)
347 return(KERN_INVALID_ARGUMENT
);
349 if (host_security
== HOST_NULL
)
350 return(KERN_INVALID_SECURITY
);
353 * No longer supported.
355 return(KERN_FAILURE
);
359 init_task_ledgers(void)
363 assert(task_ledger_template
== NULL
);
364 assert(kernel_task
== TASK_NULL
);
366 if ((t
= ledger_template_create("Per-task ledger")) == NULL
)
367 panic("couldn't create task ledger template");
369 task_ledgers
.cpu_time
= ledger_entry_add(t
, "cpu_time", "sched", "ns");
370 task_ledgers
.tkm_private
= ledger_entry_add(t
, "tkm_private",
372 task_ledgers
.tkm_shared
= ledger_entry_add(t
, "tkm_shared", "physmem",
374 task_ledgers
.phys_mem
= ledger_entry_add(t
, "phys_mem", "physmem",
376 task_ledgers
.wired_mem
= ledger_entry_add(t
, "wired_mem", "physmem",
378 task_ledgers
.platform_idle_wakeups
= ledger_entry_add(t
, "platform_idle_wakeups", "power",
380 task_ledgers
.interrupt_wakeups
= ledger_entry_add(t
, "interrupt_wakeups", "power",
383 if ((task_ledgers
.cpu_time
< 0) || (task_ledgers
.tkm_private
< 0) ||
384 (task_ledgers
.tkm_shared
< 0) || (task_ledgers
.phys_mem
< 0) ||
385 (task_ledgers
.wired_mem
< 0) || (task_ledgers
.platform_idle_wakeups
< 0) ||
386 (task_ledgers
.interrupt_wakeups
< 0)) {
387 panic("couldn't create entries for task ledger template");
390 task_ledger_template
= t
;
394 task_create_internal(
396 boolean_t inherit_memory
,
398 task_t
*child_task
) /* OUT */
401 vm_shared_region_t shared_region
;
402 ledger_t ledger
= NULL
;
404 new_task
= (task_t
) zalloc(task_zone
);
406 if (new_task
== TASK_NULL
)
407 return(KERN_RESOURCE_SHORTAGE
);
409 /* one ref for just being alive; one for our caller */
410 new_task
->ref_count
= 2;
412 /* allocate with active entries */
413 assert(task_ledger_template
!= NULL
);
414 if ((ledger
= ledger_instantiate(task_ledger_template
,
415 LEDGER_CREATE_ACTIVE_ENTRIES
)) == NULL
) {
416 zfree(task_zone
, new_task
);
417 return(KERN_RESOURCE_SHORTAGE
);
419 new_task
->ledger
= ledger
;
421 /* if inherit_memory is true, parent_task MUST not be NULL */
423 new_task
->map
= vm_map_fork(ledger
, parent_task
->map
);
425 new_task
->map
= vm_map_create(pmap_create(ledger
, 0, is_64bit
),
426 (vm_map_offset_t
)(VM_MIN_ADDRESS
),
427 (vm_map_offset_t
)(VM_MAX_ADDRESS
), TRUE
);
429 /* Inherit memlock limit from parent */
431 vm_map_set_user_wire_limit(new_task
->map
, (vm_size_t
)parent_task
->map
->user_wire_limit
);
433 lck_mtx_init(&new_task
->lock
, &task_lck_grp
, &task_lck_attr
);
434 queue_init(&new_task
->threads
);
435 new_task
->suspend_count
= 0;
436 new_task
->thread_count
= 0;
437 new_task
->active_thread_count
= 0;
438 new_task
->user_stop_count
= 0;
439 new_task
->role
= TASK_UNSPECIFIED
;
440 new_task
->active
= TRUE
;
441 new_task
->halting
= FALSE
;
442 new_task
->user_data
= NULL
;
443 new_task
->faults
= 0;
444 new_task
->cow_faults
= 0;
445 new_task
->pageins
= 0;
446 new_task
->messages_sent
= 0;
447 new_task
->messages_received
= 0;
448 new_task
->syscalls_mach
= 0;
449 new_task
->priv_flags
= 0;
450 new_task
->syscalls_unix
=0;
451 new_task
->c_switch
= new_task
->p_switch
= new_task
->ps_switch
= 0;
452 new_task
->taskFeatures
[0] = 0; /* Init task features */
453 new_task
->taskFeatures
[1] = 0; /* Init task features */
455 zinfo_task_init(new_task
);
458 new_task
->bsd_info
= NULL
;
459 #endif /* MACH_BSD */
461 #if defined(__i386__) || defined(__x86_64__)
462 new_task
->i386_ldt
= 0;
463 new_task
->task_debug
= NULL
;
467 queue_init(&new_task
->semaphore_list
);
468 queue_init(&new_task
->lock_set_list
);
469 new_task
->semaphores_owned
= 0;
470 new_task
->lock_sets_owned
= 0;
473 new_task
->label
= labelh_new(1);
474 mac_task_label_init (&new_task
->maclabel
);
477 ipc_task_init(new_task
, parent_task
);
479 new_task
->total_user_time
= 0;
480 new_task
->total_system_time
= 0;
482 new_task
->vtimers
= 0;
484 new_task
->shared_region
= NULL
;
486 new_task
->affinity_space
= NULL
;
489 new_task
->t_chud
= 0U;
492 new_task
->pidsuspended
= FALSE
;
493 new_task
->frozen
= FALSE
;
494 new_task
->rusage_cpu_flags
= 0;
495 new_task
->rusage_cpu_percentage
= 0;
496 new_task
->rusage_cpu_interval
= 0;
497 new_task
->rusage_cpu_deadline
= 0;
498 new_task
->rusage_cpu_callt
= NULL
;
499 new_task
->proc_terminate
= 0;
501 queue_init(&new_task
->task_watchers
);
502 new_task
->appstate
= TASK_APPSTATE_ACTIVE
;
503 new_task
->num_taskwatchers
= 0;
504 new_task
->watchapplying
= 0;
505 #endif /* CONFIG_EMBEDDED */
507 new_task
->uexc_range_start
= new_task
->uexc_range_size
= new_task
->uexc_handler
= 0;
509 if (parent_task
!= TASK_NULL
) {
510 new_task
->sec_token
= parent_task
->sec_token
;
511 new_task
->audit_token
= parent_task
->audit_token
;
513 /* inherit the parent's shared region */
514 shared_region
= vm_shared_region_get(parent_task
);
515 vm_shared_region_set(new_task
, shared_region
);
517 if(task_has_64BitAddr(parent_task
))
518 task_set_64BitAddr(new_task
);
519 new_task
->all_image_info_addr
= parent_task
->all_image_info_addr
;
520 new_task
->all_image_info_size
= parent_task
->all_image_info_size
;
522 #if defined(__i386__) || defined(__x86_64__)
523 if (inherit_memory
&& parent_task
->i386_ldt
)
524 new_task
->i386_ldt
= user_ldt_copy(parent_task
->i386_ldt
);
526 if (inherit_memory
&& parent_task
->affinity_space
)
527 task_affinity_create(parent_task
, new_task
);
529 new_task
->pset_hint
= parent_task
->pset_hint
= task_choose_pset(parent_task
);
530 new_task
->policystate
= parent_task
->policystate
;
531 /* inherit the self action state */
532 new_task
->appliedstate
= parent_task
->appliedstate
;
533 new_task
->ext_policystate
= parent_task
->ext_policystate
;
535 /* till the child lifecycle is cleared do not inherit external action */
536 new_task
->ext_appliedstate
= parent_task
->ext_appliedstate
;
538 new_task
->ext_appliedstate
= default_task_null_policy
;
542 new_task
->sec_token
= KERNEL_SECURITY_TOKEN
;
543 new_task
->audit_token
= KERNEL_AUDIT_TOKEN
;
546 task_set_64BitAddr(new_task
);
548 new_task
->all_image_info_addr
= (mach_vm_address_t
)0;
549 new_task
->all_image_info_size
= (mach_vm_size_t
)0;
551 new_task
->pset_hint
= PROCESSOR_SET_NULL
;
552 new_task
->policystate
= default_task_proc_policy
;
553 new_task
->ext_policystate
= default_task_proc_policy
;
554 new_task
->appliedstate
= default_task_null_policy
;
555 new_task
->ext_appliedstate
= default_task_null_policy
;
558 if (kernel_task
== TASK_NULL
) {
559 new_task
->priority
= BASEPRI_KERNEL
;
560 new_task
->max_priority
= MAXPRI_KERNEL
;
563 new_task
->priority
= BASEPRI_DEFAULT
;
564 new_task
->max_priority
= MAXPRI_USER
;
567 bzero(&new_task
->extmod_statistics
, sizeof(new_task
->extmod_statistics
));
568 new_task
->task_timer_wakeups_bin_1
= new_task
->task_timer_wakeups_bin_2
= 0;
570 lck_mtx_lock(&tasks_threads_lock
);
571 queue_enter(&tasks
, new_task
, task_t
, tasks
);
573 lck_mtx_unlock(&tasks_threads_lock
);
575 if (vm_backing_store_low
&& parent_task
!= NULL
)
576 new_task
->priv_flags
|= (parent_task
->priv_flags
&VM_BACKING_STORE_PRIV
);
578 ipc_task_enable(new_task
);
580 *child_task
= new_task
;
581 return(KERN_SUCCESS
);
587 * Drop a reference on a task.
593 ledger_amount_t credit
, debit
, interrupt_wakeups
, platform_idle_wakeups
;
595 if (task
== TASK_NULL
)
598 if (task_deallocate_internal(task
) > 0)
601 lck_mtx_lock(&tasks_threads_lock
);
602 queue_remove(&terminated_tasks
, task
, task_t
, tasks
);
603 lck_mtx_unlock(&tasks_threads_lock
);
606 * Give the machine dependent code a chance
607 * to perform cleanup before ripping apart
610 machine_task_terminate(task
);
612 ipc_task_terminate(task
);
614 if (task
->affinity_space
)
615 task_affinity_deallocate(task
);
617 vm_map_deallocate(task
->map
);
618 is_release(task
->itk_space
);
620 ledger_get_entries(task
->ledger
, task_ledgers
.interrupt_wakeups
,
621 &interrupt_wakeups
, &debit
);
622 ledger_get_entries(task
->ledger
, task_ledgers
.platform_idle_wakeups
,
623 &platform_idle_wakeups
, &debit
);
625 /* Accumulate statistics for dead tasks */
626 lck_spin_lock(&dead_task_statistics_lock
);
627 dead_task_statistics
.total_user_time
+= task
->total_user_time
;
628 dead_task_statistics
.total_system_time
+= task
->total_system_time
;
630 dead_task_statistics
.task_interrupt_wakeups
+= interrupt_wakeups
;
631 dead_task_statistics
.task_platform_idle_wakeups
+= platform_idle_wakeups
;
633 dead_task_statistics
.task_timer_wakeups_bin_1
+= task
->task_timer_wakeups_bin_1
;
634 dead_task_statistics
.task_timer_wakeups_bin_2
+= task
->task_timer_wakeups_bin_2
;
636 lck_spin_unlock(&dead_task_statistics_lock
);
637 lck_mtx_destroy(&task
->lock
, &task_lck_grp
);
640 labelh_release(task
->label
);
643 if (!ledger_get_entries(task
->ledger
, task_ledgers
.tkm_private
, &credit
,
645 OSAddAtomic64(credit
, (int64_t *)&tasks_tkm_private
.alloc
);
646 OSAddAtomic64(debit
, (int64_t *)&tasks_tkm_private
.free
);
648 if (!ledger_get_entries(task
->ledger
, task_ledgers
.tkm_shared
, &credit
,
650 OSAddAtomic64(credit
, (int64_t *)&tasks_tkm_shared
.alloc
);
651 OSAddAtomic64(debit
, (int64_t *)&tasks_tkm_shared
.free
);
653 ledger_dereference(task
->ledger
);
654 zinfo_task_free(task
);
655 zfree(task_zone
, task
);
659 * task_name_deallocate:
661 * Drop a reference on a task name.
664 task_name_deallocate(
665 task_name_t task_name
)
667 return(task_deallocate((task_t
)task_name
));
674 * Terminate the specified task. See comments on thread_terminate
675 * (kern/thread.c) about problems with terminating the "current task."
682 if (task
== TASK_NULL
)
683 return (KERN_INVALID_ARGUMENT
);
686 return (KERN_FAILURE
);
688 return (task_terminate_internal(task
));
692 task_terminate_internal(
695 thread_t thread
, self
;
697 boolean_t interrupt_save
;
699 assert(task
!= kernel_task
);
701 self
= current_thread();
702 self_task
= self
->task
;
705 * Get the task locked and make sure that we are not racing
706 * with someone else trying to terminate us.
708 if (task
== self_task
)
711 if (task
< self_task
) {
713 task_lock(self_task
);
716 task_lock(self_task
);
722 * Task is already being terminated.
723 * Just return an error. If we are dying, this will
724 * just get us to our AST special handler and that
725 * will get us to finalize the termination of ourselves.
728 if (self_task
!= task
)
729 task_unlock(self_task
);
731 return (KERN_FAILURE
);
734 if (self_task
!= task
)
735 task_unlock(self_task
);
738 * Make sure the current thread does not get aborted out of
739 * the waits inside these operations.
741 interrupt_save
= thread_interrupt_level(THREAD_UNINT
);
744 * Indicate that we want all the threads to stop executing
745 * at user space by holding the task (we would have held
746 * each thread independently in thread_terminate_internal -
747 * but this way we may be more likely to already find it
748 * held there). Mark the task inactive, and prevent
749 * further task operations via the task port.
751 task_hold_locked(task
);
752 task
->active
= FALSE
;
753 ipc_task_disable(task
);
756 * Terminate each thread in the task.
758 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
759 thread_terminate_internal(thread
);
766 * remove all task watchers
768 task_removewatchers(task
);
769 #endif /* CONFIG_EMBEDDED */
772 * Destroy all synchronizers owned by the task.
774 task_synchronizer_destroy_all(task
);
777 * Destroy the IPC space, leaving just a reference for it.
779 ipc_space_terminate(task
->itk_space
);
781 if (vm_map_has_4GB_pagezero(task
->map
))
782 vm_map_clear_4GB_pagezero(task
->map
);
785 * If the current thread is a member of the task
786 * being terminated, then the last reference to
787 * the task will not be dropped until the thread
788 * is finally reaped. To avoid incurring the
789 * expense of removing the address space regions
790 * at reap time, we do it explictly here.
792 vm_map_remove(task
->map
,
793 task
->map
->min_offset
,
794 task
->map
->max_offset
,
797 /* release our shared region */
798 vm_shared_region_set(task
, NULL
);
800 lck_mtx_lock(&tasks_threads_lock
);
801 queue_remove(&tasks
, task
, task_t
, tasks
);
802 queue_enter(&terminated_tasks
, task
, task_t
, tasks
);
804 lck_mtx_unlock(&tasks_threads_lock
);
807 * We no longer need to guard against being aborted, so restore
808 * the previous interruptible state.
810 thread_interrupt_level(interrupt_save
);
813 * Get rid of the task active reference on itself.
815 task_deallocate(task
);
817 return (KERN_SUCCESS
);
823 * Shut the current task down (except for the current thread) in
824 * preparation for dramatic changes to the task (probably exec).
825 * We hold the task and mark all other threads in the task for
832 thread_t thread
, self
;
834 assert(task
!= kernel_task
);
836 self
= current_thread();
838 if (task
!= self
->task
)
839 return (KERN_INVALID_ARGUMENT
);
843 if (task
->halting
|| !task
->active
|| !self
->active
) {
845 * Task or current thread is already being terminated.
846 * Hurry up and return out of the current kernel context
847 * so that we run our AST special handler to terminate
852 return (KERN_FAILURE
);
855 task
->halting
= TRUE
;
857 if (task
->thread_count
> 1) {
860 * Mark all the threads to keep them from starting any more
861 * user-level execution. The thread_terminate_internal code
862 * would do this on a thread by thread basis anyway, but this
863 * gives us a better chance of not having to wait there.
865 task_hold_locked(task
);
868 * Terminate all the other threads in the task.
870 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
872 thread_terminate_internal(thread
);
875 task_release_locked(task
);
883 * task_complete_halt:
885 * Complete task halt by waiting for threads to terminate, then clean
886 * up task resources (VM, port namespace, etc...) and then let the
887 * current thread go in the (practically empty) task context.
890 task_complete_halt(task_t task
)
893 assert(task
->halting
);
894 assert(task
== current_task());
897 * Wait for the other threads to get shut down.
898 * When the last other thread is reaped, we'll be
901 if (task
->thread_count
> 1) {
902 assert_wait((event_t
)&task
->halting
, THREAD_UNINT
);
904 thread_block(THREAD_CONTINUE_NULL
);
910 * Give the machine dependent code a chance
911 * to perform cleanup of task-level resources
912 * associated with the current thread before
913 * ripping apart the task.
915 machine_task_terminate(task
);
918 * Destroy all synchronizers owned by the task.
920 task_synchronizer_destroy_all(task
);
923 * Destroy the contents of the IPC space, leaving just
924 * a reference for it.
926 ipc_space_clean(task
->itk_space
);
929 * Clean out the address space, as we are going to be
932 vm_map_remove(task
->map
, task
->map
->min_offset
,
933 task
->map
->max_offset
, VM_MAP_NO_FLAGS
);
935 task
->halting
= FALSE
;
941 * Suspend execution of the specified task.
942 * This is a recursive-style suspension of the task, a count of
943 * suspends is maintained.
945 * CONDITIONS: the task is locked and active.
949 register task_t task
)
951 register thread_t thread
;
953 assert(task
->active
);
955 if (task
->suspend_count
++ > 0)
959 * Iterate through all the threads and hold them.
961 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
962 thread_mtx_lock(thread
);
964 thread_mtx_unlock(thread
);
971 * Same as the internal routine above, except that is must lock
972 * and verify that the task is active. This differs from task_suspend
973 * in that it places a kernel hold on the task rather than just a
974 * user-level hold. This keeps users from over resuming and setting
975 * it running out from under the kernel.
977 * CONDITIONS: the caller holds a reference on the task
981 register task_t task
)
983 if (task
== TASK_NULL
)
984 return (KERN_INVALID_ARGUMENT
);
991 return (KERN_FAILURE
);
994 task_hold_locked(task
);
997 return (KERN_SUCCESS
);
1003 boolean_t until_not_runnable
)
1005 if (task
== TASK_NULL
)
1006 return (KERN_INVALID_ARGUMENT
);
1010 if (!task
->active
) {
1013 return (KERN_FAILURE
);
1016 task_wait_locked(task
, until_not_runnable
);
1019 return (KERN_SUCCESS
);
1025 * Wait for all threads in task to stop.
1028 * Called with task locked, active, and held.
1032 register task_t task
,
1033 boolean_t until_not_runnable
)
1035 register thread_t thread
, self
;
1037 assert(task
->active
);
1038 assert(task
->suspend_count
> 0);
1040 self
= current_thread();
1043 * Iterate through all the threads and wait for them to
1044 * stop. Do not wait for the current thread if it is within
1047 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1049 thread_wait(thread
, until_not_runnable
);
1054 * task_release_locked:
1056 * Release a kernel hold on a task.
1058 * CONDITIONS: the task is locked and active
1061 task_release_locked(
1062 register task_t task
)
1064 register thread_t thread
;
1066 assert(task
->active
);
1067 assert(task
->suspend_count
> 0);
1069 if (--task
->suspend_count
> 0)
1072 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1073 thread_mtx_lock(thread
);
1074 thread_release(thread
);
1075 thread_mtx_unlock(thread
);
1082 * Same as the internal routine above, except that it must lock
1083 * and verify that the task is active.
1085 * CONDITIONS: The caller holds a reference to the task
1091 if (task
== TASK_NULL
)
1092 return (KERN_INVALID_ARGUMENT
);
1096 if (!task
->active
) {
1099 return (KERN_FAILURE
);
1102 task_release_locked(task
);
1105 return (KERN_SUCCESS
);
1111 thread_act_array_t
*threads_out
,
1112 mach_msg_type_number_t
*count
)
1114 mach_msg_type_number_t actual
;
1115 thread_t
*thread_list
;
1117 vm_size_t size
, size_needed
;
1121 if (task
== TASK_NULL
)
1122 return (KERN_INVALID_ARGUMENT
);
1124 size
= 0; addr
= NULL
;
1128 if (!task
->active
) {
1134 return (KERN_FAILURE
);
1137 actual
= task
->thread_count
;
1139 /* do we have the memory we need? */
1140 size_needed
= actual
* sizeof (mach_port_t
);
1141 if (size_needed
<= size
)
1144 /* unlock the task and allocate more memory */
1150 assert(size_needed
> 0);
1153 addr
= kalloc(size
);
1155 return (KERN_RESOURCE_SHORTAGE
);
1158 /* OK, have memory and the task is locked & active */
1159 thread_list
= (thread_t
*)addr
;
1163 for (thread
= (thread_t
)queue_first(&task
->threads
); i
< actual
;
1164 ++i
, thread
= (thread_t
)queue_next(&thread
->task_threads
)) {
1165 thread_reference_internal(thread
);
1166 thread_list
[j
++] = thread
;
1169 assert(queue_end(&task
->threads
, (queue_entry_t
)thread
));
1172 size_needed
= actual
* sizeof (mach_port_t
);
1174 /* can unlock task now that we've got the thread refs */
1178 /* no threads, so return null pointer and deallocate memory */
1180 *threads_out
= NULL
;
1187 /* if we allocated too much, must copy */
1189 if (size_needed
< size
) {
1192 newaddr
= kalloc(size_needed
);
1194 for (i
= 0; i
< actual
; ++i
)
1195 thread_deallocate(thread_list
[i
]);
1197 return (KERN_RESOURCE_SHORTAGE
);
1200 bcopy(addr
, newaddr
, size_needed
);
1202 thread_list
= (thread_t
*)newaddr
;
1205 *threads_out
= thread_list
;
1208 /* do the conversion that Mig should handle */
1210 for (i
= 0; i
< actual
; ++i
)
1211 ((ipc_port_t
*) thread_list
)[i
] = convert_thread_to_port(thread_list
[i
]);
1214 return (KERN_SUCCESS
);
1217 static kern_return_t
1219 register task_t task
)
1221 if (!task
->active
) {
1222 return (KERN_FAILURE
);
1225 if (task
->user_stop_count
++ > 0) {
1227 * If the stop count was positive, the task is
1228 * already stopped and we can exit.
1230 return (KERN_SUCCESS
);
1234 * Put a kernel-level hold on the threads in the task (all
1235 * user-level task suspensions added together represent a
1236 * single kernel-level hold). We then wait for the threads
1237 * to stop executing user code.
1239 task_hold_locked(task
);
1240 task_wait_locked(task
, TRUE
);
1242 return (KERN_SUCCESS
);
1245 static kern_return_t
1247 register task_t task
,
1248 boolean_t pidresume
)
1250 register boolean_t release
= FALSE
;
1252 if (!task
->active
) {
1253 return (KERN_FAILURE
);
1257 if (task
->pidsuspended
== FALSE
) {
1258 return (KERN_FAILURE
);
1260 task
->pidsuspended
= FALSE
;
1263 if (task
->user_stop_count
> (task
->pidsuspended
? 1 : 0)) {
1264 if (--task
->user_stop_count
== 0) {
1269 return (KERN_FAILURE
);
1273 * Release the task if necessary.
1276 task_release_locked(task
);
1278 return (KERN_SUCCESS
);
1284 * Implement a user-level suspension on a task.
1287 * The caller holds a reference to the task
1291 register task_t task
)
1295 if (task
== TASK_NULL
|| task
== kernel_task
)
1296 return (KERN_INVALID_ARGUMENT
);
1300 kr
= place_task_hold(task
);
1309 * Release a kernel hold on a task.
1312 * The caller holds a reference to the task
1316 register task_t task
)
1320 if (task
== TASK_NULL
|| task
== kernel_task
)
1321 return (KERN_INVALID_ARGUMENT
);
1325 kr
= release_task_hold(task
, FALSE
);
1333 task_pidsuspend_locked(task_t task
)
1337 if (task
->pidsuspended
) {
1342 task
->pidsuspended
= TRUE
;
1344 kr
= place_task_hold(task
);
1345 if (kr
!= KERN_SUCCESS
) {
1346 task
->pidsuspended
= FALSE
;
1356 * Suspends a task by placing a hold on its threads.
1359 * The caller holds a reference to the task
1363 register task_t task
)
1367 if (task
== TASK_NULL
|| task
== kernel_task
)
1368 return (KERN_INVALID_ARGUMENT
);
1372 kr
= task_pidsuspend_locked(task
);
1379 /* If enabled, we bring all the frozen pages back in prior to resumption; otherwise, they're faulted back in on demand */
1380 #define THAW_ON_RESUME 1
1384 * Resumes a previously suspended task.
1387 * The caller holds a reference to the task
1391 register task_t task
)
1394 #if (CONFIG_FREEZE && THAW_ON_RESUME)
1398 if (task
== TASK_NULL
|| task
== kernel_task
)
1399 return (KERN_INVALID_ARGUMENT
);
1403 #if (CONFIG_FREEZE && THAW_ON_RESUME)
1404 frozen
= task
->frozen
;
1405 task
->frozen
= FALSE
;
1408 kr
= release_task_hold(task
, TRUE
);
1412 #if (CONFIG_FREEZE && THAW_ON_RESUME)
1413 if ((kr
== KERN_SUCCESS
) && (frozen
== TRUE
)) {
1414 kr
= vm_map_thaw(task
->map
);
1429 * The caller holds a reference to the task
1433 register task_t task
,
1434 uint32_t *purgeable_count
,
1435 uint32_t *wired_count
,
1436 uint32_t *clean_count
,
1437 uint32_t *dirty_count
,
1438 uint32_t dirty_budget
,
1440 boolean_t walk_only
)
1444 if (task
== TASK_NULL
|| task
== kernel_task
)
1445 return (KERN_INVALID_ARGUMENT
);
1451 return (KERN_FAILURE
);
1454 if (walk_only
== FALSE
) {
1455 task
->frozen
= TRUE
;
1461 kr
= vm_map_freeze_walk(task
->map
, purgeable_count
, wired_count
, clean_count
, dirty_count
, dirty_budget
, shared
);
1463 kr
= vm_map_freeze(task
->map
, purgeable_count
, wired_count
, clean_count
, dirty_count
, dirty_budget
, shared
);
1472 * Thaw a currently frozen task.
1475 * The caller holds a reference to the task
1479 register task_t task
)
1483 if (task
== TASK_NULL
|| task
== kernel_task
)
1484 return (KERN_INVALID_ARGUMENT
);
1488 if (!task
->frozen
) {
1490 return (KERN_FAILURE
);
1493 task
->frozen
= FALSE
;
1497 kr
= vm_map_thaw(task
->map
);
1502 #endif /* CONFIG_FREEZE */
1505 host_security_set_task_token(
1506 host_security_t host_security
,
1508 security_token_t sec_token
,
1509 audit_token_t audit_token
,
1510 host_priv_t host_priv
)
1512 ipc_port_t host_port
;
1515 if (task
== TASK_NULL
)
1516 return(KERN_INVALID_ARGUMENT
);
1518 if (host_security
== HOST_NULL
)
1519 return(KERN_INVALID_SECURITY
);
1522 task
->sec_token
= sec_token
;
1523 task
->audit_token
= audit_token
;
1526 if (host_priv
!= HOST_PRIV_NULL
) {
1527 kr
= host_get_host_priv_port(host_priv
, &host_port
);
1529 kr
= host_get_host_port(host_priv_self(), &host_port
);
1531 assert(kr
== KERN_SUCCESS
);
1532 kr
= task_set_special_port(task
, TASK_HOST_PORT
, host_port
);
1537 * This routine was added, pretty much exclusively, for registering the
1538 * RPC glue vector for in-kernel short circuited tasks. Rather than
1539 * removing it completely, I have only disabled that feature (which was
1540 * the only feature at the time). It just appears that we are going to
1541 * want to add some user data to tasks in the future (i.e. bsd info,
1542 * task names, etc...), so I left it in the formal task interface.
1547 task_flavor_t flavor
,
1548 __unused task_info_t task_info_in
, /* pointer to IN array */
1549 __unused mach_msg_type_number_t task_info_count
)
1551 if (task
== TASK_NULL
)
1552 return(KERN_INVALID_ARGUMENT
);
1556 return (KERN_INVALID_ARGUMENT
);
1558 return (KERN_SUCCESS
);
1564 task_flavor_t flavor
,
1565 task_info_t task_info_out
,
1566 mach_msg_type_number_t
*task_info_count
)
1568 kern_return_t error
= KERN_SUCCESS
;
1570 if (task
== TASK_NULL
)
1571 return (KERN_INVALID_ARGUMENT
);
1575 if ((task
!= current_task()) && (!task
->active
)) {
1577 return (KERN_INVALID_ARGUMENT
);
1582 case TASK_BASIC_INFO_32
:
1583 case TASK_BASIC2_INFO_32
:
1585 task_basic_info_32_t basic_info
;
1590 if (*task_info_count
< TASK_BASIC_INFO_32_COUNT
) {
1591 error
= KERN_INVALID_ARGUMENT
;
1595 basic_info
= (task_basic_info_32_t
)task_info_out
;
1597 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1598 basic_info
->virtual_size
= (typeof(basic_info
->virtual_size
))map
->size
;
1599 if (flavor
== TASK_BASIC2_INFO_32
) {
1601 * The "BASIC2" flavor gets the maximum resident
1602 * size instead of the current resident size...
1604 basic_info
->resident_size
= pmap_resident_max(map
->pmap
);
1606 basic_info
->resident_size
= pmap_resident_count(map
->pmap
);
1608 basic_info
->resident_size
*= PAGE_SIZE
;
1610 basic_info
->policy
= ((task
!= kernel_task
)?
1611 POLICY_TIMESHARE
: POLICY_RR
);
1612 basic_info
->suspend_count
= task
->user_stop_count
;
1614 absolutetime_to_microtime(task
->total_user_time
, &secs
, &usecs
);
1615 basic_info
->user_time
.seconds
=
1616 (typeof(basic_info
->user_time
.seconds
))secs
;
1617 basic_info
->user_time
.microseconds
= usecs
;
1619 absolutetime_to_microtime(task
->total_system_time
, &secs
, &usecs
);
1620 basic_info
->system_time
.seconds
=
1621 (typeof(basic_info
->system_time
.seconds
))secs
;
1622 basic_info
->system_time
.microseconds
= usecs
;
1624 *task_info_count
= TASK_BASIC_INFO_32_COUNT
;
1628 case TASK_BASIC_INFO_64
:
1630 task_basic_info_64_t basic_info
;
1635 if (*task_info_count
< TASK_BASIC_INFO_64_COUNT
) {
1636 error
= KERN_INVALID_ARGUMENT
;
1640 basic_info
= (task_basic_info_64_t
)task_info_out
;
1642 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1643 basic_info
->virtual_size
= map
->size
;
1644 basic_info
->resident_size
=
1645 (mach_vm_size_t
)(pmap_resident_count(map
->pmap
))
1648 basic_info
->policy
= ((task
!= kernel_task
)?
1649 POLICY_TIMESHARE
: POLICY_RR
);
1650 basic_info
->suspend_count
= task
->user_stop_count
;
1652 absolutetime_to_microtime(task
->total_user_time
, &secs
, &usecs
);
1653 basic_info
->user_time
.seconds
=
1654 (typeof(basic_info
->user_time
.seconds
))secs
;
1655 basic_info
->user_time
.microseconds
= usecs
;
1657 absolutetime_to_microtime(task
->total_system_time
, &secs
, &usecs
);
1658 basic_info
->system_time
.seconds
=
1659 (typeof(basic_info
->system_time
.seconds
))secs
;
1660 basic_info
->system_time
.microseconds
= usecs
;
1662 *task_info_count
= TASK_BASIC_INFO_64_COUNT
;
1666 case MACH_TASK_BASIC_INFO
:
1668 mach_task_basic_info_t basic_info
;
1673 if (*task_info_count
< MACH_TASK_BASIC_INFO_COUNT
) {
1674 error
= KERN_INVALID_ARGUMENT
;
1678 basic_info
= (mach_task_basic_info_t
)task_info_out
;
1680 map
= (task
== kernel_task
) ? kernel_map
: task
->map
;
1682 basic_info
->virtual_size
= map
->size
;
1684 basic_info
->resident_size
=
1685 (mach_vm_size_t
)(pmap_resident_count(map
->pmap
));
1686 basic_info
->resident_size
*= PAGE_SIZE_64
;
1688 basic_info
->resident_size_max
=
1689 (mach_vm_size_t
)(pmap_resident_max(map
->pmap
));
1690 basic_info
->resident_size_max
*= PAGE_SIZE_64
;
1692 basic_info
->policy
= ((task
!= kernel_task
) ?
1693 POLICY_TIMESHARE
: POLICY_RR
);
1695 basic_info
->suspend_count
= task
->user_stop_count
;
1697 absolutetime_to_microtime(task
->total_user_time
, &secs
, &usecs
);
1698 basic_info
->user_time
.seconds
=
1699 (typeof(basic_info
->user_time
.seconds
))secs
;
1700 basic_info
->user_time
.microseconds
= usecs
;
1702 absolutetime_to_microtime(task
->total_system_time
, &secs
, &usecs
);
1703 basic_info
->system_time
.seconds
=
1704 (typeof(basic_info
->system_time
.seconds
))secs
;
1705 basic_info
->system_time
.microseconds
= usecs
;
1707 *task_info_count
= MACH_TASK_BASIC_INFO_COUNT
;
1711 case TASK_THREAD_TIMES_INFO
:
1713 register task_thread_times_info_t times_info
;
1714 register thread_t thread
;
1716 if (*task_info_count
< TASK_THREAD_TIMES_INFO_COUNT
) {
1717 error
= KERN_INVALID_ARGUMENT
;
1721 times_info
= (task_thread_times_info_t
) task_info_out
;
1722 times_info
->user_time
.seconds
= 0;
1723 times_info
->user_time
.microseconds
= 0;
1724 times_info
->system_time
.seconds
= 0;
1725 times_info
->system_time
.microseconds
= 0;
1728 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1729 time_value_t user_time
, system_time
;
1731 thread_read_times(thread
, &user_time
, &system_time
);
1733 time_value_add(×_info
->user_time
, &user_time
);
1734 time_value_add(×_info
->system_time
, &system_time
);
1738 *task_info_count
= TASK_THREAD_TIMES_INFO_COUNT
;
1742 case TASK_ABSOLUTETIME_INFO
:
1744 task_absolutetime_info_t info
;
1745 register thread_t thread
;
1747 if (*task_info_count
< TASK_ABSOLUTETIME_INFO_COUNT
) {
1748 error
= KERN_INVALID_ARGUMENT
;
1752 info
= (task_absolutetime_info_t
)task_info_out
;
1753 info
->threads_user
= info
->threads_system
= 0;
1756 info
->total_user
= task
->total_user_time
;
1757 info
->total_system
= task
->total_system_time
;
1759 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1764 thread_lock(thread
);
1766 tval
= timer_grab(&thread
->user_timer
);
1767 info
->threads_user
+= tval
;
1768 info
->total_user
+= tval
;
1770 tval
= timer_grab(&thread
->system_timer
);
1771 if (thread
->precise_user_kernel_time
) {
1772 info
->threads_system
+= tval
;
1773 info
->total_system
+= tval
;
1775 /* system_timer may represent either sys or user */
1776 info
->threads_user
+= tval
;
1777 info
->total_user
+= tval
;
1780 thread_unlock(thread
);
1785 *task_info_count
= TASK_ABSOLUTETIME_INFO_COUNT
;
1789 case TASK_DYLD_INFO
:
1791 task_dyld_info_t info
;
1794 * We added the format field to TASK_DYLD_INFO output. For
1795 * temporary backward compatibility, accept the fact that
1796 * clients may ask for the old version - distinquished by the
1797 * size of the expected result structure.
1799 #define TASK_LEGACY_DYLD_INFO_COUNT \
1800 offsetof(struct task_dyld_info, all_image_info_format)/sizeof(natural_t)
1802 if (*task_info_count
< TASK_LEGACY_DYLD_INFO_COUNT
) {
1803 error
= KERN_INVALID_ARGUMENT
;
1807 info
= (task_dyld_info_t
)task_info_out
;
1808 info
->all_image_info_addr
= task
->all_image_info_addr
;
1809 info
->all_image_info_size
= task
->all_image_info_size
;
1811 /* only set format on output for those expecting it */
1812 if (*task_info_count
>= TASK_DYLD_INFO_COUNT
) {
1813 info
->all_image_info_format
= task_has_64BitAddr(task
) ?
1814 TASK_DYLD_ALL_IMAGE_INFO_64
:
1815 TASK_DYLD_ALL_IMAGE_INFO_32
;
1816 *task_info_count
= TASK_DYLD_INFO_COUNT
;
1818 *task_info_count
= TASK_LEGACY_DYLD_INFO_COUNT
;
1823 case TASK_EXTMOD_INFO
:
1825 task_extmod_info_t info
;
1828 if (*task_info_count
< TASK_EXTMOD_INFO_COUNT
) {
1829 error
= KERN_INVALID_ARGUMENT
;
1833 info
= (task_extmod_info_t
)task_info_out
;
1835 p
= get_bsdtask_info(task
);
1837 proc_getexecutableuuid(p
, info
->task_uuid
, sizeof(info
->task_uuid
));
1839 bzero(info
->task_uuid
, sizeof(info
->task_uuid
));
1841 info
->extmod_statistics
= task
->extmod_statistics
;
1842 *task_info_count
= TASK_EXTMOD_INFO_COUNT
;
1847 case TASK_KERNELMEMORY_INFO
:
1849 task_kernelmemory_info_t tkm_info
;
1850 ledger_amount_t credit
, debit
;
1852 if (*task_info_count
< TASK_KERNELMEMORY_INFO_COUNT
) {
1853 error
= KERN_INVALID_ARGUMENT
;
1857 tkm_info
= (task_kernelmemory_info_t
) task_info_out
;
1858 tkm_info
->total_palloc
= 0;
1859 tkm_info
->total_pfree
= 0;
1860 tkm_info
->total_salloc
= 0;
1861 tkm_info
->total_sfree
= 0;
1863 if (task
== kernel_task
) {
1865 * All shared allocs/frees from other tasks count against
1866 * the kernel private memory usage. If we are looking up
1867 * info for the kernel task, gather from everywhere.
1871 /* start by accounting for all the terminated tasks against the kernel */
1872 tkm_info
->total_palloc
= tasks_tkm_private
.alloc
+ tasks_tkm_shared
.alloc
;
1873 tkm_info
->total_pfree
= tasks_tkm_private
.free
+ tasks_tkm_shared
.free
;
1875 /* count all other task/thread shared alloc/free against the kernel */
1876 lck_mtx_lock(&tasks_threads_lock
);
1878 /* XXX this really shouldn't be using the function parameter 'task' as a local var! */
1879 queue_iterate(&tasks
, task
, task_t
, tasks
) {
1880 if (task
== kernel_task
) {
1881 if (ledger_get_entries(task
->ledger
,
1882 task_ledgers
.tkm_private
, &credit
,
1883 &debit
) == KERN_SUCCESS
) {
1884 tkm_info
->total_palloc
+= credit
;
1885 tkm_info
->total_pfree
+= debit
;
1888 if (!ledger_get_entries(task
->ledger
,
1889 task_ledgers
.tkm_shared
, &credit
, &debit
)) {
1890 tkm_info
->total_palloc
+= credit
;
1891 tkm_info
->total_pfree
+= debit
;
1894 lck_mtx_unlock(&tasks_threads_lock
);
1896 if (!ledger_get_entries(task
->ledger
,
1897 task_ledgers
.tkm_private
, &credit
, &debit
)) {
1898 tkm_info
->total_palloc
= credit
;
1899 tkm_info
->total_pfree
= debit
;
1901 if (!ledger_get_entries(task
->ledger
,
1902 task_ledgers
.tkm_shared
, &credit
, &debit
)) {
1903 tkm_info
->total_salloc
= credit
;
1904 tkm_info
->total_sfree
= debit
;
1909 *task_info_count
= TASK_KERNELMEMORY_INFO_COUNT
;
1910 return KERN_SUCCESS
;
1914 case TASK_SCHED_FIFO_INFO
:
1917 if (*task_info_count
< POLICY_FIFO_BASE_COUNT
) {
1918 error
= KERN_INVALID_ARGUMENT
;
1922 error
= KERN_INVALID_POLICY
;
1927 case TASK_SCHED_RR_INFO
:
1929 register policy_rr_base_t rr_base
;
1930 uint32_t quantum_time
;
1931 uint64_t quantum_ns
;
1933 if (*task_info_count
< POLICY_RR_BASE_COUNT
) {
1934 error
= KERN_INVALID_ARGUMENT
;
1938 rr_base
= (policy_rr_base_t
) task_info_out
;
1940 if (task
!= kernel_task
) {
1941 error
= KERN_INVALID_POLICY
;
1945 rr_base
->base_priority
= task
->priority
;
1947 quantum_time
= SCHED(initial_quantum_size
)(THREAD_NULL
);
1948 absolutetime_to_nanoseconds(quantum_time
, &quantum_ns
);
1950 rr_base
->quantum
= (uint32_t)(quantum_ns
/ 1000 / 1000);
1952 *task_info_count
= POLICY_RR_BASE_COUNT
;
1957 case TASK_SCHED_TIMESHARE_INFO
:
1959 register policy_timeshare_base_t ts_base
;
1961 if (*task_info_count
< POLICY_TIMESHARE_BASE_COUNT
) {
1962 error
= KERN_INVALID_ARGUMENT
;
1966 ts_base
= (policy_timeshare_base_t
) task_info_out
;
1968 if (task
== kernel_task
) {
1969 error
= KERN_INVALID_POLICY
;
1973 ts_base
->base_priority
= task
->priority
;
1975 *task_info_count
= POLICY_TIMESHARE_BASE_COUNT
;
1979 case TASK_SECURITY_TOKEN
:
1981 register security_token_t
*sec_token_p
;
1983 if (*task_info_count
< TASK_SECURITY_TOKEN_COUNT
) {
1984 error
= KERN_INVALID_ARGUMENT
;
1988 sec_token_p
= (security_token_t
*) task_info_out
;
1990 *sec_token_p
= task
->sec_token
;
1992 *task_info_count
= TASK_SECURITY_TOKEN_COUNT
;
1996 case TASK_AUDIT_TOKEN
:
1998 register audit_token_t
*audit_token_p
;
2000 if (*task_info_count
< TASK_AUDIT_TOKEN_COUNT
) {
2001 error
= KERN_INVALID_ARGUMENT
;
2005 audit_token_p
= (audit_token_t
*) task_info_out
;
2007 *audit_token_p
= task
->audit_token
;
2009 *task_info_count
= TASK_AUDIT_TOKEN_COUNT
;
2013 case TASK_SCHED_INFO
:
2014 error
= KERN_INVALID_ARGUMENT
;
2017 case TASK_EVENTS_INFO
:
2019 register task_events_info_t events_info
;
2020 register thread_t thread
;
2022 if (*task_info_count
< TASK_EVENTS_INFO_COUNT
) {
2023 error
= KERN_INVALID_ARGUMENT
;
2027 events_info
= (task_events_info_t
) task_info_out
;
2030 events_info
->faults
= task
->faults
;
2031 events_info
->pageins
= task
->pageins
;
2032 events_info
->cow_faults
= task
->cow_faults
;
2033 events_info
->messages_sent
= task
->messages_sent
;
2034 events_info
->messages_received
= task
->messages_received
;
2035 events_info
->syscalls_mach
= task
->syscalls_mach
;
2036 events_info
->syscalls_unix
= task
->syscalls_unix
;
2038 events_info
->csw
= task
->c_switch
;
2040 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
2041 events_info
->csw
+= thread
->c_switch
;
2042 events_info
->syscalls_mach
+= thread
->syscalls_mach
;
2043 events_info
->syscalls_unix
+= thread
->syscalls_unix
;
2047 *task_info_count
= TASK_EVENTS_INFO_COUNT
;
2050 case TASK_AFFINITY_TAG_INFO
:
2052 if (*task_info_count
< TASK_AFFINITY_TAG_INFO_COUNT
) {
2053 error
= KERN_INVALID_ARGUMENT
;
2057 error
= task_affinity_info(task
, task_info_out
, task_info_count
);
2061 case TASK_POWER_INFO
:
2063 task_power_info_t info
;
2065 ledger_amount_t tmp
;
2067 if (*task_info_count
< TASK_POWER_INFO_COUNT
) {
2068 error
= KERN_INVALID_ARGUMENT
;
2072 info
= (task_power_info_t
)task_info_out
;
2074 ledger_get_entries(task
->ledger
, task_ledgers
.interrupt_wakeups
,
2075 (ledger_amount_t
*)&info
->task_interrupt_wakeups
, &tmp
);
2076 ledger_get_entries(task
->ledger
, task_ledgers
.platform_idle_wakeups
,
2077 (ledger_amount_t
*)&info
->task_platform_idle_wakeups
, &tmp
);
2079 info
->task_timer_wakeups_bin_1
= task
->task_timer_wakeups_bin_1
;
2080 info
->task_timer_wakeups_bin_2
= task
->task_timer_wakeups_bin_2
;
2082 info
->total_user
= task
->total_user_time
;
2083 info
->total_system
= task
->total_system_time
;
2085 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
2089 if ((task
== kernel_task
) && (thread
->priority
== IDLEPRI
) && (thread
->sched_pri
== IDLEPRI
))
2092 thread_lock(thread
);
2094 info
->task_timer_wakeups_bin_1
+= thread
->thread_timer_wakeups_bin_1
;
2095 info
->task_timer_wakeups_bin_2
+= thread
->thread_timer_wakeups_bin_2
;
2097 tval
= timer_grab(&thread
->user_timer
);
2098 info
->total_user
+= tval
;
2100 tval
= timer_grab(&thread
->system_timer
);
2101 if (thread
->precise_user_kernel_time
) {
2102 info
->total_system
+= tval
;
2104 /* system_timer may represent either sys or user */
2105 info
->total_user
+= tval
;
2108 thread_unlock(thread
);
2115 error
= KERN_INVALID_ARGUMENT
;
2130 /* assert(task == current_task()); */ /* bogus assert 4803227 4807483 */
2134 task
->vtimers
|= which
;
2138 case TASK_VTIMER_USER
:
2139 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
2141 thread_lock(thread
);
2142 if (thread
->precise_user_kernel_time
)
2143 thread
->vtimer_user_save
= timer_grab(&thread
->user_timer
);
2145 thread
->vtimer_user_save
= timer_grab(&thread
->system_timer
);
2146 thread_unlock(thread
);
2151 case TASK_VTIMER_PROF
:
2152 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
2154 thread_lock(thread
);
2155 thread
->vtimer_prof_save
= timer_grab(&thread
->user_timer
);
2156 thread
->vtimer_prof_save
+= timer_grab(&thread
->system_timer
);
2157 thread_unlock(thread
);
2162 case TASK_VTIMER_RLIM
:
2163 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
2165 thread_lock(thread
);
2166 thread
->vtimer_rlim_save
= timer_grab(&thread
->user_timer
);
2167 thread
->vtimer_rlim_save
+= timer_grab(&thread
->system_timer
);
2168 thread_unlock(thread
);
2182 assert(task
== current_task());
2186 task
->vtimers
&= ~which
;
2196 uint32_t *microsecs
)
2198 thread_t thread
= current_thread();
2203 assert(task
== current_task());
2205 assert(task
->vtimers
& which
);
2211 case TASK_VTIMER_USER
:
2212 if (thread
->precise_user_kernel_time
) {
2213 tdelt
= (uint32_t)timer_delta(&thread
->user_timer
,
2214 &thread
->vtimer_user_save
);
2216 tdelt
= (uint32_t)timer_delta(&thread
->system_timer
,
2217 &thread
->vtimer_user_save
);
2219 absolutetime_to_microtime(tdelt
, &secs
, microsecs
);
2222 case TASK_VTIMER_PROF
:
2223 tsum
= timer_grab(&thread
->user_timer
);
2224 tsum
+= timer_grab(&thread
->system_timer
);
2225 tdelt
= (uint32_t)(tsum
- thread
->vtimer_prof_save
);
2226 absolutetime_to_microtime(tdelt
, &secs
, microsecs
);
2227 /* if the time delta is smaller than a usec, ignore */
2228 if (*microsecs
!= 0)
2229 thread
->vtimer_prof_save
= tsum
;
2232 case TASK_VTIMER_RLIM
:
2233 tsum
= timer_grab(&thread
->user_timer
);
2234 tsum
+= timer_grab(&thread
->system_timer
);
2235 tdelt
= (uint32_t)(tsum
- thread
->vtimer_rlim_save
);
2236 thread
->vtimer_rlim_save
= tsum
;
2237 absolutetime_to_microtime(tdelt
, &secs
, microsecs
);
2246 * Change the assigned processor set for the task
2250 __unused task_t task
,
2251 __unused processor_set_t new_pset
,
2252 __unused boolean_t assign_threads
)
2254 return(KERN_FAILURE
);
2258 * task_assign_default:
2260 * Version of task_assign to assign to default processor set.
2263 task_assign_default(
2265 boolean_t assign_threads
)
2267 return (task_assign(task
, &pset0
, assign_threads
));
2271 * task_get_assignment
2273 * Return name of processor set that task is assigned to.
2276 task_get_assignment(
2278 processor_set_t
*pset
)
2281 return(KERN_FAILURE
);
2285 return (KERN_SUCCESS
);
2292 * Set scheduling policy and parameters, both base and limit, for
2293 * the given task. Policy must be a policy which is enabled for the
2294 * processor set. Change contained threads if requested.
2298 __unused task_t task
,
2299 __unused policy_t policy_id
,
2300 __unused policy_base_t base
,
2301 __unused mach_msg_type_number_t count
,
2302 __unused boolean_t set_limit
,
2303 __unused boolean_t change
)
2305 return(KERN_FAILURE
);
2311 * Set scheduling policy and parameters, both base and limit, for
2312 * the given task. Policy can be any policy implemented by the
2313 * processor set, whether enabled or not. Change contained threads
2318 __unused task_t task
,
2319 __unused processor_set_t pset
,
2320 __unused policy_t policy_id
,
2321 __unused policy_base_t base
,
2322 __unused mach_msg_type_number_t base_count
,
2323 __unused policy_limit_t limit
,
2324 __unused mach_msg_type_number_t limit_count
,
2325 __unused boolean_t change
)
2327 return(KERN_FAILURE
);
2337 extern int fast_tas_debug
;
2339 if (fast_tas_debug
) {
2340 printf("task 0x%x: setting fast_tas to [0x%x, 0x%x]\n",
2344 task
->fast_tas_base
= pc
;
2345 task
->fast_tas_end
= endpc
;
2347 return KERN_SUCCESS
;
2349 #else /* FAST_TAS */
2352 __unused task_t task
,
2353 __unused vm_offset_t pc
,
2354 __unused vm_offset_t endpc
)
2356 return KERN_FAILURE
;
2358 #endif /* FAST_TAS */
2361 task_synchronizer_destroy_all(task_t task
)
2363 semaphore_t semaphore
;
2364 lock_set_t lock_set
;
2367 * Destroy owned semaphores
2370 while (!queue_empty(&task
->semaphore_list
)) {
2371 semaphore
= (semaphore_t
) queue_first(&task
->semaphore_list
);
2372 (void) semaphore_destroy(task
, semaphore
);
2376 * Destroy owned lock sets
2379 while (!queue_empty(&task
->lock_set_list
)) {
2380 lock_set
= (lock_set_t
) queue_first(&task
->lock_set_list
);
2381 (void) lock_set_destroy(task
, lock_set
);
2386 * Install default (machine-dependent) initial thread state
2387 * on the task. Subsequent thread creation will have this initial
2388 * state set on the thread by machine_thread_inherit_taskwide().
2389 * Flavors and structures are exactly the same as those to thread_set_state()
2395 thread_state_t state
,
2396 mach_msg_type_number_t state_count
)
2400 if (task
== TASK_NULL
) {
2401 return (KERN_INVALID_ARGUMENT
);
2406 if (!task
->active
) {
2408 return (KERN_FAILURE
);
2411 ret
= machine_task_set_state(task
, flavor
, state
, state_count
);
2418 * Examine the default (machine-dependent) initial thread state
2419 * on the task, as set by task_set_state(). Flavors and structures
2420 * are exactly the same as those passed to thread_get_state().
2426 thread_state_t state
,
2427 mach_msg_type_number_t
*state_count
)
2431 if (task
== TASK_NULL
) {
2432 return (KERN_INVALID_ARGUMENT
);
2437 if (!task
->active
) {
2439 return (KERN_FAILURE
);
2442 ret
= machine_task_get_state(task
, flavor
, state
, state_count
);
2450 * We need to export some functions to other components that
2451 * are currently implemented in macros within the osfmk
2452 * component. Just export them as functions of the same name.
2454 boolean_t
is_kerneltask(task_t t
)
2456 if (t
== kernel_task
)
2463 check_for_tasksuspend(task_t task
)
2466 if (task
== TASK_NULL
)
2469 return (task
->suspend_count
> 0);
2473 task_t
current_task(void);
2474 task_t
current_task(void)
2476 return (current_task_fast());
2479 #undef task_reference
2480 void task_reference(task_t task
);
2485 if (task
!= TASK_NULL
)
2486 task_reference_internal(task
);
2490 * This routine is called always with task lock held.
2491 * And it returns a thread handle without reference as the caller
2492 * operates on it under the task lock held.
2495 task_findtid(task_t task
, uint64_t tid
)
2497 thread_t thread
= THREAD_NULL
;
2499 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
2500 if (thread
->thread_id
== tid
)
2503 return(THREAD_NULL
);
2507 #if CONFIG_MACF_MACH
2509 * Protect 2 task labels against modification by adding a reference on
2510 * both label handles. The locks do not actually have to be held while
2511 * using the labels as only labels with one reference can be modified
2520 labelh_reference(a
->label
);
2521 labelh_reference(b
->label
);
2529 labelh_release(a
->label
);
2530 labelh_release(b
->label
);
2534 mac_task_label_update_internal(
2539 tasklabel_lock(task
);
2540 task
->label
= labelh_modify(task
->label
);
2541 mac_task_label_update(pl
, &task
->maclabel
);
2542 tasklabel_unlock(task
);
2543 ip_lock(task
->itk_self
);
2544 mac_port_label_update_cred(pl
, &task
->itk_self
->ip_label
);
2545 ip_unlock(task
->itk_self
);
2549 mac_task_label_modify(
2552 void (*f
) (struct label
*l
, void *arg
))
2555 tasklabel_lock(task
);
2556 task
->label
= labelh_modify(task
->label
);
2557 (*f
)(&task
->maclabel
, arg
);
2558 tasklabel_unlock(task
);
2562 mac_task_get_label(struct task
*task
)
2564 return (&task
->maclabel
);