2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * @OSF_FREE_COPYRIGHT@
27 * Mach Operating System
28 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
29 * All Rights Reserved.
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 * Carnegie Mellon requests users of this software to return to
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
53 * Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub,
56 * Task management primitives implementation.
59 * Copyright (c) 1993 The University of Utah and
60 * the Computer Systems Laboratory (CSL). All rights reserved.
62 * Permission to use, copy, modify and distribute this software and its
63 * documentation is hereby granted, provided that both the copyright
64 * notice and this permission notice appear in all copies of the
65 * software, derivative works or modified versions, and any portions
66 * thereof, and that both notices appear in supporting documentation.
68 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
69 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
70 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
72 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
73 * improvements that they make and grant CSL redistribution rights.
78 #include <mach_host.h>
79 #include <mach_prof.h>
81 #include <platforms.h>
83 #include <mach/mach_types.h>
84 #include <mach/boolean.h>
85 #include <mach/host_priv.h>
86 #include <mach/machine/vm_types.h>
87 #include <mach/vm_param.h>
88 #include <mach/semaphore.h>
89 #include <mach/task_info.h>
90 #include <mach/task_special_ports.h>
92 #include <ipc/ipc_types.h>
93 #include <ipc/ipc_space.h>
94 #include <ipc/ipc_entry.h>
96 #include <kern/kern_types.h>
97 #include <kern/mach_param.h>
98 #include <kern/misc_protos.h>
99 #include <kern/task.h>
100 #include <kern/thread.h>
101 #include <kern/zalloc.h>
102 #include <kern/kalloc.h>
103 #include <kern/processor.h>
104 #include <kern/sched_prim.h> /* for thread_wakeup */
105 #include <kern/ipc_tt.h>
106 #include <kern/ledger.h>
107 #include <kern/host.h>
108 #include <kern/clock.h>
109 #include <kern/timer.h>
110 #include <kern/profile.h>
111 #include <kern/assert.h>
112 #include <kern/sync_lock.h>
115 #include <vm/vm_map.h>
116 #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */
117 #include <vm/vm_pageout.h>
118 #include <vm/vm_protos.h> /* for vm_map_remove_commpage64 */
121 #include <ddb/db_sym.h>
122 #endif /* MACH_KDB */
125 #include <ppc/exception.h>
126 #include <ppc/hw_perfmon.h>
130 * Exported interfaces
133 #include <mach/task_server.h>
134 #include <mach/mach_host_server.h>
135 #include <mach/host_security_server.h>
136 #include <mach/mach_port_server.h>
138 #include <vm/task_working_set.h>
139 #include <vm/vm_shared_memory_server.h>
146 void task_hold_locked(
148 void task_wait_locked(
150 void task_release_locked(
154 void task_synchronizer_destroy_all(
157 kern_return_t
task_set_ledger(
163 task_backing_store_privileged(
167 task
->priv_flags
|= VM_BACKING_STORE_PRIV
;
173 task_working_set_disable(task_t task
)
178 ws
= task
->dynamic_working_set
;
179 task
->dynamic_working_set
= NULL
;
182 tws_hash_ws_flush(ws
);
183 tws_hash_destroy(ws
);
193 /* LP64todo - no task working set for 64-bit */
194 task_set_64BitAddr(task
);
195 task_working_set_disable(task
);
196 task
->map
->max_offset
= MACH_VM_MAX_ADDRESS
;
199 * Deallocate all memory previously allocated
200 * above the 32-bit address space, since it won't
201 * be accessible anymore.
203 /* LP64todo - make this clean */
205 vm_map_remove_commpage64(task
->map
);
206 pmap_unmap_sharedpage(task
->map
->pmap
); /* Unmap commpage */
208 (void) vm_map_remove(task
->map
,
209 (vm_map_offset_t
) VM_MAX_ADDRESS
,
212 task_clear_64BitAddr(task
);
213 task
->map
->max_offset
= (vm_map_offset_t
)VM_MAX_ADDRESS
;
222 TASK_MAX
* sizeof(struct task
),
223 TASK_CHUNK
* sizeof(struct task
),
227 * Create the kernel task as the first task.
229 if (task_create_internal(TASK_NULL
, FALSE
, &kernel_task
) != KERN_SUCCESS
)
230 panic("task_init\n");
232 vm_map_deallocate(kernel_task
->map
);
233 kernel_task
->map
= kernel_map
;
245 * If may_assign is false, task is already being assigned,
246 * wait for that to finish.
248 while (task
->may_assign
== FALSE
) {
251 task
->assign_active
= TRUE
;
252 res
= thread_sleep_mutex((event_t
) &task
->assign_active
,
253 &task
->lock
, THREAD_UNINT
);
254 assert(res
== THREAD_AWAKENED
);
256 task
->may_assign
= FALSE
;
261 #define thread_freeze(thread) assert(task->processor_set == &default_pset)
270 assert(task
->may_assign
== FALSE
);
271 task
->may_assign
= TRUE
;
272 if (task
->assign_active
== TRUE
) {
273 task
->assign_active
= FALSE
;
274 thread_wakeup((event_t
)&task
->assign_active
);
280 #define thread_unfreeze(thread) assert(task->processor_set == &default_pset)
283 #endif /* MACH_HOST */
286 * Create a task running in the kernel address space. It may
287 * have its own map of size mem_size and may have ipc privileges.
291 __unused task_t parent_task
,
292 __unused vm_offset_t map_base
,
293 __unused vm_size_t map_size
,
294 __unused task_t
*child_task
)
296 return (KERN_INVALID_ARGUMENT
);
302 __unused ledger_port_array_t ledger_ports
,
303 __unused mach_msg_type_number_t num_ledger_ports
,
304 boolean_t inherit_memory
,
305 task_t
*child_task
) /* OUT */
307 if (parent_task
== TASK_NULL
)
308 return(KERN_INVALID_ARGUMENT
);
310 return task_create_internal(
311 parent_task
, inherit_memory
, child_task
);
315 host_security_create_task_token(
316 host_security_t host_security
,
318 security_token_t sec_token
,
319 audit_token_t audit_token
,
320 host_priv_t host_priv
,
321 __unused ledger_port_array_t ledger_ports
,
322 __unused mach_msg_type_number_t num_ledger_ports
,
323 boolean_t inherit_memory
,
324 task_t
*child_task
) /* OUT */
326 kern_return_t result
;
328 if (parent_task
== TASK_NULL
)
329 return(KERN_INVALID_ARGUMENT
);
331 if (host_security
== HOST_NULL
)
332 return(KERN_INVALID_SECURITY
);
334 result
= task_create_internal(
335 parent_task
, inherit_memory
, child_task
);
337 if (result
!= KERN_SUCCESS
)
340 result
= host_security_set_task_token(host_security
,
346 if (result
!= KERN_SUCCESS
)
353 task_create_internal(
355 boolean_t inherit_memory
,
356 task_t
*child_task
) /* OUT */
359 processor_set_t pset
;
361 new_task
= (task_t
) zalloc(task_zone
);
363 if (new_task
== TASK_NULL
)
364 return(KERN_RESOURCE_SHORTAGE
);
366 /* one ref for just being alive; one for our caller */
367 new_task
->ref_count
= 2;
370 new_task
->map
= vm_map_fork(parent_task
->map
);
372 new_task
->map
= vm_map_create(pmap_create(0),
373 (vm_map_offset_t
)(VM_MIN_ADDRESS
),
374 (vm_map_offset_t
)(VM_MAX_ADDRESS
), TRUE
);
376 mutex_init(&new_task
->lock
, 0);
377 queue_init(&new_task
->threads
);
378 new_task
->suspend_count
= 0;
379 new_task
->thread_count
= 0;
380 new_task
->active_thread_count
= 0;
381 new_task
->user_stop_count
= 0;
382 new_task
->role
= TASK_UNSPECIFIED
;
383 new_task
->active
= TRUE
;
384 new_task
->user_data
= 0;
385 new_task
->faults
= 0;
386 new_task
->cow_faults
= 0;
387 new_task
->pageins
= 0;
388 new_task
->messages_sent
= 0;
389 new_task
->messages_received
= 0;
390 new_task
->syscalls_mach
= 0;
391 new_task
->priv_flags
= 0;
392 new_task
->syscalls_unix
=0;
394 new_task
->taskFeatures
[0] = 0; /* Init task features */
395 new_task
->taskFeatures
[1] = 0; /* Init task features */
396 new_task
->dynamic_working_set
= 0;
398 task_working_set_create(new_task
, TWS_SMALL_HASH_LINE_COUNT
,
399 0, TWS_HASH_STYLE_DEFAULT
);
402 new_task
->bsd_info
= 0;
403 #endif /* MACH_BSD */
406 if(BootProcInfo
.pf
.Available
& pf64Bit
) new_task
->taskFeatures
[0] |= tf64BitData
; /* If 64-bit machine, show we have 64-bit registers at least */
409 queue_init(&new_task
->semaphore_list
);
410 queue_init(&new_task
->lock_set_list
);
411 new_task
->semaphores_owned
= 0;
412 new_task
->lock_sets_owned
= 0;
415 new_task
->may_assign
= TRUE
;
416 new_task
->assign_active
= FALSE
;
417 #endif /* MACH_HOST */
419 ipc_task_init(new_task
, parent_task
);
421 new_task
->total_user_time
= 0;
422 new_task
->total_system_time
= 0;
424 task_prof_init(new_task
);
426 if (parent_task
!= TASK_NULL
) {
429 * Freeze the parent, so that parent_task->processor_set
432 task_freeze(parent_task
);
433 #endif /* MACH_HOST */
434 pset
= parent_task
->processor_set
;
436 pset
= &default_pset
;
438 new_task
->sec_token
= parent_task
->sec_token
;
439 new_task
->audit_token
= parent_task
->audit_token
;
441 shared_region_mapping_ref(parent_task
->system_shared_region
);
442 new_task
->system_shared_region
= parent_task
->system_shared_region
;
444 new_task
->wired_ledger_port
= ledger_copy(
445 convert_port_to_ledger(parent_task
->wired_ledger_port
));
446 new_task
->paged_ledger_port
= ledger_copy(
447 convert_port_to_ledger(parent_task
->paged_ledger_port
));
448 if(task_has_64BitAddr(parent_task
))
449 task_set_64BitAddr(new_task
);
452 pset
= &default_pset
;
454 new_task
->sec_token
= KERNEL_SECURITY_TOKEN
;
455 new_task
->audit_token
= KERNEL_AUDIT_TOKEN
;
456 new_task
->wired_ledger_port
= ledger_copy(root_wired_ledger
);
457 new_task
->paged_ledger_port
= ledger_copy(root_paged_ledger
);
460 if (kernel_task
== TASK_NULL
) {
461 new_task
->priority
= BASEPRI_KERNEL
;
462 new_task
->max_priority
= MAXPRI_KERNEL
;
465 new_task
->priority
= BASEPRI_DEFAULT
;
466 new_task
->max_priority
= MAXPRI_USER
;
470 pset_add_task(pset
, new_task
);
473 if (parent_task
!= TASK_NULL
)
474 task_unfreeze(parent_task
);
475 #endif /* MACH_HOST */
477 if (vm_backing_store_low
&& parent_task
!= NULL
)
478 new_task
->priv_flags
|= (parent_task
->priv_flags
&VM_BACKING_STORE_PRIV
);
480 ipc_task_enable(new_task
);
482 *child_task
= new_task
;
483 return(KERN_SUCCESS
);
489 * Drop a reference on a task.
495 processor_set_t pset
;
497 if (task
== TASK_NULL
)
500 if (task_deallocate_internal(task
) > 0)
503 pset
= task
->processor_set
;
504 pset_deallocate(pset
);
506 if(task
->dynamic_working_set
)
507 tws_hash_destroy(task
->dynamic_working_set
);
509 ipc_task_terminate(task
);
511 vm_map_deallocate(task
->map
);
512 is_release(task
->itk_space
);
514 task_prof_deallocate(task
);
515 zfree(task_zone
, task
);
521 * Terminate the specified task. See comments on thread_terminate
522 * (kern/thread.c) about problems with terminating the "current task."
529 if (task
== TASK_NULL
)
530 return (KERN_INVALID_ARGUMENT
);
533 return (KERN_FAILURE
);
535 return (task_terminate_internal(task
));
539 task_terminate_internal(
542 processor_set_t pset
;
543 thread_t thread
, self
;
545 boolean_t interrupt_save
;
547 assert(task
!= kernel_task
);
549 self
= current_thread();
550 self_task
= self
->task
;
553 * Get the task locked and make sure that we are not racing
554 * with someone else trying to terminate us.
556 if (task
== self_task
)
559 if (task
< self_task
) {
561 task_lock(self_task
);
564 task_lock(self_task
);
568 if (!task
->active
|| !self
->active
) {
570 * Task or current act is already being terminated.
571 * Just return an error. If we are dying, this will
572 * just get us to our AST special handler and that
573 * will get us to finalize the termination of ourselves.
576 if (self_task
!= task
)
577 task_unlock(self_task
);
579 return (KERN_FAILURE
);
582 if (self_task
!= task
)
583 task_unlock(self_task
);
586 * Make sure the current thread does not get aborted out of
587 * the waits inside these operations.
589 interrupt_save
= thread_interrupt_level(THREAD_UNINT
);
592 * Indicate that we want all the threads to stop executing
593 * at user space by holding the task (we would have held
594 * each thread independently in thread_terminate_internal -
595 * but this way we may be more likely to already find it
596 * held there). Mark the task inactive, and prevent
597 * further task operations via the task port.
599 task_hold_locked(task
);
600 task
->active
= FALSE
;
601 ipc_task_disable(task
);
604 * Terminate each thread in the task.
606 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
607 thread_terminate_internal(thread
);
611 * Give the machine dependent code a chance
612 * to perform cleanup before ripping apart
615 if (self_task
== task
)
616 machine_thread_terminate_self();
621 * Destroy all synchronizers owned by the task.
623 task_synchronizer_destroy_all(task
);
626 * Destroy the IPC space, leaving just a reference for it.
628 ipc_space_destroy(task
->itk_space
);
630 /* LP64todo - make this clean */
632 vm_map_remove_commpage64(task
->map
);
633 pmap_unmap_sharedpage(task
->map
->pmap
); /* Unmap commpage */
637 * If the current thread is a member of the task
638 * being terminated, then the last reference to
639 * the task will not be dropped until the thread
640 * is finally reaped. To avoid incurring the
641 * expense of removing the address space regions
642 * at reap time, we do it explictly here.
644 vm_map_remove(task
->map
, task
->map
->min_offset
,
645 task
->map
->max_offset
, VM_MAP_NO_FLAGS
);
647 shared_region_mapping_dealloc(task
->system_shared_region
);
650 * Flush working set here to avoid I/O in reaper thread
652 if (task
->dynamic_working_set
)
653 tws_hash_ws_flush(task
->dynamic_working_set
);
655 pset
= task
->processor_set
;
657 pset_remove_task(pset
,task
);
661 * We no longer need to guard against being aborted, so restore
662 * the previous interruptible state.
664 thread_interrupt_level(interrupt_save
);
667 perfmon_release_facility(task
); // notify the perfmon facility
671 * Get rid of the task active reference on itself.
673 task_deallocate(task
);
675 return (KERN_SUCCESS
);
681 * Shut the current task down (except for the current thread) in
682 * preparation for dramatic changes to the task (probably exec).
683 * We hold the task, terminate all other threads in the task and
684 * wait for them to terminate, clean up the portspace, and when
685 * all done, let the current thread go.
691 thread_t thread
, self
;
693 assert(task
!= kernel_task
);
695 self
= current_thread();
697 if (task
!= self
->task
)
698 return (KERN_INVALID_ARGUMENT
);
702 if (!task
->active
|| !self
->active
) {
704 * Task or current thread is already being terminated.
705 * Hurry up and return out of the current kernel context
706 * so that we run our AST special handler to terminate
711 return (KERN_FAILURE
);
714 if (task
->thread_count
> 1) {
716 * Mark all the threads to keep them from starting any more
717 * user-level execution. The thread_terminate_internal code
718 * would do this on a thread by thread basis anyway, but this
719 * gives us a better chance of not having to wait there.
721 task_hold_locked(task
);
724 * Terminate all the other threads in the task.
726 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
728 thread_terminate_internal(thread
);
731 task_release_locked(task
);
735 * Give the machine dependent code a chance
736 * to perform cleanup before ripping apart
739 machine_thread_terminate_self();
744 * Destroy all synchronizers owned by the task.
746 task_synchronizer_destroy_all(task
);
749 * Destroy the contents of the IPC space, leaving just
750 * a reference for it.
752 ipc_space_clean(task
->itk_space
);
755 * Clean out the address space, as we are going to be
758 vm_map_remove(task
->map
, task
->map
->min_offset
,
759 task
->map
->max_offset
, VM_MAP_NO_FLAGS
);
761 return (KERN_SUCCESS
);
767 * Suspend execution of the specified task.
768 * This is a recursive-style suspension of the task, a count of
769 * suspends is maintained.
771 * CONDITIONS: the task is locked and active.
775 register task_t task
)
777 register thread_t thread
;
779 assert(task
->active
);
781 if (task
->suspend_count
++ > 0)
785 * Iterate through all the threads and hold them.
787 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
788 thread_mtx_lock(thread
);
790 thread_mtx_unlock(thread
);
797 * Same as the internal routine above, except that is must lock
798 * and verify that the task is active. This differs from task_suspend
799 * in that it places a kernel hold on the task rather than just a
800 * user-level hold. This keeps users from over resuming and setting
801 * it running out from under the kernel.
803 * CONDITIONS: the caller holds a reference on the task
807 register task_t task
)
809 if (task
== TASK_NULL
)
810 return (KERN_INVALID_ARGUMENT
);
817 return (KERN_FAILURE
);
820 task_hold_locked(task
);
823 return (KERN_SUCCESS
);
829 * Wait for all threads in task to stop.
832 * Called with task locked, active, and held.
836 register task_t task
)
838 register thread_t thread
, self
;
840 assert(task
->active
);
841 assert(task
->suspend_count
> 0);
843 self
= current_thread();
846 * Iterate through all the threads and wait for them to
847 * stop. Do not wait for the current thread if it is within
850 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
857 * task_release_locked:
859 * Release a kernel hold on a task.
861 * CONDITIONS: the task is locked and active
865 register task_t task
)
867 register thread_t thread
;
869 assert(task
->active
);
870 assert(task
->suspend_count
> 0);
872 if (--task
->suspend_count
> 0)
875 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
876 thread_mtx_lock(thread
);
877 thread_release(thread
);
878 thread_mtx_unlock(thread
);
885 * Same as the internal routine above, except that it must lock
886 * and verify that the task is active.
888 * CONDITIONS: The caller holds a reference to the task
894 if (task
== TASK_NULL
)
895 return (KERN_INVALID_ARGUMENT
);
902 return (KERN_FAILURE
);
905 task_release_locked(task
);
908 return (KERN_SUCCESS
);
914 thread_act_array_t
*threads_out
,
915 mach_msg_type_number_t
*count
)
917 mach_msg_type_number_t actual
;
920 vm_size_t size
, size_needed
;
924 if (task
== TASK_NULL
)
925 return (KERN_INVALID_ARGUMENT
);
937 return (KERN_FAILURE
);
940 actual
= task
->thread_count
;
942 /* do we have the memory we need? */
943 size_needed
= actual
* sizeof (mach_port_t
);
944 if (size_needed
<= size
)
947 /* unlock the task and allocate more memory */
953 assert(size_needed
> 0);
958 return (KERN_RESOURCE_SHORTAGE
);
961 /* OK, have memory and the task is locked & active */
962 threads
= (thread_t
*)addr
;
966 for (thread
= (thread_t
)queue_first(&task
->threads
); i
< actual
;
967 ++i
, thread
= (thread_t
)queue_next(&thread
->task_threads
)) {
968 thread_reference_internal(thread
);
969 threads
[j
++] = thread
;
972 assert(queue_end(&task
->threads
, (queue_entry_t
)thread
));
975 size_needed
= actual
* sizeof (mach_port_t
);
977 /* can unlock task now that we've got the thread refs */
981 /* no threads, so return null pointer and deallocate memory */
990 /* if we allocated too much, must copy */
992 if (size_needed
< size
) {
995 newaddr
= kalloc(size_needed
);
997 for (i
= 0; i
< actual
; ++i
)
998 thread_deallocate(threads
[i
]);
1000 return (KERN_RESOURCE_SHORTAGE
);
1003 bcopy(addr
, newaddr
, size_needed
);
1005 threads
= (thread_t
*)newaddr
;
1008 *threads_out
= threads
;
1011 /* do the conversion that Mig should handle */
1013 for (i
= 0; i
< actual
; ++i
)
1014 ((ipc_port_t
*) threads
)[i
] = convert_thread_to_port(threads
[i
]);
1017 return (KERN_SUCCESS
);
1023 * Implement a user-level suspension on a task.
1026 * The caller holds a reference to the task
1030 register task_t task
)
1032 if (task
== TASK_NULL
|| task
== kernel_task
)
1033 return (KERN_INVALID_ARGUMENT
);
1037 if (!task
->active
) {
1040 return (KERN_FAILURE
);
1043 if (task
->user_stop_count
++ > 0) {
1045 * If the stop count was positive, the task is
1046 * already stopped and we can exit.
1050 return (KERN_SUCCESS
);
1054 * Put a kernel-level hold on the threads in the task (all
1055 * user-level task suspensions added together represent a
1056 * single kernel-level hold). We then wait for the threads
1057 * to stop executing user code.
1059 task_hold_locked(task
);
1060 task_wait_locked(task
);
1064 return (KERN_SUCCESS
);
1069 * Release a kernel hold on a task.
1072 * The caller holds a reference to the task
1076 register task_t task
)
1078 register boolean_t release
= FALSE
;
1080 if (task
== TASK_NULL
|| task
== kernel_task
)
1081 return (KERN_INVALID_ARGUMENT
);
1085 if (!task
->active
) {
1088 return (KERN_FAILURE
);
1091 if (task
->user_stop_count
> 0) {
1092 if (--task
->user_stop_count
== 0)
1098 return (KERN_FAILURE
);
1102 * Release the task if necessary.
1105 task_release_locked(task
);
1109 return (KERN_SUCCESS
);
1113 host_security_set_task_token(
1114 host_security_t host_security
,
1116 security_token_t sec_token
,
1117 audit_token_t audit_token
,
1118 host_priv_t host_priv
)
1120 ipc_port_t host_port
;
1123 if (task
== TASK_NULL
)
1124 return(KERN_INVALID_ARGUMENT
);
1126 if (host_security
== HOST_NULL
)
1127 return(KERN_INVALID_SECURITY
);
1130 task
->sec_token
= sec_token
;
1131 task
->audit_token
= audit_token
;
1134 if (host_priv
!= HOST_PRIV_NULL
) {
1135 kr
= host_get_host_priv_port(host_priv
, &host_port
);
1137 kr
= host_get_host_port(host_priv_self(), &host_port
);
1139 assert(kr
== KERN_SUCCESS
);
1140 kr
= task_set_special_port(task
, TASK_HOST_PORT
, host_port
);
1145 * Utility routine to set a ledger
1153 if (task
== TASK_NULL
)
1154 return(KERN_INVALID_ARGUMENT
);
1158 ipc_port_release_send(task
->wired_ledger_port
);
1159 task
->wired_ledger_port
= ledger_copy(wired
);
1162 ipc_port_release_send(task
->paged_ledger_port
);
1163 task
->paged_ledger_port
= ledger_copy(paged
);
1167 return(KERN_SUCCESS
);
1171 * This routine was added, pretty much exclusively, for registering the
1172 * RPC glue vector for in-kernel short circuited tasks. Rather than
1173 * removing it completely, I have only disabled that feature (which was
1174 * the only feature at the time). It just appears that we are going to
1175 * want to add some user data to tasks in the future (i.e. bsd info,
1176 * task names, etc...), so I left it in the formal task interface.
1181 task_flavor_t flavor
,
1182 __unused task_info_t task_info_in
, /* pointer to IN array */
1183 __unused mach_msg_type_number_t task_info_count
)
1185 if (task
== TASK_NULL
)
1186 return(KERN_INVALID_ARGUMENT
);
1190 return (KERN_INVALID_ARGUMENT
);
1192 return (KERN_SUCCESS
);
1198 task_flavor_t flavor
,
1199 task_info_t task_info_out
,
1200 mach_msg_type_number_t
*task_info_count
)
1202 if (task
== TASK_NULL
)
1203 return (KERN_INVALID_ARGUMENT
);
1207 case TASK_BASIC_INFO_32
:
1209 task_basic_info_32_t basic_info
;
1212 if (*task_info_count
< TASK_BASIC_INFO_32_COUNT
)
1213 return (KERN_INVALID_ARGUMENT
);
1215 basic_info
= (task_basic_info_32_t
)task_info_out
;
1217 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1218 basic_info
->virtual_size
= CAST_DOWN(vm_offset_t
,map
->size
);
1219 basic_info
->resident_size
= pmap_resident_count(map
->pmap
)
1223 basic_info
->policy
= ((task
!= kernel_task
)?
1224 POLICY_TIMESHARE
: POLICY_RR
);
1225 basic_info
->suspend_count
= task
->user_stop_count
;
1227 absolutetime_to_microtime(
1228 task
->total_user_time
,
1229 &basic_info
->user_time
.seconds
,
1230 &basic_info
->user_time
.microseconds
);
1231 absolutetime_to_microtime(
1232 task
->total_system_time
,
1233 &basic_info
->system_time
.seconds
,
1234 &basic_info
->system_time
.microseconds
);
1237 *task_info_count
= TASK_BASIC_INFO_32_COUNT
;
1241 case TASK_BASIC_INFO_64
:
1243 task_basic_info_64_t basic_info
;
1246 if (*task_info_count
< TASK_BASIC_INFO_64_COUNT
)
1247 return (KERN_INVALID_ARGUMENT
);
1249 basic_info
= (task_basic_info_64_t
)task_info_out
;
1251 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1252 basic_info
->virtual_size
= map
->size
;
1253 basic_info
->resident_size
= (mach_vm_size_t
)(pmap_resident_count(map
->pmap
)
1257 basic_info
->policy
= ((task
!= kernel_task
)?
1258 POLICY_TIMESHARE
: POLICY_RR
);
1259 basic_info
->suspend_count
= task
->user_stop_count
;
1261 absolutetime_to_microtime(
1262 task
->total_user_time
,
1263 &basic_info
->user_time
.seconds
,
1264 &basic_info
->user_time
.microseconds
);
1265 absolutetime_to_microtime(
1266 task
->total_system_time
,
1267 &basic_info
->system_time
.seconds
,
1268 &basic_info
->system_time
.microseconds
);
1271 *task_info_count
= TASK_BASIC_INFO_64_COUNT
;
1275 case TASK_THREAD_TIMES_INFO
:
1277 register task_thread_times_info_t times_info
;
1278 register thread_t thread
;
1280 if (*task_info_count
< TASK_THREAD_TIMES_INFO_COUNT
)
1281 return (KERN_INVALID_ARGUMENT
);
1283 times_info
= (task_thread_times_info_t
) task_info_out
;
1284 times_info
->user_time
.seconds
= 0;
1285 times_info
->user_time
.microseconds
= 0;
1286 times_info
->system_time
.seconds
= 0;
1287 times_info
->system_time
.microseconds
= 0;
1291 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1292 time_value_t user_time
, system_time
;
1294 thread_read_times(thread
, &user_time
, &system_time
);
1296 time_value_add(×_info
->user_time
, &user_time
);
1297 time_value_add(×_info
->system_time
, &system_time
);
1302 *task_info_count
= TASK_THREAD_TIMES_INFO_COUNT
;
1306 case TASK_ABSOLUTETIME_INFO
:
1308 task_absolutetime_info_t info
;
1309 register thread_t thread
;
1311 if (*task_info_count
< TASK_ABSOLUTETIME_INFO_COUNT
)
1312 return (KERN_INVALID_ARGUMENT
);
1314 info
= (task_absolutetime_info_t
)task_info_out
;
1315 info
->threads_user
= info
->threads_system
= 0;
1319 info
->total_user
= task
->total_user_time
;
1320 info
->total_system
= task
->total_system_time
;
1322 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1325 tval
= timer_grab(&thread
->user_timer
);
1326 info
->threads_user
+= tval
;
1327 info
->total_user
+= tval
;
1329 tval
= timer_grab(&thread
->system_timer
);
1330 info
->threads_system
+= tval
;
1331 info
->total_system
+= tval
;
1336 *task_info_count
= TASK_ABSOLUTETIME_INFO_COUNT
;
1341 case TASK_SCHED_FIFO_INFO
:
1344 if (*task_info_count
< POLICY_FIFO_BASE_COUNT
)
1345 return (KERN_INVALID_ARGUMENT
);
1347 return (KERN_INVALID_POLICY
);
1351 case TASK_SCHED_RR_INFO
:
1353 register policy_rr_base_t rr_base
;
1355 if (*task_info_count
< POLICY_RR_BASE_COUNT
)
1356 return (KERN_INVALID_ARGUMENT
);
1358 rr_base
= (policy_rr_base_t
) task_info_out
;
1361 if (task
!= kernel_task
) {
1363 return (KERN_INVALID_POLICY
);
1366 rr_base
->base_priority
= task
->priority
;
1369 rr_base
->quantum
= std_quantum_us
/ 1000;
1371 *task_info_count
= POLICY_RR_BASE_COUNT
;
1376 case TASK_SCHED_TIMESHARE_INFO
:
1378 register policy_timeshare_base_t ts_base
;
1380 if (*task_info_count
< POLICY_TIMESHARE_BASE_COUNT
)
1381 return (KERN_INVALID_ARGUMENT
);
1383 ts_base
= (policy_timeshare_base_t
) task_info_out
;
1386 if (task
== kernel_task
) {
1388 return (KERN_INVALID_POLICY
);
1391 ts_base
->base_priority
= task
->priority
;
1394 *task_info_count
= POLICY_TIMESHARE_BASE_COUNT
;
1398 case TASK_SECURITY_TOKEN
:
1400 register security_token_t
*sec_token_p
;
1402 if (*task_info_count
< TASK_SECURITY_TOKEN_COUNT
)
1403 return (KERN_INVALID_ARGUMENT
);
1405 sec_token_p
= (security_token_t
*) task_info_out
;
1408 *sec_token_p
= task
->sec_token
;
1411 *task_info_count
= TASK_SECURITY_TOKEN_COUNT
;
1415 case TASK_AUDIT_TOKEN
:
1417 register audit_token_t
*audit_token_p
;
1419 if (*task_info_count
< TASK_AUDIT_TOKEN_COUNT
)
1420 return (KERN_INVALID_ARGUMENT
);
1422 audit_token_p
= (audit_token_t
*) task_info_out
;
1425 *audit_token_p
= task
->audit_token
;
1428 *task_info_count
= TASK_AUDIT_TOKEN_COUNT
;
1432 case TASK_SCHED_INFO
:
1433 return (KERN_INVALID_ARGUMENT
);
1435 case TASK_EVENTS_INFO
:
1437 register task_events_info_t events_info
;
1439 if (*task_info_count
< TASK_EVENTS_INFO_COUNT
)
1440 return (KERN_INVALID_ARGUMENT
);
1442 events_info
= (task_events_info_t
) task_info_out
;
1445 events_info
->faults
= task
->faults
;
1446 events_info
->pageins
= task
->pageins
;
1447 events_info
->cow_faults
= task
->cow_faults
;
1448 events_info
->messages_sent
= task
->messages_sent
;
1449 events_info
->messages_received
= task
->messages_received
;
1450 events_info
->syscalls_mach
= task
->syscalls_mach
;
1451 events_info
->syscalls_unix
= task
->syscalls_unix
;
1452 events_info
->csw
= task
->csw
;
1455 *task_info_count
= TASK_EVENTS_INFO_COUNT
;
1460 return (KERN_INVALID_ARGUMENT
);
1463 return (KERN_SUCCESS
);
1469 * Change the assigned processor set for the task
1473 __unused task_t task
,
1474 __unused processor_set_t new_pset
,
1475 __unused boolean_t assign_threads
)
1477 return(KERN_FAILURE
);
1481 * task_assign_default:
1483 * Version of task_assign to assign to default processor set.
1486 task_assign_default(
1488 boolean_t assign_threads
)
1490 return (task_assign(task
, &default_pset
, assign_threads
));
1494 * task_get_assignment
1496 * Return name of processor set that task is assigned to.
1499 task_get_assignment(
1501 processor_set_t
*pset
)
1504 return(KERN_FAILURE
);
1506 *pset
= task
->processor_set
;
1507 pset_reference(*pset
);
1508 return(KERN_SUCCESS
);
1515 * Set scheduling policy and parameters, both base and limit, for
1516 * the given task. Policy must be a policy which is enabled for the
1517 * processor set. Change contained threads if requested.
1521 __unused task_t task
,
1522 __unused policy_t policy_id
,
1523 __unused policy_base_t base
,
1524 __unused mach_msg_type_number_t count
,
1525 __unused boolean_t set_limit
,
1526 __unused boolean_t change
)
1528 return(KERN_FAILURE
);
1534 * Set scheduling policy and parameters, both base and limit, for
1535 * the given task. Policy can be any policy implemented by the
1536 * processor set, whether enabled or not. Change contained threads
1541 __unused task_t task
,
1542 __unused processor_set_t pset
,
1543 __unused policy_t policy_id
,
1544 __unused policy_base_t base
,
1545 __unused mach_msg_type_number_t base_count
,
1546 __unused policy_limit_t limit
,
1547 __unused mach_msg_type_number_t limit_count
,
1548 __unused boolean_t change
)
1550 return(KERN_FAILURE
);
1560 extern int fast_tas_debug
;
1562 if (fast_tas_debug
) {
1563 printf("task 0x%x: setting fast_tas to [0x%x, 0x%x]\n",
1567 task
->fast_tas_base
= pc
;
1568 task
->fast_tas_end
= endpc
;
1570 return KERN_SUCCESS
;
1572 #else /* FAST_TAS */
1575 __unused task_t task
,
1576 __unused vm_offset_t pc
,
1577 __unused vm_offset_t endpc
)
1579 return KERN_FAILURE
;
1581 #endif /* FAST_TAS */
1584 task_synchronizer_destroy_all(task_t task
)
1586 semaphore_t semaphore
;
1587 lock_set_t lock_set
;
1590 * Destroy owned semaphores
1593 while (!queue_empty(&task
->semaphore_list
)) {
1594 semaphore
= (semaphore_t
) queue_first(&task
->semaphore_list
);
1595 (void) semaphore_destroy(task
, semaphore
);
1599 * Destroy owned lock sets
1602 while (!queue_empty(&task
->lock_set_list
)) {
1603 lock_set
= (lock_set_t
) queue_first(&task
->lock_set_list
);
1604 (void) lock_set_destroy(task
, lock_set
);
1609 * We need to export some functions to other components that
1610 * are currently implemented in macros within the osfmk
1611 * component. Just export them as functions of the same name.
1613 boolean_t
is_kerneltask(task_t t
)
1615 if (t
== kernel_task
)
1622 task_t
current_task(void);
1623 task_t
current_task(void)
1625 return (current_task_fast());
1628 #undef task_reference
1629 void task_reference(task_t task
);
1634 if (task
!= TASK_NULL
)
1635 task_reference_internal(task
);