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
);