1/* 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#include <mach/mach_types.h> 29#include <mach/machine/vm_param.h> 30#include <mach/task.h> 31 32#include <kern/kern_types.h> 33#include <kern/ledger.h> 34#include <kern/processor.h> 35#include <kern/thread.h> 36#include <kern/task.h> 37#include <kern/spl.h> 38#include <kern/lock.h> 39#include <kern/ast.h> 40#include <ipc/ipc_port.h> 41#include <ipc/ipc_object.h> 42#include <vm/vm_map.h> 43#include <vm/vm_kern.h> 44#include <vm/pmap.h> 45#include <vm/vm_protos.h> /* last */ 46#include <sys/resource.h> 47 48#undef thread_should_halt 49 50/* BSD KERN COMPONENT INTERFACE */ 51 52task_t bsd_init_task = TASK_NULL; 53char init_task_failure_data[1024]; 54extern unsigned int not_in_kdp; /* Skip acquiring locks if we're in kdp */ 55 56thread_t get_firstthread(task_t); 57int get_task_userstop(task_t); 58int get_thread_userstop(thread_t); 59boolean_t current_thread_aborted(void); 60void task_act_iterate_wth_args(task_t, void(*)(thread_t, void *), void *); 61kern_return_t get_signalact(task_t , thread_t *, int); 62int get_vmsubmap_entries(vm_map_t, vm_object_offset_t, vm_object_offset_t); 63void syscall_exit_funnelcheck(void); 64int fill_task_rusage_v2(task_t task, struct rusage_info_v2 *ri); 65 66 67/* 68 * 69 */ 70void *get_bsdtask_info(task_t t) 71{ 72 return(t->bsd_info); 73} 74 75/* 76 * 77 */ 78void *get_bsdthreadtask_info(thread_t th) 79{ 80 return(th->task != TASK_NULL ? th->task->bsd_info : NULL); 81} 82 83/* 84 * 85 */ 86void set_bsdtask_info(task_t t,void * v) 87{ 88 t->bsd_info=v; 89} 90 91/* 92 * 93 */ 94void *get_bsdthread_info(thread_t th) 95{ 96 return(th->uthread); 97} 98 99/* 100 * XXX 101 */ 102int get_thread_lock_count(thread_t th); /* forced forward */ 103int get_thread_lock_count(thread_t th) 104{ 105 return(th->mutex_count); 106} 107 108/* 109 * XXX: wait for BSD to fix signal code 110 * Until then, we cannot block here. We know the task 111 * can't go away, so we make sure it is still active after 112 * retrieving the first thread for extra safety. 113 */ 114thread_t get_firstthread(task_t task) 115{ 116 thread_t thread = (thread_t)(void *)queue_first(&task->threads); 117 118 if (queue_end(&task->threads, (queue_entry_t)thread)) 119 thread = THREAD_NULL; 120 121 if (!task->active) 122 return (THREAD_NULL); 123 124 return (thread); 125} 126 127kern_return_t 128get_signalact( 129 task_t task, 130 thread_t *result_out, 131 int setast) 132{ 133 kern_return_t result = KERN_SUCCESS; 134 thread_t inc, thread = THREAD_NULL; 135 136 task_lock(task); 137 138 if (!task->active) { 139 task_unlock(task); 140 141 return (KERN_FAILURE); 142 } 143 144 for (inc = (thread_t)(void *)queue_first(&task->threads); 145 !queue_end(&task->threads, (queue_entry_t)inc); ) { 146 thread_mtx_lock(inc); 147 if (inc->active && 148 (inc->sched_flags & TH_SFLAG_ABORTED_MASK) != TH_SFLAG_ABORT) { 149 thread = inc; 150 break; 151 } 152 thread_mtx_unlock(inc); 153 154 inc = (thread_t)(void *)queue_next(&inc->task_threads); 155 } 156 157 if (result_out) 158 *result_out = thread; 159 160 if (thread) { 161 if (setast) 162 act_set_astbsd(thread); 163 164 thread_mtx_unlock(thread); 165 } 166 else 167 result = KERN_FAILURE; 168 169 task_unlock(task); 170 171 return (result); 172} 173 174 175kern_return_t 176check_actforsig( 177 task_t task, 178 thread_t thread, 179 int setast) 180{ 181 kern_return_t result = KERN_FAILURE; 182 thread_t inc; 183 184 task_lock(task); 185 186 if (!task->active) { 187 task_unlock(task); 188 189 return (KERN_FAILURE); 190 } 191 192 for (inc = (thread_t)(void *)queue_first(&task->threads); 193 !queue_end(&task->threads, (queue_entry_t)inc); ) { 194 if (inc == thread) { 195 thread_mtx_lock(inc); 196 197 if (inc->active && 198 (inc->sched_flags & TH_SFLAG_ABORTED_MASK) != TH_SFLAG_ABORT) { 199 result = KERN_SUCCESS; 200 break; 201 } 202 203 thread_mtx_unlock(inc); 204 break; 205 } 206 207 inc = (thread_t)(void *)queue_next(&inc->task_threads); 208 } 209 210 if (result == KERN_SUCCESS) { 211 if (setast) 212 act_set_astbsd(thread); 213 214 thread_mtx_unlock(thread); 215 } 216 217 task_unlock(task); 218 219 return (result); 220} 221 222ledger_t get_task_ledger(task_t t) 223{ 224 return(t->ledger); 225} 226 227/* 228 * This is only safe to call from a thread executing in 229 * in the task's context or if the task is locked Otherwise, 230 * the map could be switched for the task (and freed) before 231 * we to return it here. 232 */ 233vm_map_t get_task_map(task_t t) 234{ 235 return(t->map); 236} 237 238vm_map_t get_task_map_reference(task_t t) 239{ 240 vm_map_t m; 241 242 if (t == NULL) 243 return VM_MAP_NULL; 244 245 task_lock(t); 246 if (!t->active) { 247 task_unlock(t); 248 return VM_MAP_NULL; 249 } 250 m = t->map; 251 vm_map_reference_swap(m); 252 task_unlock(t); 253 return m; 254} 255 256/* 257 * 258 */ 259ipc_space_t get_task_ipcspace(task_t t) 260{ 261 return(t->itk_space); 262} 263 264int get_task_numactivethreads(task_t task) 265{ 266 thread_t inc; 267 int num_active_thr=0; 268 task_lock(task); 269 270 for (inc = (thread_t)(void *)queue_first(&task->threads); 271 !queue_end(&task->threads, (queue_entry_t)inc); inc = (thread_t)(void *)queue_next(&inc->task_threads)) 272 { 273 if(inc->active) 274 num_active_thr++; 275 } 276 task_unlock(task); 277 return num_active_thr; 278} 279 280int get_task_numacts(task_t t) 281{ 282 return(t->thread_count); 283} 284 285/* does this machine need 64bit register set for signal handler */ 286int is_64signalregset(void) 287{ 288 if (task_has_64BitData(current_task())) { 289 return(1); 290 } 291 292 return(0); 293} 294 295/* 296 * Swap in a new map for the task/thread pair; the old map reference is 297 * returned. 298 */ 299vm_map_t 300swap_task_map(task_t task, thread_t thread, vm_map_t map, boolean_t doswitch) 301{ 302 vm_map_t old_map; 303 304 if (task != thread->task) 305 panic("swap_task_map"); 306 307 task_lock(task); 308 mp_disable_preemption(); 309 old_map = task->map; 310 thread->map = task->map = map; 311 if (doswitch) { 312 pmap_switch(map->pmap); 313 } 314 mp_enable_preemption(); 315 task_unlock(task); 316 317#if (defined(__i386__) || defined(__x86_64__)) && NCOPY_WINDOWS > 0 318 inval_copy_windows(thread); 319#endif 320 321 return old_map; 322} 323 324/* 325 * 326 */ 327pmap_t get_task_pmap(task_t t) 328{ 329 return(t->map->pmap); 330} 331 332/* 333 * 334 */ 335uint64_t get_task_resident_size(task_t task) 336{ 337 vm_map_t map; 338 339 map = (task == kernel_task) ? kernel_map: task->map; 340 return((uint64_t)pmap_resident_count(map->pmap) * PAGE_SIZE_64); 341} 342 343/* 344 * 345 */ 346uint64_t get_task_phys_footprint(task_t task) 347{ 348 kern_return_t ret; 349 ledger_amount_t credit, debit; 350 351 ret = ledger_get_entries(task->ledger, task_ledgers.phys_footprint, &credit, &debit); 352 if (KERN_SUCCESS == ret) { 353 return (credit - debit); 354 } 355 356 return 0; 357} 358 359/* 360 * 361 */ 362uint64_t get_task_phys_footprint_max(task_t task) 363{ 364 kern_return_t ret; 365 ledger_amount_t max; 366 367 ret = ledger_get_maximum(task->ledger, task_ledgers.phys_footprint, &max); 368 if (KERN_SUCCESS == ret) { 369 return max; 370 } 371 372 return 0; 373} 374 375/* 376 * 377 */ 378pmap_t get_map_pmap(vm_map_t map) 379{ 380 return(map->pmap); 381} 382/* 383 * 384 */ 385task_t get_threadtask(thread_t th) 386{ 387 return(th->task); 388} 389 390/* 391 * 392 */ 393vm_map_offset_t 394get_map_min( 395 vm_map_t map) 396{ 397 return(vm_map_min(map)); 398} 399 400/* 401 * 402 */ 403vm_map_offset_t 404get_map_max( 405 vm_map_t map) 406{ 407 return(vm_map_max(map)); 408} 409vm_map_size_t 410get_vmmap_size( 411 vm_map_t map) 412{ 413 return(map->size); 414} 415 416int 417get_vmsubmap_entries( 418 vm_map_t map, 419 vm_object_offset_t start, 420 vm_object_offset_t end) 421{ 422 int total_entries = 0; 423 vm_map_entry_t entry; 424 425 if (not_in_kdp) 426 vm_map_lock(map); 427 entry = vm_map_first_entry(map); 428 while((entry != vm_map_to_entry(map)) && (entry->vme_start < start)) { 429 entry = entry->vme_next; 430 } 431 432 while((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) { 433 if(entry->is_sub_map) { 434 total_entries += 435 get_vmsubmap_entries(entry->object.sub_map, 436 entry->offset, 437 entry->offset + 438 (entry->vme_end - entry->vme_start)); 439 } else { 440 total_entries += 1; 441 } 442 entry = entry->vme_next; 443 } 444 if (not_in_kdp) 445 vm_map_unlock(map); 446 return(total_entries); 447} 448 449int 450get_vmmap_entries( 451 vm_map_t map) 452{ 453 int total_entries = 0; 454 vm_map_entry_t entry; 455 456 if (not_in_kdp) 457 vm_map_lock(map); 458 entry = vm_map_first_entry(map); 459 460 while(entry != vm_map_to_entry(map)) { 461 if(entry->is_sub_map) { 462 total_entries += 463 get_vmsubmap_entries(entry->object.sub_map, 464 entry->offset, 465 entry->offset + 466 (entry->vme_end - entry->vme_start)); 467 } else { 468 total_entries += 1; 469 } 470 entry = entry->vme_next; 471 } 472 if (not_in_kdp) 473 vm_map_unlock(map); 474 return(total_entries); 475} 476 477/* 478 * 479 */ 480/* 481 * 482 */ 483int 484get_task_userstop( 485 task_t task) 486{ 487 return(task->user_stop_count); 488} 489 490/* 491 * 492 */ 493int 494get_thread_userstop( 495 thread_t th) 496{ 497 return(th->user_stop_count); 498} 499 500/* 501 * 502 */ 503boolean_t 504get_task_pidsuspended( 505 task_t task) 506{ 507 return (task->pidsuspended); 508} 509 510/* 511 * 512 */ 513boolean_t 514get_task_frozen( 515 task_t task) 516{ 517 return (task->frozen); 518} 519 520/* 521 * 522 */ 523boolean_t 524thread_should_abort( 525 thread_t th) 526{ 527 return ((th->sched_flags & TH_SFLAG_ABORTED_MASK) == TH_SFLAG_ABORT); 528} 529 530/* 531 * This routine is like thread_should_abort() above. It checks to 532 * see if the current thread is aborted. But unlike above, it also 533 * checks to see if thread is safely aborted. If so, it returns 534 * that fact, and clears the condition (safe aborts only should 535 * have a single effect, and a poll of the abort status 536 * qualifies. 537 */ 538boolean_t 539current_thread_aborted ( 540 void) 541{ 542 thread_t th = current_thread(); 543 spl_t s; 544 545 if ((th->sched_flags & TH_SFLAG_ABORTED_MASK) == TH_SFLAG_ABORT && 546 (th->options & TH_OPT_INTMASK) != THREAD_UNINT) 547 return (TRUE); 548 if (th->sched_flags & TH_SFLAG_ABORTSAFELY) { 549 s = splsched(); 550 thread_lock(th); 551 if (th->sched_flags & TH_SFLAG_ABORTSAFELY) 552 th->sched_flags &= ~TH_SFLAG_ABORTED_MASK; 553 thread_unlock(th); 554 splx(s); 555 } 556 return FALSE; 557} 558 559/* 560 * 561 */ 562void 563task_act_iterate_wth_args( 564 task_t task, 565 void (*func_callback)(thread_t, void *), 566 void *func_arg) 567{ 568 thread_t inc; 569 570 task_lock(task); 571 572 for (inc = (thread_t)(void *)queue_first(&task->threads); 573 !queue_end(&task->threads, (queue_entry_t)inc); ) { 574 (void) (*func_callback)(inc, func_arg); 575 inc = (thread_t)(void *)queue_next(&inc->task_threads); 576 } 577 578 task_unlock(task); 579} 580 581 582void 583astbsd_on(void) 584{ 585 boolean_t reenable; 586 587 reenable = ml_set_interrupts_enabled(FALSE); 588 ast_on_fast(AST_BSD); 589 (void)ml_set_interrupts_enabled(reenable); 590} 591 592 593#include <sys/bsdtask_info.h> 594 595void 596fill_taskprocinfo(task_t task, struct proc_taskinfo_internal * ptinfo) 597{ 598 vm_map_t map; 599 task_absolutetime_info_data_t tinfo; 600 thread_t thread; 601 uint32_t cswitch = 0, numrunning = 0; 602 uint32_t syscalls_unix = 0; 603 uint32_t syscalls_mach = 0; 604 605 map = (task == kernel_task)? kernel_map: task->map; 606 607 ptinfo->pti_virtual_size = map->size; 608 ptinfo->pti_resident_size = 609 (mach_vm_size_t)(pmap_resident_count(map->pmap)) 610 * PAGE_SIZE_64; 611 612 task_lock(task); 613 614 ptinfo->pti_policy = ((task != kernel_task)? 615 POLICY_TIMESHARE: POLICY_RR); 616 617 tinfo.threads_user = tinfo.threads_system = 0; 618 tinfo.total_user = task->total_user_time; 619 tinfo.total_system = task->total_system_time; 620 621 queue_iterate(&task->threads, thread, thread_t, task_threads) { 622 uint64_t tval; 623 spl_t x; 624 625 if (thread->options & TH_OPT_IDLE_THREAD) 626 continue; 627 628 x = splsched(); 629 thread_lock(thread); 630 631 if ((thread->state & TH_RUN) == TH_RUN) 632 numrunning++; 633 cswitch += thread->c_switch; 634 tval = timer_grab(&thread->user_timer); 635 tinfo.threads_user += tval; 636 tinfo.total_user += tval; 637 638 tval = timer_grab(&thread->system_timer); 639 640 if (thread->precise_user_kernel_time) { 641 tinfo.threads_system += tval; 642 tinfo.total_system += tval; 643 } else { 644 /* system_timer may represent either sys or user */ 645 tinfo.threads_user += tval; 646 tinfo.total_user += tval; 647 } 648 649 syscalls_unix += thread->syscalls_unix; 650 syscalls_mach += thread->syscalls_mach; 651 652 thread_unlock(thread); 653 splx(x); 654 } 655 656 ptinfo->pti_total_system = tinfo.total_system; 657 ptinfo->pti_total_user = tinfo.total_user; 658 ptinfo->pti_threads_system = tinfo.threads_system; 659 ptinfo->pti_threads_user = tinfo.threads_user; 660 661 ptinfo->pti_faults = task->faults; 662 ptinfo->pti_pageins = task->pageins; 663 ptinfo->pti_cow_faults = task->cow_faults; 664 ptinfo->pti_messages_sent = task->messages_sent; 665 ptinfo->pti_messages_received = task->messages_received; 666 ptinfo->pti_syscalls_mach = task->syscalls_mach + syscalls_mach; 667 ptinfo->pti_syscalls_unix = task->syscalls_unix + syscalls_unix; 668 ptinfo->pti_csw = task->c_switch + cswitch; 669 ptinfo->pti_threadnum = task->thread_count; 670 ptinfo->pti_numrunning = numrunning; 671 ptinfo->pti_priority = task->priority; 672 673 task_unlock(task); 674} 675 676int 677fill_taskthreadinfo(task_t task, uint64_t thaddr, int thuniqueid, struct proc_threadinfo_internal * ptinfo, void * vpp, int *vidp) 678{ 679 thread_t thact; 680 int err=0; 681 mach_msg_type_number_t count; 682 thread_basic_info_data_t basic_info; 683 kern_return_t kret; 684 uint64_t addr = 0; 685 686 task_lock(task); 687 688 for (thact = (thread_t)(void *)queue_first(&task->threads); 689 !queue_end(&task->threads, (queue_entry_t)thact); ) { 690 addr = (thuniqueid==0)?thact->machine.cthread_self: thact->thread_id; 691 if (addr == thaddr) 692 { 693 694 count = THREAD_BASIC_INFO_COUNT; 695 if ((kret = thread_info_internal(thact, THREAD_BASIC_INFO, (thread_info_t)&basic_info, &count)) != KERN_SUCCESS) { 696 err = 1; 697 goto out; 698 } 699 ptinfo->pth_user_time = ((basic_info.user_time.seconds * (integer_t)NSEC_PER_SEC) + (basic_info.user_time.microseconds * (integer_t)NSEC_PER_USEC)); 700 ptinfo->pth_system_time = ((basic_info.system_time.seconds * (integer_t)NSEC_PER_SEC) + (basic_info.system_time.microseconds * (integer_t)NSEC_PER_USEC)); 701 702 ptinfo->pth_cpu_usage = basic_info.cpu_usage; 703 ptinfo->pth_policy = basic_info.policy; 704 ptinfo->pth_run_state = basic_info.run_state; 705 ptinfo->pth_flags = basic_info.flags; 706 ptinfo->pth_sleep_time = basic_info.sleep_time; 707 ptinfo->pth_curpri = thact->sched_pri; 708 ptinfo->pth_priority = thact->priority; 709 ptinfo->pth_maxpriority = thact->max_priority; 710 711 if ((vpp != NULL) && (thact->uthread != NULL)) 712 bsd_threadcdir(thact->uthread, vpp, vidp); 713 bsd_getthreadname(thact->uthread,ptinfo->pth_name); 714 err = 0; 715 goto out; 716 } 717 thact = (thread_t)(void *)queue_next(&thact->task_threads); 718 } 719 err = 1; 720 721out: 722 task_unlock(task); 723 return(err); 724} 725 726int 727fill_taskthreadlist(task_t task, void * buffer, int thcount) 728{ 729 int numthr=0; 730 thread_t thact; 731 uint64_t * uptr; 732 uint64_t thaddr; 733 734 uptr = (uint64_t *)buffer; 735 736 task_lock(task); 737 738 for (thact = (thread_t)(void *)queue_first(&task->threads); 739 !queue_end(&task->threads, (queue_entry_t)thact); ) { 740 thaddr = thact->machine.cthread_self; 741 *uptr++ = thaddr; 742 numthr++; 743 if (numthr >= thcount) 744 goto out; 745 thact = (thread_t)(void *)queue_next(&thact->task_threads); 746 } 747 748out: 749 task_unlock(task); 750 return (int)(numthr * sizeof(uint64_t)); 751 752} 753 754int 755get_numthreads(task_t task) 756{ 757 return(task->thread_count); 758} 759 760void 761syscall_exit_funnelcheck(void) 762{ 763 thread_t thread; 764 765 thread = current_thread(); 766 767 if (thread->funnel_lock) 768 panic("syscall exit with funnel held\n"); 769} 770 771 772/* 773 * Gather the various pieces of info about the designated task, 774 * and collect it all into a single rusage_info. 775 */ 776int 777fill_task_rusage_v2(task_t task, struct rusage_info_v2 *ri) 778{ 779 struct task_power_info powerinfo; 780 781 assert(task != TASK_NULL); 782 task_lock(task); 783 784 task_power_info_locked(task, &powerinfo); 785 ri->ri_pkg_idle_wkups = powerinfo.task_platform_idle_wakeups; 786 ri->ri_interrupt_wkups = powerinfo.task_interrupt_wakeups; 787 ri->ri_user_time = powerinfo.total_user; 788 ri->ri_system_time = powerinfo.total_system; 789 790 ledger_get_balance(task->ledger, task_ledgers.phys_footprint, 791 (ledger_amount_t *)&ri->ri_phys_footprint); 792 ledger_get_balance(task->ledger, task_ledgers.phys_mem, 793 (ledger_amount_t *)&ri->ri_resident_size); 794 ledger_get_balance(task->ledger, task_ledgers.wired_mem, 795 (ledger_amount_t *)&ri->ri_wired_size); 796 797 ri->ri_pageins = task->pageins; 798 799 task_unlock(task); 800 return (0); 801} 802