2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * @OSF_FREE_COPYRIGHT@
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
36 * All Rights Reserved.
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young, David Golub,
63 * Task management primitives implementation.
66 * Copyright (c) 1993 The University of Utah and
67 * the Computer Systems Laboratory (CSL). All rights reserved.
69 * Permission to use, copy, modify and distribute this software and its
70 * documentation is hereby granted, provided that both the copyright
71 * notice and this permission notice appear in all copies of the
72 * software, derivative works or modified versions, and any portions
73 * thereof, and that both notices appear in supporting documentation.
75 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
76 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
77 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
79 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
80 * improvements that they make and grant CSL redistribution rights.
85 #include <mach_host.h>
86 #include <mach_prof.h>
88 #include <platforms.h>
90 #include <mach/mach_types.h>
91 #include <mach/boolean.h>
92 #include <mach/host_priv.h>
93 #include <mach/machine/vm_types.h>
94 #include <mach/vm_param.h>
95 #include <mach/semaphore.h>
96 #include <mach/task_info.h>
97 #include <mach/task_special_ports.h>
99 #include <ipc/ipc_types.h>
100 #include <ipc/ipc_space.h>
101 #include <ipc/ipc_entry.h>
103 #include <kern/kern_types.h>
104 #include <kern/mach_param.h>
105 #include <kern/misc_protos.h>
106 #include <kern/task.h>
107 #include <kern/thread.h>
108 #include <kern/zalloc.h>
109 #include <kern/kalloc.h>
110 #include <kern/processor.h>
111 #include <kern/sched_prim.h> /* for thread_wakeup */
112 #include <kern/ipc_tt.h>
113 #include <kern/ledger.h>
114 #include <kern/host.h>
115 #include <kern/clock.h>
116 #include <kern/timer.h>
117 #include <kern/profile.h>
118 #include <kern/assert.h>
119 #include <kern/sync_lock.h>
122 #include <vm/vm_map.h>
123 #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */
124 #include <vm/vm_pageout.h>
125 #include <vm/vm_protos.h> /* for vm_map_remove_commpage */
128 #include <ddb/db_sym.h>
129 #endif /* MACH_KDB */
132 #include <ppc/exception.h>
133 #include <ppc/hw_perfmon.h>
137 * Exported interfaces
140 #include <mach/task_server.h>
141 #include <mach/mach_host_server.h>
142 #include <mach/host_security_server.h>
143 #include <mach/mach_port_server.h>
145 #include <vm/task_working_set.h>
146 #include <vm/vm_shared_memory_server.h>
153 void task_hold_locked(
155 void task_wait_locked(
157 void task_release_locked(
161 void task_synchronizer_destroy_all(
164 kern_return_t
task_set_ledger(
170 task_backing_store_privileged(
174 task
->priv_flags
|= VM_BACKING_STORE_PRIV
;
180 task_working_set_disable(task_t task
)
185 ws
= task
->dynamic_working_set
;
186 task
->dynamic_working_set
= NULL
;
189 tws_hash_ws_flush(ws
);
190 tws_hash_destroy(ws
);
202 if (task_has_64BitAddr(task
))
205 /* LP64todo - no task working set for 64-bit */
206 task_set_64BitAddr(task
);
207 task_working_set_disable(task
);
209 if ( !task_has_64BitAddr(task
))
213 * Deallocate all memory previously allocated
214 * above the 32-bit address space, since it won't
215 * be accessible anymore.
217 /* LP64todo - make this clean */
218 vm_map_remove_commpage(task
->map
);
219 pmap_unmap_sharedpage(task
->map
->pmap
); /* Unmap commpage */
220 (void) vm_map_remove(task
->map
,
221 (vm_map_offset_t
) VM_MAX_ADDRESS
,
224 task_clear_64BitAddr(task
);
226 /* FIXME: On x86, the thread save state flavor can diverge from the
227 * task's 64-bit feature flag due to the 32-bit/64-bit register save
228 * state dichotomy. Since we can be pre-empted in this interval,
229 * certain routines may observe the thread as being in an inconsistent
230 * state with respect to its task's 64-bitness.
233 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
234 machine_thread_switch_addrmode(thread
, !is64bit
);
244 TASK_MAX
* sizeof(struct task
),
245 TASK_CHUNK
* sizeof(struct task
),
249 * Create the kernel task as the first task.
251 if (task_create_internal(TASK_NULL
, FALSE
, FALSE
, &kernel_task
) != KERN_SUCCESS
)
252 panic("task_init\n");
254 vm_map_deallocate(kernel_task
->map
);
255 kernel_task
->map
= kernel_map
;
267 * If may_assign is false, task is already being assigned,
268 * wait for that to finish.
270 while (task
->may_assign
== FALSE
) {
273 task
->assign_active
= TRUE
;
274 res
= thread_sleep_mutex((event_t
) &task
->assign_active
,
275 &task
->lock
, THREAD_UNINT
);
276 assert(res
== THREAD_AWAKENED
);
278 task
->may_assign
= FALSE
;
283 #define thread_freeze(thread) assert(task->processor_set == &default_pset)
292 assert(task
->may_assign
== FALSE
);
293 task
->may_assign
= TRUE
;
294 if (task
->assign_active
== TRUE
) {
295 task
->assign_active
= FALSE
;
296 thread_wakeup((event_t
)&task
->assign_active
);
302 #define thread_unfreeze(thread) assert(task->processor_set == &default_pset)
305 #endif /* MACH_HOST */
308 * Create a task running in the kernel address space. It may
309 * have its own map of size mem_size and may have ipc privileges.
313 __unused task_t parent_task
,
314 __unused vm_offset_t map_base
,
315 __unused vm_size_t map_size
,
316 __unused task_t
*child_task
)
318 return (KERN_INVALID_ARGUMENT
);
324 __unused ledger_port_array_t ledger_ports
,
325 __unused mach_msg_type_number_t num_ledger_ports
,
326 boolean_t inherit_memory
,
327 task_t
*child_task
) /* OUT */
329 if (parent_task
== TASK_NULL
)
330 return(KERN_INVALID_ARGUMENT
);
332 return task_create_internal(
333 parent_task
, inherit_memory
, task_has_64BitAddr(parent_task
), child_task
);
337 host_security_create_task_token(
338 host_security_t host_security
,
340 security_token_t sec_token
,
341 audit_token_t audit_token
,
342 host_priv_t host_priv
,
343 __unused ledger_port_array_t ledger_ports
,
344 __unused mach_msg_type_number_t num_ledger_ports
,
345 boolean_t inherit_memory
,
346 task_t
*child_task
) /* OUT */
348 kern_return_t result
;
350 if (parent_task
== TASK_NULL
)
351 return(KERN_INVALID_ARGUMENT
);
353 if (host_security
== HOST_NULL
)
354 return(KERN_INVALID_SECURITY
);
356 result
= task_create_internal(
357 parent_task
, inherit_memory
, task_has_64BitAddr(parent_task
), child_task
);
359 if (result
!= KERN_SUCCESS
)
362 result
= host_security_set_task_token(host_security
,
368 if (result
!= KERN_SUCCESS
)
375 task_create_internal(
377 boolean_t inherit_memory
,
379 task_t
*child_task
) /* OUT */
382 processor_set_t pset
;
384 new_task
= (task_t
) zalloc(task_zone
);
386 if (new_task
== TASK_NULL
)
387 return(KERN_RESOURCE_SHORTAGE
);
389 /* one ref for just being alive; one for our caller */
390 new_task
->ref_count
= 2;
393 new_task
->map
= vm_map_fork(parent_task
->map
);
395 new_task
->map
= vm_map_create(pmap_create(0, is_64bit
),
396 (vm_map_offset_t
)(VM_MIN_ADDRESS
),
397 (vm_map_offset_t
)(VM_MAX_ADDRESS
), TRUE
);
399 mutex_init(&new_task
->lock
, 0);
400 queue_init(&new_task
->threads
);
401 new_task
->suspend_count
= 0;
402 new_task
->thread_count
= 0;
403 new_task
->active_thread_count
= 0;
404 new_task
->user_stop_count
= 0;
405 new_task
->role
= TASK_UNSPECIFIED
;
406 new_task
->active
= TRUE
;
407 new_task
->user_data
= 0;
408 new_task
->faults
= 0;
409 new_task
->cow_faults
= 0;
410 new_task
->pageins
= 0;
411 new_task
->messages_sent
= 0;
412 new_task
->messages_received
= 0;
413 new_task
->syscalls_mach
= 0;
414 new_task
->priv_flags
= 0;
415 new_task
->syscalls_unix
=0;
417 new_task
->taskFeatures
[0] = 0; /* Init task features */
418 new_task
->taskFeatures
[1] = 0; /* Init task features */
419 new_task
->dynamic_working_set
= 0;
421 task_working_set_create(new_task
, TWS_SMALL_HASH_LINE_COUNT
,
422 0, TWS_HASH_STYLE_DEFAULT
);
425 new_task
->bsd_info
= 0;
426 #endif /* MACH_BSD */
429 new_task
->i386_ldt
= 0;
433 if(BootProcInfo
.pf
.Available
& pf64Bit
) new_task
->taskFeatures
[0] |= tf64BitData
; /* If 64-bit machine, show we have 64-bit registers at least */
436 queue_init(&new_task
->semaphore_list
);
437 queue_init(&new_task
->lock_set_list
);
438 new_task
->semaphores_owned
= 0;
439 new_task
->lock_sets_owned
= 0;
442 new_task
->may_assign
= TRUE
;
443 new_task
->assign_active
= FALSE
;
444 #endif /* MACH_HOST */
446 ipc_task_init(new_task
, parent_task
);
448 new_task
->total_user_time
= 0;
449 new_task
->total_system_time
= 0;
451 task_prof_init(new_task
);
453 if (parent_task
!= TASK_NULL
) {
456 * Freeze the parent, so that parent_task->processor_set
459 task_freeze(parent_task
);
460 #endif /* MACH_HOST */
461 pset
= parent_task
->processor_set
;
463 pset
= &default_pset
;
465 new_task
->sec_token
= parent_task
->sec_token
;
466 new_task
->audit_token
= parent_task
->audit_token
;
468 shared_region_mapping_ref(parent_task
->system_shared_region
);
469 new_task
->system_shared_region
= parent_task
->system_shared_region
;
471 new_task
->wired_ledger_port
= ledger_copy(
472 convert_port_to_ledger(parent_task
->wired_ledger_port
));
473 new_task
->paged_ledger_port
= ledger_copy(
474 convert_port_to_ledger(parent_task
->paged_ledger_port
));
475 if(task_has_64BitAddr(parent_task
))
476 task_set_64BitAddr(new_task
);
479 if (inherit_memory
&& parent_task
->i386_ldt
)
480 new_task
->i386_ldt
= user_ldt_copy(parent_task
->i386_ldt
);
484 pset
= &default_pset
;
486 new_task
->sec_token
= KERNEL_SECURITY_TOKEN
;
487 new_task
->audit_token
= KERNEL_AUDIT_TOKEN
;
488 new_task
->wired_ledger_port
= ledger_copy(root_wired_ledger
);
489 new_task
->paged_ledger_port
= ledger_copy(root_paged_ledger
);
492 if (kernel_task
== TASK_NULL
) {
493 new_task
->priority
= BASEPRI_KERNEL
;
494 new_task
->max_priority
= MAXPRI_KERNEL
;
497 new_task
->priority
= BASEPRI_DEFAULT
;
498 new_task
->max_priority
= MAXPRI_USER
;
502 pset_add_task(pset
, new_task
);
505 if (parent_task
!= TASK_NULL
)
506 task_unfreeze(parent_task
);
507 #endif /* MACH_HOST */
509 if (vm_backing_store_low
&& parent_task
!= NULL
)
510 new_task
->priv_flags
|= (parent_task
->priv_flags
&VM_BACKING_STORE_PRIV
);
512 ipc_task_enable(new_task
);
514 *child_task
= new_task
;
515 return(KERN_SUCCESS
);
521 * Drop a reference on a task.
527 processor_set_t pset
;
529 if (task
== TASK_NULL
)
532 if (task_deallocate_internal(task
) > 0)
535 pset
= task
->processor_set
;
536 pset_deallocate(pset
);
538 if(task
->dynamic_working_set
)
539 tws_hash_destroy(task
->dynamic_working_set
);
541 ipc_task_terminate(task
);
543 vm_map_deallocate(task
->map
);
544 is_release(task
->itk_space
);
546 task_prof_deallocate(task
);
547 zfree(task_zone
, task
);
551 * task_name_deallocate:
553 * Drop a reference on a task name.
556 task_name_deallocate(
557 task_name_t task_name
)
559 return(task_deallocate((task_t
)task_name
));
566 * Terminate the specified task. See comments on thread_terminate
567 * (kern/thread.c) about problems with terminating the "current task."
574 if (task
== TASK_NULL
)
575 return (KERN_INVALID_ARGUMENT
);
578 return (KERN_FAILURE
);
580 return (task_terminate_internal(task
));
584 task_terminate_internal(
587 processor_set_t pset
;
588 thread_t thread
, self
;
590 boolean_t interrupt_save
;
592 assert(task
!= kernel_task
);
594 self
= current_thread();
595 self_task
= self
->task
;
598 * Get the task locked and make sure that we are not racing
599 * with someone else trying to terminate us.
601 if (task
== self_task
)
604 if (task
< self_task
) {
606 task_lock(self_task
);
609 task_lock(self_task
);
613 if (!task
->active
|| !self
->active
) {
615 * Task or current act is already being terminated.
616 * Just return an error. If we are dying, this will
617 * just get us to our AST special handler and that
618 * will get us to finalize the termination of ourselves.
621 if (self_task
!= task
)
622 task_unlock(self_task
);
624 return (KERN_FAILURE
);
627 if (self_task
!= task
)
628 task_unlock(self_task
);
631 * Make sure the current thread does not get aborted out of
632 * the waits inside these operations.
634 interrupt_save
= thread_interrupt_level(THREAD_UNINT
);
637 * Indicate that we want all the threads to stop executing
638 * at user space by holding the task (we would have held
639 * each thread independently in thread_terminate_internal -
640 * but this way we may be more likely to already find it
641 * held there). Mark the task inactive, and prevent
642 * further task operations via the task port.
644 task_hold_locked(task
);
645 task
->active
= FALSE
;
646 ipc_task_disable(task
);
649 * Terminate each thread in the task.
651 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
652 thread_terminate_internal(thread
);
656 * Give the machine dependent code a chance
657 * to perform cleanup before ripping apart
660 if (self_task
== task
)
661 machine_thread_terminate_self();
666 * Destroy all synchronizers owned by the task.
668 task_synchronizer_destroy_all(task
);
671 * Destroy the IPC space, leaving just a reference for it.
673 ipc_space_destroy(task
->itk_space
);
675 /* LP64todo - make this clean */
676 vm_map_remove_commpage(task
->map
);
677 pmap_unmap_sharedpage(task
->map
->pmap
); /* Unmap commpage */
679 if (vm_map_has_4GB_pagezero(task
->map
))
680 vm_map_clear_4GB_pagezero(task
->map
);
683 * If the current thread is a member of the task
684 * being terminated, then the last reference to
685 * the task will not be dropped until the thread
686 * is finally reaped. To avoid incurring the
687 * expense of removing the address space regions
688 * at reap time, we do it explictly here.
690 vm_map_remove(task
->map
, task
->map
->min_offset
,
691 task
->map
->max_offset
, VM_MAP_NO_FLAGS
);
693 shared_region_mapping_dealloc(task
->system_shared_region
);
696 * Flush working set here to avoid I/O in reaper thread
698 if (task
->dynamic_working_set
)
699 tws_hash_ws_flush(task
->dynamic_working_set
);
701 pset
= task
->processor_set
;
703 pset_remove_task(pset
,task
);
707 * We no longer need to guard against being aborted, so restore
708 * the previous interruptible state.
710 thread_interrupt_level(interrupt_save
);
713 perfmon_release_facility(task
); // notify the perfmon facility
717 * Get rid of the task active reference on itself.
719 task_deallocate(task
);
721 return (KERN_SUCCESS
);
727 * Shut the current task down (except for the current thread) in
728 * preparation for dramatic changes to the task (probably exec).
729 * We hold the task, terminate all other threads in the task and
730 * wait for them to terminate, clean up the portspace, and when
731 * all done, let the current thread go.
737 thread_t thread
, self
;
739 assert(task
!= kernel_task
);
741 self
= current_thread();
743 if (task
!= self
->task
)
744 return (KERN_INVALID_ARGUMENT
);
748 if (!task
->active
|| !self
->active
) {
750 * Task or current thread is already being terminated.
751 * Hurry up and return out of the current kernel context
752 * so that we run our AST special handler to terminate
757 return (KERN_FAILURE
);
760 if (task
->thread_count
> 1) {
762 * Mark all the threads to keep them from starting any more
763 * user-level execution. The thread_terminate_internal code
764 * would do this on a thread by thread basis anyway, but this
765 * gives us a better chance of not having to wait there.
767 task_hold_locked(task
);
770 * Terminate all the other threads in the task.
772 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
774 thread_terminate_internal(thread
);
777 task_release_locked(task
);
781 * Give the machine dependent code a chance
782 * to perform cleanup before ripping apart
785 machine_thread_terminate_self();
790 * Destroy all synchronizers owned by the task.
792 task_synchronizer_destroy_all(task
);
795 * Destroy the contents of the IPC space, leaving just
796 * a reference for it.
798 ipc_space_clean(task
->itk_space
);
801 * Clean out the address space, as we are going to be
804 vm_map_remove(task
->map
, task
->map
->min_offset
,
805 task
->map
->max_offset
, VM_MAP_NO_FLAGS
);
807 return (KERN_SUCCESS
);
813 * Suspend execution of the specified task.
814 * This is a recursive-style suspension of the task, a count of
815 * suspends is maintained.
817 * CONDITIONS: the task is locked and active.
821 register task_t task
)
823 register thread_t thread
;
825 assert(task
->active
);
827 if (task
->suspend_count
++ > 0)
831 * Iterate through all the threads and hold them.
833 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
834 thread_mtx_lock(thread
);
836 thread_mtx_unlock(thread
);
843 * Same as the internal routine above, except that is must lock
844 * and verify that the task is active. This differs from task_suspend
845 * in that it places a kernel hold on the task rather than just a
846 * user-level hold. This keeps users from over resuming and setting
847 * it running out from under the kernel.
849 * CONDITIONS: the caller holds a reference on the task
853 register task_t task
)
855 if (task
== TASK_NULL
)
856 return (KERN_INVALID_ARGUMENT
);
863 return (KERN_FAILURE
);
866 task_hold_locked(task
);
869 return (KERN_SUCCESS
);
875 * Wait for all threads in task to stop.
878 * Called with task locked, active, and held.
882 register task_t task
)
884 register thread_t thread
, self
;
886 assert(task
->active
);
887 assert(task
->suspend_count
> 0);
889 self
= current_thread();
892 * Iterate through all the threads and wait for them to
893 * stop. Do not wait for the current thread if it is within
896 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
903 * task_release_locked:
905 * Release a kernel hold on a task.
907 * CONDITIONS: the task is locked and active
911 register task_t task
)
913 register thread_t thread
;
915 assert(task
->active
);
916 assert(task
->suspend_count
> 0);
918 if (--task
->suspend_count
> 0)
921 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
922 thread_mtx_lock(thread
);
923 thread_release(thread
);
924 thread_mtx_unlock(thread
);
931 * Same as the internal routine above, except that it must lock
932 * and verify that the task is active.
934 * CONDITIONS: The caller holds a reference to the task
940 if (task
== TASK_NULL
)
941 return (KERN_INVALID_ARGUMENT
);
948 return (KERN_FAILURE
);
951 task_release_locked(task
);
954 return (KERN_SUCCESS
);
960 thread_act_array_t
*threads_out
,
961 mach_msg_type_number_t
*count
)
963 mach_msg_type_number_t actual
;
966 vm_size_t size
, size_needed
;
970 if (task
== TASK_NULL
)
971 return (KERN_INVALID_ARGUMENT
);
983 return (KERN_FAILURE
);
986 actual
= task
->thread_count
;
988 /* do we have the memory we need? */
989 size_needed
= actual
* sizeof (mach_port_t
);
990 if (size_needed
<= size
)
993 /* unlock the task and allocate more memory */
999 assert(size_needed
> 0);
1002 addr
= kalloc(size
);
1004 return (KERN_RESOURCE_SHORTAGE
);
1007 /* OK, have memory and the task is locked & active */
1008 threads
= (thread_t
*)addr
;
1012 for (thread
= (thread_t
)queue_first(&task
->threads
); i
< actual
;
1013 ++i
, thread
= (thread_t
)queue_next(&thread
->task_threads
)) {
1014 thread_reference_internal(thread
);
1015 threads
[j
++] = thread
;
1018 assert(queue_end(&task
->threads
, (queue_entry_t
)thread
));
1021 size_needed
= actual
* sizeof (mach_port_t
);
1023 /* can unlock task now that we've got the thread refs */
1027 /* no threads, so return null pointer and deallocate memory */
1036 /* if we allocated too much, must copy */
1038 if (size_needed
< size
) {
1041 newaddr
= kalloc(size_needed
);
1043 for (i
= 0; i
< actual
; ++i
)
1044 thread_deallocate(threads
[i
]);
1046 return (KERN_RESOURCE_SHORTAGE
);
1049 bcopy(addr
, newaddr
, size_needed
);
1051 threads
= (thread_t
*)newaddr
;
1054 *threads_out
= threads
;
1057 /* do the conversion that Mig should handle */
1059 for (i
= 0; i
< actual
; ++i
)
1060 ((ipc_port_t
*) threads
)[i
] = convert_thread_to_port(threads
[i
]);
1063 return (KERN_SUCCESS
);
1069 * Implement a user-level suspension on a task.
1072 * The caller holds a reference to the task
1076 register task_t task
)
1078 if (task
== TASK_NULL
|| task
== kernel_task
)
1079 return (KERN_INVALID_ARGUMENT
);
1083 if (!task
->active
) {
1086 return (KERN_FAILURE
);
1089 if (task
->user_stop_count
++ > 0) {
1091 * If the stop count was positive, the task is
1092 * already stopped and we can exit.
1096 return (KERN_SUCCESS
);
1100 * Put a kernel-level hold on the threads in the task (all
1101 * user-level task suspensions added together represent a
1102 * single kernel-level hold). We then wait for the threads
1103 * to stop executing user code.
1105 task_hold_locked(task
);
1106 task_wait_locked(task
);
1110 return (KERN_SUCCESS
);
1115 * Release a kernel hold on a task.
1118 * The caller holds a reference to the task
1122 register task_t task
)
1124 register boolean_t release
= FALSE
;
1126 if (task
== TASK_NULL
|| task
== kernel_task
)
1127 return (KERN_INVALID_ARGUMENT
);
1131 if (!task
->active
) {
1134 return (KERN_FAILURE
);
1137 if (task
->user_stop_count
> 0) {
1138 if (--task
->user_stop_count
== 0)
1144 return (KERN_FAILURE
);
1148 * Release the task if necessary.
1151 task_release_locked(task
);
1155 return (KERN_SUCCESS
);
1159 host_security_set_task_token(
1160 host_security_t host_security
,
1162 security_token_t sec_token
,
1163 audit_token_t audit_token
,
1164 host_priv_t host_priv
)
1166 ipc_port_t host_port
;
1169 if (task
== TASK_NULL
)
1170 return(KERN_INVALID_ARGUMENT
);
1172 if (host_security
== HOST_NULL
)
1173 return(KERN_INVALID_SECURITY
);
1176 task
->sec_token
= sec_token
;
1177 task
->audit_token
= audit_token
;
1180 if (host_priv
!= HOST_PRIV_NULL
) {
1181 kr
= host_get_host_priv_port(host_priv
, &host_port
);
1183 kr
= host_get_host_port(host_priv_self(), &host_port
);
1185 assert(kr
== KERN_SUCCESS
);
1186 kr
= task_set_special_port(task
, TASK_HOST_PORT
, host_port
);
1191 * Utility routine to set a ledger
1199 if (task
== TASK_NULL
)
1200 return(KERN_INVALID_ARGUMENT
);
1204 ipc_port_release_send(task
->wired_ledger_port
);
1205 task
->wired_ledger_port
= ledger_copy(wired
);
1208 ipc_port_release_send(task
->paged_ledger_port
);
1209 task
->paged_ledger_port
= ledger_copy(paged
);
1213 return(KERN_SUCCESS
);
1217 * This routine was added, pretty much exclusively, for registering the
1218 * RPC glue vector for in-kernel short circuited tasks. Rather than
1219 * removing it completely, I have only disabled that feature (which was
1220 * the only feature at the time). It just appears that we are going to
1221 * want to add some user data to tasks in the future (i.e. bsd info,
1222 * task names, etc...), so I left it in the formal task interface.
1227 task_flavor_t flavor
,
1228 __unused task_info_t task_info_in
, /* pointer to IN array */
1229 __unused mach_msg_type_number_t task_info_count
)
1231 if (task
== TASK_NULL
)
1232 return(KERN_INVALID_ARGUMENT
);
1236 return (KERN_INVALID_ARGUMENT
);
1238 return (KERN_SUCCESS
);
1244 task_flavor_t flavor
,
1245 task_info_t task_info_out
,
1246 mach_msg_type_number_t
*task_info_count
)
1248 if (task
== TASK_NULL
)
1249 return (KERN_INVALID_ARGUMENT
);
1253 case TASK_BASIC_INFO_32
:
1255 task_basic_info_32_t basic_info
;
1258 if (*task_info_count
< TASK_BASIC_INFO_32_COUNT
)
1259 return (KERN_INVALID_ARGUMENT
);
1261 basic_info
= (task_basic_info_32_t
)task_info_out
;
1263 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1264 basic_info
->virtual_size
= CAST_DOWN(vm_offset_t
,map
->size
);
1265 basic_info
->resident_size
= pmap_resident_count(map
->pmap
)
1269 basic_info
->policy
= ((task
!= kernel_task
)?
1270 POLICY_TIMESHARE
: POLICY_RR
);
1271 basic_info
->suspend_count
= task
->user_stop_count
;
1273 absolutetime_to_microtime(
1274 task
->total_user_time
,
1275 &basic_info
->user_time
.seconds
,
1276 &basic_info
->user_time
.microseconds
);
1277 absolutetime_to_microtime(
1278 task
->total_system_time
,
1279 &basic_info
->system_time
.seconds
,
1280 &basic_info
->system_time
.microseconds
);
1283 *task_info_count
= TASK_BASIC_INFO_32_COUNT
;
1287 case TASK_BASIC_INFO_64
:
1289 task_basic_info_64_t basic_info
;
1292 if (*task_info_count
< TASK_BASIC_INFO_64_COUNT
)
1293 return (KERN_INVALID_ARGUMENT
);
1295 basic_info
= (task_basic_info_64_t
)task_info_out
;
1297 map
= (task
== kernel_task
)? kernel_map
: task
->map
;
1298 basic_info
->virtual_size
= map
->size
;
1299 basic_info
->resident_size
= (mach_vm_size_t
)(pmap_resident_count(map
->pmap
)
1303 basic_info
->policy
= ((task
!= kernel_task
)?
1304 POLICY_TIMESHARE
: POLICY_RR
);
1305 basic_info
->suspend_count
= task
->user_stop_count
;
1307 absolutetime_to_microtime(
1308 task
->total_user_time
,
1309 &basic_info
->user_time
.seconds
,
1310 &basic_info
->user_time
.microseconds
);
1311 absolutetime_to_microtime(
1312 task
->total_system_time
,
1313 &basic_info
->system_time
.seconds
,
1314 &basic_info
->system_time
.microseconds
);
1317 *task_info_count
= TASK_BASIC_INFO_64_COUNT
;
1321 case TASK_THREAD_TIMES_INFO
:
1323 register task_thread_times_info_t times_info
;
1324 register thread_t thread
;
1326 if (*task_info_count
< TASK_THREAD_TIMES_INFO_COUNT
)
1327 return (KERN_INVALID_ARGUMENT
);
1329 times_info
= (task_thread_times_info_t
) task_info_out
;
1330 times_info
->user_time
.seconds
= 0;
1331 times_info
->user_time
.microseconds
= 0;
1332 times_info
->system_time
.seconds
= 0;
1333 times_info
->system_time
.microseconds
= 0;
1337 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1338 time_value_t user_time
, system_time
;
1340 thread_read_times(thread
, &user_time
, &system_time
);
1342 time_value_add(×_info
->user_time
, &user_time
);
1343 time_value_add(×_info
->system_time
, &system_time
);
1348 *task_info_count
= TASK_THREAD_TIMES_INFO_COUNT
;
1352 case TASK_ABSOLUTETIME_INFO
:
1354 task_absolutetime_info_t info
;
1355 register thread_t thread
;
1357 if (*task_info_count
< TASK_ABSOLUTETIME_INFO_COUNT
)
1358 return (KERN_INVALID_ARGUMENT
);
1360 info
= (task_absolutetime_info_t
)task_info_out
;
1361 info
->threads_user
= info
->threads_system
= 0;
1365 info
->total_user
= task
->total_user_time
;
1366 info
->total_system
= task
->total_system_time
;
1368 queue_iterate(&task
->threads
, thread
, thread_t
, task_threads
) {
1371 tval
= timer_grab(&thread
->user_timer
);
1372 info
->threads_user
+= tval
;
1373 info
->total_user
+= tval
;
1375 tval
= timer_grab(&thread
->system_timer
);
1376 info
->threads_system
+= tval
;
1377 info
->total_system
+= tval
;
1382 *task_info_count
= TASK_ABSOLUTETIME_INFO_COUNT
;
1387 case TASK_SCHED_FIFO_INFO
:
1390 if (*task_info_count
< POLICY_FIFO_BASE_COUNT
)
1391 return (KERN_INVALID_ARGUMENT
);
1393 return (KERN_INVALID_POLICY
);
1397 case TASK_SCHED_RR_INFO
:
1399 register policy_rr_base_t rr_base
;
1401 if (*task_info_count
< POLICY_RR_BASE_COUNT
)
1402 return (KERN_INVALID_ARGUMENT
);
1404 rr_base
= (policy_rr_base_t
) task_info_out
;
1407 if (task
!= kernel_task
) {
1409 return (KERN_INVALID_POLICY
);
1412 rr_base
->base_priority
= task
->priority
;
1415 rr_base
->quantum
= std_quantum_us
/ 1000;
1417 *task_info_count
= POLICY_RR_BASE_COUNT
;
1422 case TASK_SCHED_TIMESHARE_INFO
:
1424 register policy_timeshare_base_t ts_base
;
1426 if (*task_info_count
< POLICY_TIMESHARE_BASE_COUNT
)
1427 return (KERN_INVALID_ARGUMENT
);
1429 ts_base
= (policy_timeshare_base_t
) task_info_out
;
1432 if (task
== kernel_task
) {
1434 return (KERN_INVALID_POLICY
);
1437 ts_base
->base_priority
= task
->priority
;
1440 *task_info_count
= POLICY_TIMESHARE_BASE_COUNT
;
1444 case TASK_SECURITY_TOKEN
:
1446 register security_token_t
*sec_token_p
;
1448 if (*task_info_count
< TASK_SECURITY_TOKEN_COUNT
)
1449 return (KERN_INVALID_ARGUMENT
);
1451 sec_token_p
= (security_token_t
*) task_info_out
;
1454 *sec_token_p
= task
->sec_token
;
1457 *task_info_count
= TASK_SECURITY_TOKEN_COUNT
;
1461 case TASK_AUDIT_TOKEN
:
1463 register audit_token_t
*audit_token_p
;
1465 if (*task_info_count
< TASK_AUDIT_TOKEN_COUNT
)
1466 return (KERN_INVALID_ARGUMENT
);
1468 audit_token_p
= (audit_token_t
*) task_info_out
;
1471 *audit_token_p
= task
->audit_token
;
1474 *task_info_count
= TASK_AUDIT_TOKEN_COUNT
;
1478 case TASK_SCHED_INFO
:
1479 return (KERN_INVALID_ARGUMENT
);
1481 case TASK_EVENTS_INFO
:
1483 register task_events_info_t events_info
;
1485 if (*task_info_count
< TASK_EVENTS_INFO_COUNT
)
1486 return (KERN_INVALID_ARGUMENT
);
1488 events_info
= (task_events_info_t
) task_info_out
;
1491 events_info
->faults
= task
->faults
;
1492 events_info
->pageins
= task
->pageins
;
1493 events_info
->cow_faults
= task
->cow_faults
;
1494 events_info
->messages_sent
= task
->messages_sent
;
1495 events_info
->messages_received
= task
->messages_received
;
1496 events_info
->syscalls_mach
= task
->syscalls_mach
;
1497 events_info
->syscalls_unix
= task
->syscalls_unix
;
1498 events_info
->csw
= task
->csw
;
1501 *task_info_count
= TASK_EVENTS_INFO_COUNT
;
1506 return (KERN_INVALID_ARGUMENT
);
1509 return (KERN_SUCCESS
);
1515 * Change the assigned processor set for the task
1519 __unused task_t task
,
1520 __unused processor_set_t new_pset
,
1521 __unused boolean_t assign_threads
)
1523 return(KERN_FAILURE
);
1527 * task_assign_default:
1529 * Version of task_assign to assign to default processor set.
1532 task_assign_default(
1534 boolean_t assign_threads
)
1536 return (task_assign(task
, &default_pset
, assign_threads
));
1540 * task_get_assignment
1542 * Return name of processor set that task is assigned to.
1545 task_get_assignment(
1547 processor_set_t
*pset
)
1550 return(KERN_FAILURE
);
1552 *pset
= task
->processor_set
;
1553 pset_reference(*pset
);
1554 return(KERN_SUCCESS
);
1561 * Set scheduling policy and parameters, both base and limit, for
1562 * the given task. Policy must be a policy which is enabled for the
1563 * processor set. Change contained threads if requested.
1567 __unused task_t task
,
1568 __unused policy_t policy_id
,
1569 __unused policy_base_t base
,
1570 __unused mach_msg_type_number_t count
,
1571 __unused boolean_t set_limit
,
1572 __unused boolean_t change
)
1574 return(KERN_FAILURE
);
1580 * Set scheduling policy and parameters, both base and limit, for
1581 * the given task. Policy can be any policy implemented by the
1582 * processor set, whether enabled or not. Change contained threads
1587 __unused task_t task
,
1588 __unused processor_set_t pset
,
1589 __unused policy_t policy_id
,
1590 __unused policy_base_t base
,
1591 __unused mach_msg_type_number_t base_count
,
1592 __unused policy_limit_t limit
,
1593 __unused mach_msg_type_number_t limit_count
,
1594 __unused boolean_t change
)
1596 return(KERN_FAILURE
);
1606 extern int fast_tas_debug
;
1608 if (fast_tas_debug
) {
1609 printf("task 0x%x: setting fast_tas to [0x%x, 0x%x]\n",
1613 task
->fast_tas_base
= pc
;
1614 task
->fast_tas_end
= endpc
;
1616 return KERN_SUCCESS
;
1618 #else /* FAST_TAS */
1621 __unused task_t task
,
1622 __unused vm_offset_t pc
,
1623 __unused vm_offset_t endpc
)
1625 return KERN_FAILURE
;
1627 #endif /* FAST_TAS */
1630 task_synchronizer_destroy_all(task_t task
)
1632 semaphore_t semaphore
;
1633 lock_set_t lock_set
;
1636 * Destroy owned semaphores
1639 while (!queue_empty(&task
->semaphore_list
)) {
1640 semaphore
= (semaphore_t
) queue_first(&task
->semaphore_list
);
1641 (void) semaphore_destroy(task
, semaphore
);
1645 * Destroy owned lock sets
1648 while (!queue_empty(&task
->lock_set_list
)) {
1649 lock_set
= (lock_set_t
) queue_first(&task
->lock_set_list
);
1650 (void) lock_set_destroy(task
, lock_set
);
1655 * We need to export some functions to other components that
1656 * are currently implemented in macros within the osfmk
1657 * component. Just export them as functions of the same name.
1659 boolean_t
is_kerneltask(task_t t
)
1661 if (t
== kernel_task
)
1668 task_t
current_task(void);
1669 task_t
current_task(void)
1671 return (current_task_fast());
1674 #undef task_reference
1675 void task_reference(task_t task
);
1680 if (task
!= TASK_NULL
)
1681 task_reference_internal(task
);