2 * Copyright (c) 2000-2009 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.
91 #include <platforms.h>
93 #include <mach/mach_types.h>
94 #include <mach/boolean.h>
95 #include <mach/host_priv.h>
96 #include <mach/machine/vm_types.h>
97 #include <mach/vm_param.h>
98 #include <mach/semaphore.h>
99 #include <mach/task_info.h>
100 #include <mach/task_special_ports.h>
102 #include <ipc/ipc_types.h>
103 #include <ipc/ipc_space.h>
104 #include <ipc/ipc_entry.h>
106 #include <kern/kern_types.h>
107 #include <kern/mach_param.h>
108 #include <kern/misc_protos.h>
109 #include <kern/task.h>
110 #include <kern/thread.h>
111 #include <kern/zalloc.h>
112 #include <kern/kalloc.h>
113 #include <kern/processor.h>
114 #include <kern/sched_prim.h> /* for thread_wakeup */
115 #include <kern/ipc_tt.h>
116 #include <kern/ledger.h>
117 #include <kern/host.h>
118 #include <kern/clock.h>
119 #include <kern/timer.h>
120 #include <kern/assert.h>
121 #include <kern/sync_lock.h>
122 #include <kern/affinity.h>
125 #include <vm/vm_map.h>
126 #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */
127 #include <vm/vm_pageout.h>
128 #include <vm/vm_protos.h>
131 #include <ddb/db_sym.h>
132 #endif /* MACH_KDB */
135 #include <ppc/exception.h>
136 #include <ppc/hw_perfmon.h>
141 * Exported interfaces
144 #include <mach/task_server.h>
145 #include <mach/mach_host_server.h>
146 #include <mach/host_security_server.h>
147 #include <mach/mach_port_server.h>
148 #include <mach/security_server.h>
150 #include <vm/vm_shared_region.h>
153 #include <security/mac_mach_internal.h>
158 #endif /* CONFIG_COUNTERS */
162 lck_attr_t task_lck_attr
;
163 lck_grp_t task_lck_grp
;
164 lck_grp_attr_t task_lck_grp_attr
;
166 int task_max
= CONFIG_TASK_MAX
; /* Max number of tasks */
170 void task_hold_locked(
172 void task_wait_locked(
174 void task_release_locked(
178 void task_synchronizer_destroy_all(
181 kern_return_t
task_set_ledger(
186 int check_for_tasksuspend(
190 task_backing_store_privileged(
194 task
->priv_flags
|= VM_BACKING_STORE_PRIV
;
205 #if defined(__i386__) || defined(__x86_64__)
207 #endif /* __i386__ */
211 if (task_has_64BitAddr(task
))
214 task_set_64BitAddr(task
);
216 if ( !task_has_64BitAddr(task
))
220 * Deallocate all memory previously allocated
221 * above the 32-bit address space, since it won't
222 * be accessible anymore.
224 /* remove regular VM map entries & pmap mappings */
225 (void) vm_map_remove(task
->map
,
226 (vm_map_offset_t
) VM_MAX_ADDRESS
,
231 * PPC51: ppc64 is limited to 51-bit addresses.
232 * Memory mapped above that limit is handled specially
233 * at the pmap level, so let pmap clean the commpage mapping
236 pmap_unmap_sharedpage(task
->map
->pmap
); /* Unmap commpage */
237 /* ... and avoid regular pmap cleanup */
238 vm_flags
|= VM_MAP_REMOVE_NO_PMAP_CLEANUP
;
240 /* remove the higher VM mappings */
241 (void) vm_map_remove(task
->map
,
243 0xFFFFFFFFFFFFF000ULL
,
245 task_clear_64BitAddr(task
);
247 /* FIXME: On x86, the thread save state flavor can diverge from the
248 * task's 64-bit feature flag due to the 32-bit/64-bit register save
249 * state dichotomy. Since we can be pre-empted in this interval,
250 * certain routines may observe the thread as being in an inconsistent
251 * state with respect to its task's 64-bitness.
253 #if defined(__i386__) || defined(__x86_64__)
255 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
256 thread_mtx_lock(thread
);
257 machine_thread_switch_addrmode(thread
);
258 thread_mtx_unlock(thread
);
261 #endif /* __i386__ */
266 task_set_dyld_info(task_t task
, mach_vm_address_t addr
, mach_vm_size_t size
)
269 task
->all_image_info_addr
= addr
;
270 task
->all_image_info_size
= size
;
278 lck_grp_attr_setdefault(&task_lck_grp_attr
);
279 lck_grp_init(&task_lck_grp
, "task", &task_lck_grp_attr
);
280 lck_attr_setdefault(&task_lck_attr
);
281 lck_mtx_init(&tasks_threads_lock
, &task_lck_grp
, &task_lck_attr
);
285 task_max
* sizeof(struct task
),
286 TASK_CHUNK
* sizeof(struct task
),
288 zone_change(task_zone
, Z_NOENCRYPT
, TRUE
);
291 * Create the kernel task as the first task.
294 if (task_create_internal(TASK_NULL
, FALSE
, TRUE
, &kernel_task
) != KERN_SUCCESS
)
296 if (task_create_internal(TASK_NULL
, FALSE
, FALSE
, &kernel_task
) != KERN_SUCCESS
)
298 panic("task_init\n");
300 vm_map_deallocate(kernel_task
->map
);
301 kernel_task
->map
= kernel_map
;
305 * Create a task running in the kernel address space. It may
306 * have its own map of size mem_size and may have ipc privileges.
310 __unused task_t parent_task
,
311 __unused vm_offset_t map_base
,
312 __unused vm_size_t map_size
,
313 __unused task_t
*child_task
)
315 return (KERN_INVALID_ARGUMENT
);
321 __unused ledger_port_array_t ledger_ports
,
322 __unused mach_msg_type_number_t num_ledger_ports
,
323 __unused boolean_t inherit_memory
,
324 __unused task_t
*child_task
) /* OUT */
326 if (parent_task
== TASK_NULL
)
327 return(KERN_INVALID_ARGUMENT
);
330 * No longer supported: too many calls assume that a task has a valid
333 return(KERN_FAILURE
);
337 host_security_create_task_token(
338 host_security_t host_security
,
340 __unused security_token_t sec_token
,
341 __unused audit_token_t audit_token
,
342 __unused host_priv_t host_priv
,
343 __unused ledger_port_array_t ledger_ports
,
344 __unused mach_msg_type_number_t num_ledger_ports
,
345 __unused boolean_t inherit_memory
,
346 __unused task_t
*child_task
) /* OUT */
348 if (parent_task
== TASK_NULL
)
349 return(KERN_INVALID_ARGUMENT
);
351 if (host_security
== HOST_NULL
)
352 return(KERN_INVALID_SECURITY
);
355 * No longer supported.
357 return(KERN_FAILURE
);
361 task_create_internal(
363 boolean_t inherit_memory
,
365 task_t
*child_task
) /* OUT */
368 vm_shared_region_t shared_region
;
370 new_task
= (task_t
) zalloc(task_zone
);
372 if (new_task
== TASK_NULL
)
373 return(KERN_RESOURCE_SHORTAGE
);
375 /* one ref for just being alive; one for our caller */
376 new_task
->ref_count
= 2;
378 /* if inherit_memory is true, parent_task MUST not be NULL */
380 new_task
->map
= vm_map_fork(parent_task
->map
);
382 new_task
->map
= vm_map_create(pmap_create(0, is_64bit
),
383 (vm_map_offset_t
)(VM_MIN_ADDRESS
),
384 (vm_map_offset_t
)(VM_MAX_ADDRESS
), TRUE
);
386 /* Inherit memlock limit from parent */
388 vm_map_set_user_wire_limit(new_task
->map
, (vm_size_t
)parent_task
->map
->user_wire_limit
);
390 lck_mtx_init(&new_task
->lock
, &task_lck_grp
, &task_lck_attr
);
391 queue_init(&new_task
->threads
);
392 new_task
->suspend_count
= 0;
393 new_task
->thread_count
= 0;
394 new_task
->active_thread_count
= 0;
395 new_task
->user_stop_count
= 0;
396 new_task
->role
= TASK_UNSPECIFIED
;
397 new_task
->active
= TRUE
;
398 new_task
->halting
= FALSE
;
399 new_task
->user_data
= NULL
;
400 new_task
->faults
= 0;
401 new_task
->cow_faults
= 0;
402 new_task
->pageins
= 0;
403 new_task
->messages_sent
= 0;
404 new_task
->messages_received
= 0;
405 new_task
->syscalls_mach
= 0;
406 new_task
->priv_flags
= 0;
407 new_task
->syscalls_unix
=0;
408 new_task
->c_switch
= new_task
->p_switch
= new_task
->ps_switch
= 0;
409 new_task
->taskFeatures
[0] = 0; /* Init task features */
410 new_task
->taskFeatures
[1] = 0; /* Init task features */
413 new_task
->bsd_info
= NULL
;
414 #endif /* MACH_BSD */
416 #if defined(__i386__) || defined(__x86_64__)
417 new_task
->i386_ldt
= 0;
418 new_task
->task_debug
= NULL
;
423 if(BootProcInfo
.pf
.Available
& pf64Bit
) new_task
->taskFeatures
[0] |= tf64BitData
; /* If 64-bit machine, show we have 64-bit registers at least */
426 queue_init(&new_task
->semaphore_list
);
427 queue_init(&new_task
->lock_set_list
);
428 new_task
->semaphores_owned
= 0;
429 new_task
->lock_sets_owned
= 0;
432 new_task
->label
= labelh_new(1);
433 mac_task_label_init (&new_task
->maclabel
);
436 ipc_task_init(new_task
, parent_task
);
438 new_task
->total_user_time
= 0;
439 new_task
->total_system_time
= 0;
441 new_task
->vtimers
= 0;
443 new_task
->shared_region
= NULL
;
445 new_task
->affinity_space
= NULL
;
448 new_task
->t_chud
= 0U;
451 if (parent_task
!= TASK_NULL
) {
452 new_task
->sec_token
= parent_task
->sec_token
;
453 new_task
->audit_token
= parent_task
->audit_token
;
455 /* inherit the parent's shared region */
456 shared_region
= vm_shared_region_get(parent_task
);
457 vm_shared_region_set(new_task
, shared_region
);
459 new_task
->wired_ledger_port
= ledger_copy(
460 convert_port_to_ledger(parent_task
->wired_ledger_port
));
461 new_task
->paged_ledger_port
= ledger_copy(
462 convert_port_to_ledger(parent_task
->paged_ledger_port
));
463 if(task_has_64BitAddr(parent_task
))
464 task_set_64BitAddr(new_task
);
465 new_task
->all_image_info_addr
= parent_task
->all_image_info_addr
;
466 new_task
->all_image_info_size
= parent_task
->all_image_info_size
;
468 #if defined(__i386__) || defined(__x86_64__)
469 if (inherit_memory
&& parent_task
->i386_ldt
)
470 new_task
->i386_ldt
= user_ldt_copy(parent_task
->i386_ldt
);
472 if (inherit_memory
&& parent_task
->affinity_space
)
473 task_affinity_create(parent_task
, new_task
);
475 new_task
->pset_hint
= parent_task
->pset_hint
= task_choose_pset(parent_task
);
478 new_task
->sec_token
= KERNEL_SECURITY_TOKEN
;
479 new_task
->audit_token
= KERNEL_AUDIT_TOKEN
;
480 new_task
->wired_ledger_port
= ledger_copy(root_wired_ledger
);
481 new_task
->paged_ledger_port
= ledger_copy(root_paged_ledger
);
484 task_set_64BitAddr(new_task
);
487 new_task
->pset_hint
= PROCESSOR_SET_NULL
;
490 if (kernel_task
== TASK_NULL
) {
491 new_task
->priority
= BASEPRI_KERNEL
;
492 new_task
->max_priority
= MAXPRI_KERNEL
;
495 new_task
->priority
= BASEPRI_DEFAULT
;
496 new_task
->max_priority
= MAXPRI_USER
;
499 lck_mtx_lock(&tasks_threads_lock
);
500 queue_enter(&tasks
, new_task
, task_t
, tasks
);
502 lck_mtx_unlock(&tasks_threads_lock
);
504 if (vm_backing_store_low
&& parent_task
!= NULL
)
505 new_task
->priv_flags
|= (parent_task
->priv_flags
&VM_BACKING_STORE_PRIV
);
507 ipc_task_enable(new_task
);
509 *child_task
= new_task
;
510 return(KERN_SUCCESS
);
516 * Drop a reference on a task.
522 if (task
== TASK_NULL
)
525 if (task_deallocate_internal(task
) > 0)
528 ipc_task_terminate(task
);
530 if (task
->affinity_space
)
531 task_affinity_deallocate(task
);
533 vm_map_deallocate(task
->map
);
534 is_release(task
->itk_space
);
536 lck_mtx_destroy(&task
->lock
, &task_lck_grp
);
539 labelh_release(task
->label
);
541 zfree(task_zone
, task
);
545 * task_name_deallocate:
547 * Drop a reference on a task name.
550 task_name_deallocate(
551 task_name_t task_name
)
553 return(task_deallocate((task_t
)task_name
));
560 * Terminate the specified task. See comments on thread_terminate
561 * (kern/thread.c) about problems with terminating the "current task."
568 if (task
== TASK_NULL
)
569 return (KERN_INVALID_ARGUMENT
);
572 return (KERN_FAILURE
);
574 return (task_terminate_internal(task
));
578 task_terminate_internal(
581 thread_t thread
, self
;
583 boolean_t interrupt_save
;
585 assert(task
!= kernel_task
);
587 self
= current_thread();
588 self_task
= self
->task
;
591 * Get the task locked and make sure that we are not racing
592 * with someone else trying to terminate us.
594 if (task
== self_task
)
597 if (task
< self_task
) {
599 task_lock(self_task
);
602 task_lock(self_task
);
606 if (!task
->active
|| !self
->active
) {
608 * Task or current act is already being terminated.
609 * Just return an error. If we are dying, this will
610 * just get us to our AST special handler and that
611 * will get us to finalize the termination of ourselves.
614 if (self_task
!= task
)
615 task_unlock(self_task
);
617 return (KERN_FAILURE
);
620 if (self_task
!= task
)
621 task_unlock(self_task
);
624 * Make sure the current thread does not get aborted out of
625 * the waits inside these operations.
627 interrupt_save
= thread_interrupt_level(THREAD_UNINT
);
630 * Indicate that we want all the threads to stop executing
631 * at user space by holding the task (we would have held
632 * each thread independently in thread_terminate_internal -
633 * but this way we may be more likely to already find it
634 * held there). Mark the task inactive, and prevent
635 * further task operations via the task port.
637 task_hold_locked(task
);
638 task
->active
= FALSE
;
639 ipc_task_disable(task
);
642 * Terminate each thread in the task.
644 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
645 thread_terminate_internal(thread
);
649 * Give the machine dependent code a chance
650 * to perform cleanup before ripping apart
653 if (self_task
== task
)
654 machine_thread_terminate_self();
659 * Destroy all synchronizers owned by the task.
661 task_synchronizer_destroy_all(task
);
664 * Destroy the IPC space, leaving just a reference for it.
666 ipc_space_destroy(task
->itk_space
);
670 * PPC51: ppc64 is limited to 51-bit addresses.
672 pmap_unmap_sharedpage(task
->map
->pmap
); /* Unmap commpage */
675 if (vm_map_has_4GB_pagezero(task
->map
))
676 vm_map_clear_4GB_pagezero(task
->map
);
679 * If the current thread is a member of the task
680 * being terminated, then the last reference to
681 * the task will not be dropped until the thread
682 * is finally reaped. To avoid incurring the
683 * expense of removing the address space regions
684 * at reap time, we do it explictly here.
686 vm_map_remove(task
->map
,
687 task
->map
->min_offset
,
688 task
->map
->max_offset
,
691 /* release our shared region */
692 vm_shared_region_set(task
, NULL
);
694 lck_mtx_lock(&tasks_threads_lock
);
695 queue_remove(&tasks
, task
, task_t
, tasks
);
697 lck_mtx_unlock(&tasks_threads_lock
);
700 * We no longer need to guard against being aborted, so restore
701 * the previous interruptible state.
703 thread_interrupt_level(interrupt_save
);
706 perfmon_release_facility(task
); // notify the perfmon facility
710 * Get rid of the task active reference on itself.
712 task_deallocate(task
);
714 return (KERN_SUCCESS
);
720 * Shut the current task down (except for the current thread) in
721 * preparation for dramatic changes to the task (probably exec).
722 * We hold the task and mark all other threads in the task for
729 thread_t thread
, self
;
731 assert(task
!= kernel_task
);
733 self
= current_thread();
735 if (task
!= self
->task
)
736 return (KERN_INVALID_ARGUMENT
);
740 if (task
->halting
|| !task
->active
|| !self
->active
) {
742 * Task or current thread is already being terminated.
743 * Hurry up and return out of the current kernel context
744 * so that we run our AST special handler to terminate
749 return (KERN_FAILURE
);
752 task
->halting
= TRUE
;
754 if (task
->thread_count
> 1) {
757 * Mark all the threads to keep them from starting any more
758 * user-level execution. The thread_terminate_internal code
759 * would do this on a thread by thread basis anyway, but this
760 * gives us a better chance of not having to wait there.
762 task_hold_locked(task
);
765 * Terminate all the other threads in the task.
767 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
769 thread_terminate_internal(thread
);
772 task_release_locked(task
);
780 * task_complete_halt:
782 * Complete task halt by waiting for threads to terminate, then clean
783 * up task resources (VM, port namespace, etc...) and then let the
784 * current thread go in the (practically empty) task context.
787 task_complete_halt(task_t task
)
790 assert(task
->halting
);
791 assert(task
== current_task());
794 * Give the machine dependent code a chance
795 * to perform cleanup of task-level resources
796 * associated with the current thread before
797 * ripping apart the task.
799 * This must be done with the task locked.
801 machine_thread_terminate_self();
804 * Wait for the other threads to get shut down.
805 * When the last other thread is reaped, we'll be
808 if (task
->thread_count
> 1) {
809 assert_wait((event_t
)&task
->halting
, THREAD_UNINT
);
811 thread_block(THREAD_CONTINUE_NULL
);
817 * Destroy all synchronizers owned by the task.
819 task_synchronizer_destroy_all(task
);
822 * Destroy the contents of the IPC space, leaving just
823 * a reference for it.
825 ipc_space_clean(task
->itk_space
);
828 * Clean out the address space, as we are going to be
831 vm_map_remove(task
->map
, task
->map
->min_offset
,
832 task
->map
->max_offset
, VM_MAP_NO_FLAGS
);
834 task
->halting
= FALSE
;
840 * Suspend execution of the specified task.
841 * This is a recursive-style suspension of the task, a count of
842 * suspends is maintained.
844 * CONDITIONS: the task is locked and active.
848 register task_t task
)
850 register thread_t thread
;
852 assert(task
->active
);
854 if (task
->suspend_count
++ > 0)
858 * Iterate through all the threads and hold them.
860 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
861 thread_mtx_lock(thread
);
863 thread_mtx_unlock(thread
);
870 * Same as the internal routine above, except that is must lock
871 * and verify that the task is active. This differs from task_suspend
872 * in that it places a kernel hold on the task rather than just a
873 * user-level hold. This keeps users from over resuming and setting
874 * it running out from under the kernel.
876 * CONDITIONS: the caller holds a reference on the task
880 register task_t task
)
882 if (task
== TASK_NULL
)
883 return (KERN_INVALID_ARGUMENT
);
890 return (KERN_FAILURE
);
893 task_hold_locked(task
);
896 return (KERN_SUCCESS
);
902 * Wait for all threads in task to stop.
905 * Called with task locked, active, and held.
909 register task_t task
)
911 register thread_t thread
, self
;
913 assert(task
->active
);
914 assert(task
->suspend_count
> 0);
916 self
= current_thread();
919 * Iterate through all the threads and wait for them to
920 * stop. Do not wait for the current thread if it is within
923 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
930 * task_release_locked:
932 * Release a kernel hold on a task.
934 * CONDITIONS: the task is locked and active
938 register task_t task
)
940 register thread_t thread
;
942 assert(task
->active
);
943 assert(task
->suspend_count
> 0);
945 if (--task
->suspend_count
> 0)
948 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
949 thread_mtx_lock(thread
);
950 thread_release(thread
);
951 thread_mtx_unlock(thread
);
958 * Same as the internal routine above, except that it must lock
959 * and verify that the task is active.
961 * CONDITIONS: The caller holds a reference to the task
967 if (task
== TASK_NULL
)
968 return (KERN_INVALID_ARGUMENT
);
975 return (KERN_FAILURE
);
978 task_release_locked(task
);
981 return (KERN_SUCCESS
);
987 thread_act_array_t
*threads_out
,
988 mach_msg_type_number_t
*count
)
990 mach_msg_type_number_t actual
;
991 thread_t
*thread_list
;
993 vm_size_t size
, size_needed
;
997 if (task
== TASK_NULL
)
998 return (KERN_INVALID_ARGUMENT
);
1000 size
= 0; addr
= NULL
;
1004 if (!task
->active
) {
1010 return (KERN_FAILURE
);
1013 actual
= task
->thread_count
;
1015 /* do we have the memory we need? */
1016 size_needed
= actual
* sizeof (mach_port_t
);
1017 if (size_needed
<= size
)
1020 /* unlock the task and allocate more memory */
1026 assert(size_needed
> 0);
1029 addr
= kalloc(size
);
1031 return (KERN_RESOURCE_SHORTAGE
);
1034 /* OK, have memory and the task is locked & active */
1035 thread_list
= (thread_t
*)addr
;
1039 for (thread
= (thread_t
)queue_first(&task
->threads
); i
< actual
;
1040 ++i
, thread
= (thread_t
)queue_next(&thread
->task_threads
)) {
1041 thread_reference_internal(thread
);
1042 thread_list
[j
++] = thread
;
1045 assert(queue_end(&task
->threads
, (queue_entry_t
)thread
));
1048 size_needed
= actual
* sizeof (mach_port_t
);
1050 /* can unlock task now that we've got the thread refs */
1054 /* no threads, so return null pointer and deallocate memory */
1056 *threads_out
= NULL
;
1063 /* if we allocated too much, must copy */
1065 if (size_needed
< size
) {
1068 newaddr
= kalloc(size_needed
);
1070 for (i
= 0; i
< actual
; ++i
)
1071 thread_deallocate(thread_list
[i
]);
1073 return (KERN_RESOURCE_SHORTAGE
);
1076 bcopy(addr
, newaddr
, size_needed
);
1078 thread_list
= (thread_t
*)newaddr
;
1081 *threads_out
= thread_list
;
1084 /* do the conversion that Mig should handle */
1086 for (i
= 0; i
< actual
; ++i
)
1087 ((ipc_port_t
*) thread_list
)[i
] = convert_thread_to_port(thread_list
[i
]);
1090 return (KERN_SUCCESS
);
1096 * Implement a user-level suspension on a task.
1099 * The caller holds a reference to the task
1103 register task_t task
)
1105 if (task
== TASK_NULL
|| task
== kernel_task
)
1106 return (KERN_INVALID_ARGUMENT
);
1110 if (!task
->active
) {
1113 return (KERN_FAILURE
);
1116 if (task
->user_stop_count
++ > 0) {
1118 * If the stop count was positive, the task is
1119 * already stopped and we can exit.
1123 return (KERN_SUCCESS
);
1127 * Put a kernel-level hold on the threads in the task (all
1128 * user-level task suspensions added together represent a
1129 * single kernel-level hold). We then wait for the threads
1130 * to stop executing user code.
1132 task_hold_locked(task
);
1133 task_wait_locked(task
);
1137 return (KERN_SUCCESS
);
1142 * Release a kernel hold on a task.
1145 * The caller holds a reference to the task
1149 register task_t task
)
1151 register boolean_t release
= FALSE
;
1153 if (task
== TASK_NULL
|| task
== kernel_task
)
1154 return (KERN_INVALID_ARGUMENT
);
1158 if (!task
->active
) {
1161 return (KERN_FAILURE
);
1164 if (task
->user_stop_count
> 0) {
1165 if (--task
->user_stop_count
== 0)
1171 return (KERN_FAILURE
);
1175 * Release the task if necessary.
1178 task_release_locked(task
);
1182 return (KERN_SUCCESS
);
1186 host_security_set_task_token(
1187 host_security_t host_security
,
1189 security_token_t sec_token
,
1190 audit_token_t audit_token
,
1191 host_priv_t host_priv
)
1193 ipc_port_t host_port
;
1196 if (task
== TASK_NULL
)
1197 return(KERN_INVALID_ARGUMENT
);
1199 if (host_security
== HOST_NULL
)
1200 return(KERN_INVALID_SECURITY
);
1203 task
->sec_token
= sec_token
;
1204 task
->audit_token
= audit_token
;
1207 if (host_priv
!= HOST_PRIV_NULL
) {
1208 kr
= host_get_host_priv_port(host_priv
, &host_port
);
1210 kr
= host_get_host_port(host_priv_self(), &host_port
);
1212 assert(kr
== KERN_SUCCESS
);
1213 kr
= task_set_special_port(task
, TASK_HOST_PORT
, host_port
);
1218 * Utility routine to set a ledger
1226 if (task
== TASK_NULL
)
1227 return(KERN_INVALID_ARGUMENT
);
1231 ipc_port_release_send(task
->wired_ledger_port
);
1232 task
->wired_ledger_port
= ledger_copy(wired
);
1235 ipc_port_release_send(task
->paged_ledger_port
);
1236 task
->paged_ledger_port
= ledger_copy(paged
);
1240 return(KERN_SUCCESS
);
1244 * This routine was added, pretty much exclusively, for registering the
1245 * RPC glue vector for in-kernel short circuited tasks. Rather than
1246 * removing it completely, I have only disabled that feature (which was
1247 * the only feature at the time). It just appears that we are going to
1248 * want to add some user data to tasks in the future (i.e. bsd info,
1249 * task names, etc...), so I left it in the formal task interface.
1254 task_flavor_t flavor
,
1255 __unused task_info_t task_info_in
, /* pointer to IN array */
1256 __unused mach_msg_type_number_t task_info_count
)
1258 if (task
== TASK_NULL
)
1259 return(KERN_INVALID_ARGUMENT
);
1263 return (KERN_INVALID_ARGUMENT
);
1265 return (KERN_SUCCESS
);
1271 task_flavor_t flavor
,
1272 task_info_t task_info_out
,
1273 mach_msg_type_number_t
*task_info_count
)
1275 kern_return_t error
= KERN_SUCCESS
;
1277 if (task
== TASK_NULL
)
1278 return (KERN_INVALID_ARGUMENT
);
1282 if ((task
!= current_task()) && (!task
->active
)) {
1284 return (KERN_INVALID_ARGUMENT
);
1289 case TASK_BASIC_INFO_32
:
1290 case TASK_BASIC2_INFO_32
:
1292 task_basic_info_32_t basic_info
;
1297 if (*task_info_count
< TASK_BASIC_INFO_32_COUNT
) {
1298 error
= KERN_INVALID_ARGUMENT
;
1302 basic_info
= (task_basic_info_32_t
)task_info_out
;
1304 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1305 basic_info
->virtual_size
= (typeof(basic_info
->virtual_size
))map
->size
;
1306 if (flavor
== TASK_BASIC2_INFO_32
) {
1308 * The "BASIC2" flavor gets the maximum resident
1309 * size instead of the current resident size...
1311 basic_info
->resident_size
= pmap_resident_max(map
->pmap
);
1313 basic_info
->resident_size
= pmap_resident_count(map
->pmap
);
1315 basic_info
->resident_size
*= PAGE_SIZE
;
1317 basic_info
->policy
= ((task
!= kernel_task
)?
1318 POLICY_TIMESHARE
: POLICY_RR
);
1319 basic_info
->suspend_count
= task
->user_stop_count
;
1321 absolutetime_to_microtime(task
->total_user_time
, &secs
, &usecs
);
1322 basic_info
->user_time
.seconds
=
1323 (typeof(basic_info
->user_time
.seconds
))secs
;
1324 basic_info
->user_time
.microseconds
= usecs
;
1326 absolutetime_to_microtime(task
->total_system_time
, &secs
, &usecs
);
1327 basic_info
->system_time
.seconds
=
1328 (typeof(basic_info
->system_time
.seconds
))secs
;
1329 basic_info
->system_time
.microseconds
= usecs
;
1331 *task_info_count
= TASK_BASIC_INFO_32_COUNT
;
1335 case TASK_BASIC_INFO_64
:
1337 task_basic_info_64_t basic_info
;
1342 if (*task_info_count
< TASK_BASIC_INFO_64_COUNT
) {
1343 error
= KERN_INVALID_ARGUMENT
;
1347 basic_info
= (task_basic_info_64_t
)task_info_out
;
1349 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1350 basic_info
->virtual_size
= map
->size
;
1351 basic_info
->resident_size
=
1352 (mach_vm_size_t
)(pmap_resident_count(map
->pmap
))
1355 basic_info
->policy
= ((task
!= kernel_task
)?
1356 POLICY_TIMESHARE
: POLICY_RR
);
1357 basic_info
->suspend_count
= task
->user_stop_count
;
1359 absolutetime_to_microtime(task
->total_user_time
, &secs
, &usecs
);
1360 basic_info
->user_time
.seconds
=
1361 (typeof(basic_info
->user_time
.seconds
))secs
;
1362 basic_info
->user_time
.microseconds
= usecs
;
1364 absolutetime_to_microtime(task
->total_system_time
, &secs
, &usecs
);
1365 basic_info
->system_time
.seconds
=
1366 (typeof(basic_info
->system_time
.seconds
))secs
;
1367 basic_info
->system_time
.microseconds
= usecs
;
1369 *task_info_count
= TASK_BASIC_INFO_64_COUNT
;
1373 case TASK_THREAD_TIMES_INFO
:
1375 register task_thread_times_info_t times_info
;
1376 register thread_t thread
;
1378 if (*task_info_count
< TASK_THREAD_TIMES_INFO_COUNT
) {
1379 error
= KERN_INVALID_ARGUMENT
;
1383 times_info
= (task_thread_times_info_t
) task_info_out
;
1384 times_info
->user_time
.seconds
= 0;
1385 times_info
->user_time
.microseconds
= 0;
1386 times_info
->system_time
.seconds
= 0;
1387 times_info
->system_time
.microseconds
= 0;
1390 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1391 time_value_t user_time
, system_time
;
1393 thread_read_times(thread
, &user_time
, &system_time
);
1395 time_value_add(×_info
->user_time
, &user_time
);
1396 time_value_add(×_info
->system_time
, &system_time
);
1400 *task_info_count
= TASK_THREAD_TIMES_INFO_COUNT
;
1404 case TASK_ABSOLUTETIME_INFO
:
1406 task_absolutetime_info_t info
;
1407 register thread_t thread
;
1409 if (*task_info_count
< TASK_ABSOLUTETIME_INFO_COUNT
) {
1410 error
= KERN_INVALID_ARGUMENT
;
1414 info
= (task_absolutetime_info_t
)task_info_out
;
1415 info
->threads_user
= info
->threads_system
= 0;
1418 info
->total_user
= task
->total_user_time
;
1419 info
->total_system
= task
->total_system_time
;
1421 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1424 tval
= timer_grab(&thread
->user_timer
);
1425 info
->threads_user
+= tval
;
1426 info
->total_user
+= tval
;
1428 tval
= timer_grab(&thread
->system_timer
);
1429 info
->threads_system
+= tval
;
1430 info
->total_system
+= tval
;
1434 *task_info_count
= TASK_ABSOLUTETIME_INFO_COUNT
;
1438 case TASK_DYLD_INFO
:
1440 task_dyld_info_t info
;
1442 if (*task_info_count
< TASK_DYLD_INFO_COUNT
) {
1443 error
= KERN_INVALID_ARGUMENT
;
1446 info
= (task_dyld_info_t
)task_info_out
;
1447 info
->all_image_info_addr
= task
->all_image_info_addr
;
1448 info
->all_image_info_size
= task
->all_image_info_size
;
1449 *task_info_count
= TASK_DYLD_INFO_COUNT
;
1454 case TASK_SCHED_FIFO_INFO
:
1457 if (*task_info_count
< POLICY_FIFO_BASE_COUNT
) {
1458 error
= KERN_INVALID_ARGUMENT
;
1462 error
= KERN_INVALID_POLICY
;
1466 case TASK_SCHED_RR_INFO
:
1468 register policy_rr_base_t rr_base
;
1470 if (*task_info_count
< POLICY_RR_BASE_COUNT
) {
1471 error
= KERN_INVALID_ARGUMENT
;
1475 rr_base
= (policy_rr_base_t
) task_info_out
;
1477 if (task
!= kernel_task
) {
1478 error
= KERN_INVALID_POLICY
;
1482 rr_base
->base_priority
= task
->priority
;
1484 rr_base
->quantum
= std_quantum_us
/ 1000;
1486 *task_info_count
= POLICY_RR_BASE_COUNT
;
1491 case TASK_SCHED_TIMESHARE_INFO
:
1493 register policy_timeshare_base_t ts_base
;
1495 if (*task_info_count
< POLICY_TIMESHARE_BASE_COUNT
) {
1496 error
= KERN_INVALID_ARGUMENT
;
1500 ts_base
= (policy_timeshare_base_t
) task_info_out
;
1502 if (task
== kernel_task
) {
1503 error
= KERN_INVALID_POLICY
;
1507 ts_base
->base_priority
= task
->priority
;
1509 *task_info_count
= POLICY_TIMESHARE_BASE_COUNT
;
1513 case TASK_SECURITY_TOKEN
:
1515 register security_token_t
*sec_token_p
;
1517 if (*task_info_count
< TASK_SECURITY_TOKEN_COUNT
) {
1518 error
= KERN_INVALID_ARGUMENT
;
1522 sec_token_p
= (security_token_t
*) task_info_out
;
1524 *sec_token_p
= task
->sec_token
;
1526 *task_info_count
= TASK_SECURITY_TOKEN_COUNT
;
1530 case TASK_AUDIT_TOKEN
:
1532 register audit_token_t
*audit_token_p
;
1534 if (*task_info_count
< TASK_AUDIT_TOKEN_COUNT
) {
1535 error
= KERN_INVALID_ARGUMENT
;
1539 audit_token_p
= (audit_token_t
*) task_info_out
;
1541 *audit_token_p
= task
->audit_token
;
1543 *task_info_count
= TASK_AUDIT_TOKEN_COUNT
;
1547 case TASK_SCHED_INFO
:
1548 error
= KERN_INVALID_ARGUMENT
;
1550 case TASK_EVENTS_INFO
:
1552 register task_events_info_t events_info
;
1553 register thread_t thread
;
1555 if (*task_info_count
< TASK_EVENTS_INFO_COUNT
) {
1556 error
= KERN_INVALID_ARGUMENT
;
1560 events_info
= (task_events_info_t
) task_info_out
;
1563 events_info
->faults
= task
->faults
;
1564 events_info
->pageins
= task
->pageins
;
1565 events_info
->cow_faults
= task
->cow_faults
;
1566 events_info
->messages_sent
= task
->messages_sent
;
1567 events_info
->messages_received
= task
->messages_received
;
1568 events_info
->syscalls_mach
= task
->syscalls_mach
;
1569 events_info
->syscalls_unix
= task
->syscalls_unix
;
1571 events_info
->csw
= task
->c_switch
;
1573 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1574 events_info
->csw
+= thread
->c_switch
;
1578 *task_info_count
= TASK_EVENTS_INFO_COUNT
;
1581 case TASK_AFFINITY_TAG_INFO
:
1583 if (*task_info_count
< TASK_AFFINITY_TAG_INFO_COUNT
) {
1584 error
= KERN_INVALID_ARGUMENT
;
1588 error
= task_affinity_info(task
, task_info_out
, task_info_count
);
1592 error
= KERN_INVALID_ARGUMENT
;
1606 /* assert(task == current_task()); */ /* bogus assert 4803227 4807483 */
1610 task
->vtimers
|= which
;
1614 case TASK_VTIMER_USER
:
1615 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1616 thread
->vtimer_user_save
= timer_grab(&thread
->user_timer
);
1620 case TASK_VTIMER_PROF
:
1621 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1622 thread
->vtimer_prof_save
= timer_grab(&thread
->user_timer
);
1623 thread
->vtimer_prof_save
+= timer_grab(&thread
->system_timer
);
1627 case TASK_VTIMER_RLIM
:
1628 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1629 thread
->vtimer_rlim_save
= timer_grab(&thread
->user_timer
);
1630 thread
->vtimer_rlim_save
+= timer_grab(&thread
->system_timer
);
1643 assert(task
== current_task());
1647 task
->vtimers
&= ~which
;
1657 uint32_t *microsecs
)
1659 thread_t thread
= current_thread();
1664 assert(task
== current_task());
1666 assert(task
->vtimers
& which
);
1672 case TASK_VTIMER_USER
:
1673 tdelt
= (uint32_t)timer_delta(&thread
->user_timer
,
1674 &thread
->vtimer_user_save
);
1675 absolutetime_to_microtime(tdelt
, &secs
, microsecs
);
1678 case TASK_VTIMER_PROF
:
1679 tsum
= timer_grab(&thread
->user_timer
);
1680 tsum
+= timer_grab(&thread
->system_timer
);
1681 tdelt
= (uint32_t)(tsum
- thread
->vtimer_prof_save
);
1682 absolutetime_to_microtime(tdelt
, &secs
, microsecs
);
1683 /* if the time delta is smaller than a usec, ignore */
1684 if (*microsecs
!= 0)
1685 thread
->vtimer_prof_save
= tsum
;
1688 case TASK_VTIMER_RLIM
:
1689 tsum
= timer_grab(&thread
->user_timer
);
1690 tsum
+= timer_grab(&thread
->system_timer
);
1691 tdelt
= (uint32_t)(tsum
- thread
->vtimer_rlim_save
);
1692 thread
->vtimer_rlim_save
= tsum
;
1693 absolutetime_to_microtime(tdelt
, &secs
, microsecs
);
1702 * Change the assigned processor set for the task
1706 __unused task_t task
,
1707 __unused processor_set_t new_pset
,
1708 __unused boolean_t assign_threads
)
1710 return(KERN_FAILURE
);
1714 * task_assign_default:
1716 * Version of task_assign to assign to default processor set.
1719 task_assign_default(
1721 boolean_t assign_threads
)
1723 return (task_assign(task
, &pset0
, assign_threads
));
1727 * task_get_assignment
1729 * Return name of processor set that task is assigned to.
1732 task_get_assignment(
1734 processor_set_t
*pset
)
1737 return(KERN_FAILURE
);
1741 return (KERN_SUCCESS
);
1748 * Set scheduling policy and parameters, both base and limit, for
1749 * the given task. Policy must be a policy which is enabled for the
1750 * processor set. Change contained threads if requested.
1754 __unused task_t task
,
1755 __unused policy_t policy_id
,
1756 __unused policy_base_t base
,
1757 __unused mach_msg_type_number_t count
,
1758 __unused boolean_t set_limit
,
1759 __unused boolean_t change
)
1761 return(KERN_FAILURE
);
1767 * Set scheduling policy and parameters, both base and limit, for
1768 * the given task. Policy can be any policy implemented by the
1769 * processor set, whether enabled or not. Change contained threads
1774 __unused task_t task
,
1775 __unused processor_set_t pset
,
1776 __unused policy_t policy_id
,
1777 __unused policy_base_t base
,
1778 __unused mach_msg_type_number_t base_count
,
1779 __unused policy_limit_t limit
,
1780 __unused mach_msg_type_number_t limit_count
,
1781 __unused boolean_t change
)
1783 return(KERN_FAILURE
);
1793 extern int fast_tas_debug
;
1795 if (fast_tas_debug
) {
1796 printf("task 0x%x: setting fast_tas to [0x%x, 0x%x]\n",
1800 task
->fast_tas_base
= pc
;
1801 task
->fast_tas_end
= endpc
;
1803 return KERN_SUCCESS
;
1805 #else /* FAST_TAS */
1808 __unused task_t task
,
1809 __unused vm_offset_t pc
,
1810 __unused vm_offset_t endpc
)
1812 return KERN_FAILURE
;
1814 #endif /* FAST_TAS */
1817 task_synchronizer_destroy_all(task_t task
)
1819 semaphore_t semaphore
;
1820 lock_set_t lock_set
;
1823 * Destroy owned semaphores
1826 while (!queue_empty(&task
->semaphore_list
)) {
1827 semaphore
= (semaphore_t
) queue_first(&task
->semaphore_list
);
1828 (void) semaphore_destroy(task
, semaphore
);
1832 * Destroy owned lock sets
1835 while (!queue_empty(&task
->lock_set_list
)) {
1836 lock_set
= (lock_set_t
) queue_first(&task
->lock_set_list
);
1837 (void) lock_set_destroy(task
, lock_set
);
1842 * Install default (machine-dependent) initial thread state
1843 * on the task. Subsequent thread creation will have this initial
1844 * state set on the thread by machine_thread_inherit_taskwide().
1845 * Flavors and structures are exactly the same as those to thread_set_state()
1851 thread_state_t state
,
1852 mach_msg_type_number_t state_count
)
1856 if (task
== TASK_NULL
) {
1857 return (KERN_INVALID_ARGUMENT
);
1862 if (!task
->active
) {
1864 return (KERN_FAILURE
);
1867 ret
= machine_task_set_state(task
, flavor
, state
, state_count
);
1874 * Examine the default (machine-dependent) initial thread state
1875 * on the task, as set by task_set_state(). Flavors and structures
1876 * are exactly the same as those passed to thread_get_state().
1882 thread_state_t state
,
1883 mach_msg_type_number_t
*state_count
)
1887 if (task
== TASK_NULL
) {
1888 return (KERN_INVALID_ARGUMENT
);
1893 if (!task
->active
) {
1895 return (KERN_FAILURE
);
1898 ret
= machine_task_get_state(task
, flavor
, state
, state_count
);
1906 * We need to export some functions to other components that
1907 * are currently implemented in macros within the osfmk
1908 * component. Just export them as functions of the same name.
1910 boolean_t
is_kerneltask(task_t t
)
1912 if (t
== kernel_task
)
1919 check_for_tasksuspend(task_t task
)
1922 if (task
== TASK_NULL
)
1925 return (task
->suspend_count
> 0);
1929 task_t
current_task(void);
1930 task_t
current_task(void)
1932 return (current_task_fast());
1935 #undef task_reference
1936 void task_reference(task_t task
);
1941 if (task
!= TASK_NULL
)
1942 task_reference_internal(task
);
1945 #if CONFIG_MACF_MACH
1947 * Protect 2 task labels against modification by adding a reference on
1948 * both label handles. The locks do not actually have to be held while
1949 * using the labels as only labels with one reference can be modified
1958 labelh_reference(a
->label
);
1959 labelh_reference(b
->label
);
1967 labelh_release(a
->label
);
1968 labelh_release(b
->label
);
1972 mac_task_label_update_internal(
1977 tasklabel_lock(task
);
1978 task
->label
= labelh_modify(task
->label
);
1979 mac_task_label_update(pl
, &task
->maclabel
);
1980 tasklabel_unlock(task
);
1981 ip_lock(task
->itk_self
);
1982 mac_port_label_update_cred(pl
, &task
->itk_self
->ip_label
);
1983 ip_unlock(task
->itk_self
);
1987 mac_task_label_modify(
1990 void (*f
) (struct label
*l
, void *arg
))
1993 tasklabel_lock(task
);
1994 task
->label
= labelh_modify(task
->label
);
1995 (*f
)(&task
->maclabel
, arg
);
1996 tasklabel_unlock(task
);
2000 mac_task_get_label(struct task
*task
)
2002 return (&task
->maclabel
);