]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/bsd_kern.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / kern / bsd_kern.c
CommitLineData
1c79356b 1/*
d9a64523 2 * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28#include <mach/mach_types.h>
b0d623f7 29#include <mach/machine/vm_param.h>
39236c6e 30#include <mach/task.h>
91447636
A
31
32#include <kern/kern_types.h>
39236c6e 33#include <kern/ledger.h>
91447636 34#include <kern/processor.h>
1c79356b 35#include <kern/thread.h>
1c79356b
A
36#include <kern/task.h>
37#include <kern/spl.h>
91447636 38#include <kern/ast.h>
1c79356b
A
39#include <ipc/ipc_port.h>
40#include <ipc/ipc_object.h>
91447636 41#include <vm/vm_map.h>
0c530ab8 42#include <vm/vm_kern.h>
91447636
A
43#include <vm/pmap.h>
44#include <vm/vm_protos.h> /* last */
39236c6e 45#include <sys/resource.h>
3e170ce0 46#include <sys/signal.h>
cb323159 47#include <sys/errno.h>
f427ee49 48#include <sys/proc_require.h>
1c79356b 49
5ba3f43e
A
50#if MONOTONIC
51#include <kern/monotonic.h>
52#include <machine/monotonic.h>
53#endif /* MONOTONIC */
54
55#include <machine/limits.h>
cb323159 56#include <sys/codesign.h> /* CS_CDHASH_LEN */
5ba3f43e 57
1c79356b 58#undef thread_should_halt
1c79356b 59
1c79356b
A
60/* BSD KERN COMPONENT INTERFACE */
61
55e303ae 62extern unsigned int not_in_kdp; /* Skip acquiring locks if we're in kdp */
0a7de745 63
91447636 64thread_t get_firstthread(task_t);
1c79356b 65int get_task_userstop(task_t);
91447636 66int get_thread_userstop(thread_t);
1c79356b 67boolean_t current_thread_aborted(void);
0a7de745
A
68void task_act_iterate_wth_args(task_t, void (*)(thread_t, void *), void *);
69kern_return_t get_signalact(task_t, thread_t *, int);
fe8ab488
A
70int fill_task_rusage(task_t task, rusage_info_current *ri);
71int fill_task_io_rusage(task_t task, rusage_info_current *ri);
72int fill_task_qos_rusage(task_t task, rusage_info_current *ri);
5ba3f43e 73void fill_task_monotonic_rusage(task_t task, rusage_info_current *ri);
cb323159 74uint64_t get_task_logical_writes(task_t task, boolean_t external);
fe8ab488 75void fill_task_billed_usage(task_t task, rusage_info_current *ri);
3e170ce0
A
76void task_bsdtask_kill(task_t);
77
39037602 78extern uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p);
cb323159 79extern uint64_t get_dispatchqueue_label_offset_from_proc(void *p);
39037602 80extern uint64_t proc_uniqueid(void *p);
5ba3f43e 81extern int proc_pidversion(void *p);
cb323159 82extern int proc_getcdhash(void *p, char *cdhash);
39037602 83
3e170ce0
A
84#if MACH_BSD
85extern void psignal(void *, int);
86#endif
1c79356b 87
1c79356b
A
88/*
89 *
90 */
0a7de745
A
91void *
92get_bsdtask_info(task_t t)
1c79356b 93{
f427ee49 94 proc_require(t->bsd_info, PROC_REQUIRE_ALLOW_NULL | PROC_REQUIRE_ALLOW_KERNPROC);
0a7de745 95 return t->bsd_info;
1c79356b
A
96}
97
0a7de745
A
98void
99task_bsdtask_kill(task_t t)
3e170ce0
A
100{
101 void * bsd_info = get_bsdtask_info(t);
102 if (bsd_info != NULL) {
103 psignal(bsd_info, SIGKILL);
104 }
105}
2d21ac55
A
106/*
107 *
108 */
0a7de745
A
109void *
110get_bsdthreadtask_info(thread_t th)
2d21ac55 111{
f427ee49
A
112 void *bsd_info = NULL;
113
114 if (th->task) {
115 bsd_info = get_bsdtask_info(th->task);
116 }
117 return bsd_info;
2d21ac55
A
118}
119
1c79356b
A
120/*
121 *
122 */
0a7de745
A
123void
124set_bsdtask_info(task_t t, void * v)
1c79356b 125{
0a7de745 126 t->bsd_info = v;
1c79356b
A
127}
128
129/*
130 *
131 */
0a7de745
A
132void *
133get_bsdthread_info(thread_t th)
134{
135 return th->uthread;
136}
137
cb323159
A
138/*
139 * This is used to remember any FS error from VNOP_PAGEIN code when
140 * invoked under vm_fault(). The value is an errno style value. It can
141 * be retrieved by exception handlers using thread_get_state().
142 */
143void
144set_thread_pagein_error(thread_t th, int error)
145{
146 assert(th == current_thread());
147 if (error == 0 || th->t_pagein_error == 0) {
148 th->t_pagein_error = error;
149 }
150}
151
0a7de745
A
152#if defined(__x86_64__)
153/*
154 * Returns non-zero if the thread has a non-NULL task
155 * and that task has an LDT.
156 */
157int
158thread_task_has_ldt(thread_t th)
1c79356b 159{
0a7de745 160 return th->task && th->task->i386_ldt != 0;
1c79356b 161}
0a7de745 162#endif /* __x86_64__ */
1c79356b 163
6d2010ae
A
164/*
165 * XXX
166 */
0a7de745
A
167int get_thread_lock_count(thread_t th); /* forced forward */
168int
169get_thread_lock_count(thread_t th)
6d2010ae 170{
0a7de745 171 return th->mutex_count;
6d2010ae
A
172}
173
1c79356b
A
174/*
175 * XXX: wait for BSD to fix signal code
176 * Until then, we cannot block here. We know the task
177 * can't go away, so we make sure it is still active after
178 * retrieving the first thread for extra safety.
179 */
0a7de745
A
180thread_t
181get_firstthread(task_t task)
1c79356b 182{
0a7de745 183 thread_t thread = (thread_t)(void *)queue_first(&task->threads);
91447636 184
0a7de745 185 if (queue_end(&task->threads, (queue_entry_t)thread)) {
91447636 186 thread = THREAD_NULL;
0a7de745 187 }
1c79356b 188
0a7de745
A
189 if (!task->active) {
190 return THREAD_NULL;
191 }
91447636 192
0a7de745 193 return thread;
1c79356b
A
194}
195
91447636
A
196kern_return_t
197get_signalact(
0a7de745
A
198 task_t task,
199 thread_t *result_out,
200 int setast)
1c79356b 201{
0a7de745
A
202 kern_return_t result = KERN_SUCCESS;
203 thread_t inc, thread = THREAD_NULL;
1c79356b
A
204
205 task_lock(task);
91447636 206
1c79356b
A
207 if (!task->active) {
208 task_unlock(task);
91447636 209
0a7de745 210 return KERN_FAILURE;
1c79356b
A
211 }
212
39236c6e 213 for (inc = (thread_t)(void *)queue_first(&task->threads);
0a7de745 214 !queue_end(&task->threads, (queue_entry_t)inc);) {
2d21ac55
A
215 thread_mtx_lock(inc);
216 if (inc->active &&
0a7de745 217 (inc->sched_flags & TH_SFLAG_ABORTED_MASK) != TH_SFLAG_ABORT) {
2d21ac55
A
218 thread = inc;
219 break;
220 }
221 thread_mtx_unlock(inc);
222
39236c6e 223 inc = (thread_t)(void *)queue_next(&inc->task_threads);
91447636
A
224 }
225
0a7de745 226 if (result_out) {
91447636 227 *result_out = thread;
0a7de745 228 }
91447636
A
229
230 if (thread) {
0a7de745 231 if (setast) {
91447636 232 act_set_astbsd(thread);
0a7de745 233 }
91447636
A
234
235 thread_mtx_unlock(thread);
0a7de745 236 } else {
91447636 237 result = KERN_FAILURE;
0a7de745 238 }
91447636 239
1c79356b
A
240 task_unlock(task);
241
0a7de745 242 return result;
1c79356b
A
243}
244
0b4e3aa0 245
91447636
A
246kern_return_t
247check_actforsig(
0a7de745
A
248 task_t task,
249 thread_t thread,
250 int setast)
0b4e3aa0 251{
0a7de745
A
252 kern_return_t result = KERN_FAILURE;
253 thread_t inc;
0b4e3aa0
A
254
255 task_lock(task);
91447636 256
0b4e3aa0
A
257 if (!task->active) {
258 task_unlock(task);
91447636 259
0a7de745 260 return KERN_FAILURE;
0b4e3aa0
A
261 }
262
39236c6e 263 for (inc = (thread_t)(void *)queue_first(&task->threads);
0a7de745 264 !queue_end(&task->threads, (queue_entry_t)inc);) {
91447636
A
265 if (inc == thread) {
266 thread_mtx_lock(inc);
267
0a7de745
A
268 if (inc->active &&
269 (inc->sched_flags & TH_SFLAG_ABORTED_MASK) != TH_SFLAG_ABORT) {
91447636 270 result = KERN_SUCCESS;
0b4e3aa0 271 break;
91447636 272 }
0b4e3aa0 273
91447636
A
274 thread_mtx_unlock(inc);
275 break;
276 }
277
39236c6e 278 inc = (thread_t)(void *)queue_next(&inc->task_threads);
91447636
A
279 }
280
281 if (result == KERN_SUCCESS) {
0a7de745 282 if (setast) {
91447636 283 act_set_astbsd(thread);
0a7de745 284 }
91447636
A
285
286 thread_mtx_unlock(thread);
287 }
288
289 task_unlock(task);
290
0a7de745 291 return result;
0b4e3aa0
A
292}
293
0a7de745
A
294ledger_t
295get_task_ledger(task_t t)
316670eb 296{
0a7de745 297 return t->ledger;
316670eb
A
298}
299
1c79356b 300/*
91447636 301 * This is only safe to call from a thread executing in
3e170ce0 302 * in the task's context or if the task is locked. Otherwise,
91447636 303 * the map could be switched for the task (and freed) before
3e170ce0 304 * we go to return it here.
1c79356b 305 */
0a7de745
A
306vm_map_t
307get_task_map(task_t t)
1c79356b 308{
0a7de745 309 return t->map;
1c79356b
A
310}
311
0a7de745
A
312vm_map_t
313get_task_map_reference(task_t t)
91447636
A
314{
315 vm_map_t m;
316
0a7de745 317 if (t == NULL) {
91447636 318 return VM_MAP_NULL;
0a7de745 319 }
91447636
A
320
321 task_lock(t);
322 if (!t->active) {
323 task_unlock(t);
324 return VM_MAP_NULL;
325 }
326 m = t->map;
c3c9b80d 327 vm_map_reference(m);
91447636
A
328 task_unlock(t);
329 return m;
330}
331
1c79356b
A
332/*
333 *
334 */
0a7de745
A
335ipc_space_t
336get_task_ipcspace(task_t t)
1c79356b 337{
0a7de745 338 return t->itk_space;
1c79356b
A
339}
340
0a7de745
A
341int
342get_task_numacts(task_t t)
1c79356b 343{
0a7de745 344 return t->thread_count;
55e303ae
A
345}
346
347/* does this machine need 64bit register set for signal handler */
0a7de745
A
348int
349is_64signalregset(void)
55e303ae 350{
d9a64523 351 if (task_has_64Bit_data(current_task())) {
0a7de745 352 return 1;
39236c6e
A
353 }
354
0a7de745 355 return 0;
1c79356b
A
356}
357
358/*
b0d623f7 359 * Swap in a new map for the task/thread pair; the old map reference is
d190cdc3 360 * returned. Also does a pmap switch if thread provided is current thread.
1c79356b
A
361 */
362vm_map_t
d190cdc3 363swap_task_map(task_t task, thread_t thread, vm_map_t map)
1c79356b
A
364{
365 vm_map_t old_map;
d190cdc3 366 boolean_t doswitch = (thread == current_thread()) ? TRUE : FALSE;
1c79356b 367
0a7de745 368 if (task != thread->task) {
55e303ae 369 panic("swap_task_map");
0a7de745 370 }
55e303ae 371
1c79356b 372 task_lock(task);
6d2010ae 373 mp_disable_preemption();
39037602 374
1c79356b 375 old_map = task->map;
91447636 376 thread->map = task->map = map;
39037602
A
377 vm_commit_pagezero_status(map);
378
316670eb 379 if (doswitch) {
0a7de745 380 PMAP_SWITCH_USER(thread, map, cpu_number());
316670eb 381 }
6d2010ae 382 mp_enable_preemption();
1c79356b 383 task_unlock(task);
0c530ab8 384
1c79356b
A
385 return old_map;
386}
387
1c79356b
A
388/*
389 *
3e170ce0
A
390 * This is only safe to call from a thread executing in
391 * in the task's context or if the task is locked. Otherwise,
392 * the map could be switched for the task (and freed) before
393 * we go to return it here.
1c79356b 394 */
0a7de745
A
395pmap_t
396get_task_pmap(task_t t)
1c79356b 397{
0a7de745 398 return t->map->pmap;
1c79356b
A
399}
400
b0d623f7
A
401/*
402 *
403 */
0a7de745
A
404uint64_t
405get_task_resident_size(task_t task)
b0d623f7
A
406{
407 vm_map_t map;
0a7de745 408
b0d623f7 409 map = (task == kernel_task) ? kernel_map: task->map;
0a7de745 410 return (uint64_t)pmap_resident_count(map->pmap) * PAGE_SIZE_64;
b0d623f7
A
411}
412
0a7de745
A
413uint64_t
414get_task_compressed(task_t task)
fe8ab488
A
415{
416 vm_map_t map;
0a7de745 417
fe8ab488 418 map = (task == kernel_task) ? kernel_map: task->map;
0a7de745 419 return (uint64_t)pmap_compressed(map->pmap) * PAGE_SIZE_64;
fe8ab488
A
420}
421
0a7de745
A
422uint64_t
423get_task_resident_max(task_t task)
fe8ab488
A
424{
425 vm_map_t map;
0a7de745 426
fe8ab488 427 map = (task == kernel_task) ? kernel_map: task->map;
0a7de745 428 return (uint64_t)pmap_resident_max(map->pmap) * PAGE_SIZE_64;
fe8ab488
A
429}
430
f427ee49
A
431/*
432 * Get the balance for a given field in the task ledger.
433 * Returns 0 if the entry is invalid.
434 */
435static uint64_t
436get_task_ledger_balance(task_t task, int entry)
437{
438 ledger_amount_t balance = 0;
439
440 ledger_get_balance(task->ledger, entry, &balance);
441 return balance;
442}
443
0a7de745
A
444uint64_t
445get_task_purgeable_size(task_t task)
fe8ab488 446{
3e170ce0 447 kern_return_t ret;
f427ee49 448 ledger_amount_t balance = 0;
3e170ce0
A
449 uint64_t volatile_size = 0;
450
f427ee49 451 ret = ledger_get_balance(task->ledger, task_ledgers.purgeable_volatile, &balance);
3e170ce0
A
452 if (ret != KERN_SUCCESS) {
453 return 0;
454 }
455
f427ee49 456 volatile_size += balance;
3e170ce0 457
f427ee49 458 ret = ledger_get_balance(task->ledger, task_ledgers.purgeable_volatile_compressed, &balance);
3e170ce0
A
459 if (ret != KERN_SUCCESS) {
460 return 0;
461 }
fe8ab488 462
f427ee49 463 volatile_size += balance;
3e170ce0
A
464
465 return volatile_size;
fe8ab488 466}
3e170ce0 467
39236c6e
A
468/*
469 *
470 */
0a7de745
A
471uint64_t
472get_task_phys_footprint(task_t task)
5ba3f43e 473{
f427ee49 474 return get_task_ledger_balance(task, task_ledgers.phys_footprint);
39236c6e
A
475}
476
d9a64523 477#if CONFIG_LEDGER_INTERVAL_MAX
39236c6e
A
478/*
479 *
480 */
0a7de745
A
481uint64_t
482get_task_phys_footprint_interval_max(task_t task, int reset)
5ba3f43e 483{
39236c6e
A
484 kern_return_t ret;
485 ledger_amount_t max;
5ba3f43e 486
d9a64523
A
487 ret = ledger_get_interval_max(task->ledger, task_ledgers.phys_footprint, &max, reset);
488
0a7de745 489 if (KERN_SUCCESS == ret) {
39236c6e
A
490 return max;
491 }
492
493 return 0;
494}
d9a64523 495#endif /* CONFIG_LEDGER_INTERVAL_MAX */
39236c6e 496
5ba3f43e
A
497/*
498 *
499 */
0a7de745
A
500uint64_t
501get_task_phys_footprint_lifetime_max(task_t task)
5ba3f43e
A
502{
503 kern_return_t ret;
504 ledger_amount_t max;
505
506 ret = ledger_get_lifetime_max(task->ledger, task_ledgers.phys_footprint, &max);
507
0a7de745 508 if (KERN_SUCCESS == ret) {
5ba3f43e
A
509 return max;
510 }
511
512 return 0;
513}
514
39037602
A
515/*
516 *
517 */
0a7de745
A
518uint64_t
519get_task_phys_footprint_limit(task_t task)
39037602
A
520{
521 kern_return_t ret;
522 ledger_amount_t max;
523
524 ret = ledger_get_limit(task->ledger, task_ledgers.phys_footprint, &max);
525 if (KERN_SUCCESS == ret) {
526 return max;
527 }
528
529 return 0;
530}
531
0a7de745
A
532uint64_t
533get_task_internal(task_t task)
39037602 534{
f427ee49
A
535 return get_task_ledger_balance(task, task_ledgers.internal);
536}
39037602 537
f427ee49
A
538uint64_t
539get_task_internal_compressed(task_t task)
540{
541 return get_task_ledger_balance(task, task_ledgers.internal_compressed);
542}
39037602 543
f427ee49
A
544uint64_t
545get_task_purgeable_nonvolatile(task_t task)
546{
547 return get_task_ledger_balance(task, task_ledgers.purgeable_nonvolatile);
39037602
A
548}
549
0a7de745 550uint64_t
f427ee49 551get_task_purgeable_nonvolatile_compressed(task_t task)
39037602 552{
f427ee49
A
553 return get_task_ledger_balance(task, task_ledgers.purgeable_nonvolatile_compressed);
554}
39037602 555
f427ee49
A
556uint64_t
557get_task_alternate_accounting(task_t task)
558{
559 return get_task_ledger_balance(task, task_ledgers.alternate_accounting);
560}
39037602 561
f427ee49
A
562uint64_t
563get_task_alternate_accounting_compressed(task_t task)
564{
565 return get_task_ledger_balance(task, task_ledgers.alternate_accounting_compressed);
39037602
A
566}
567
0a7de745 568uint64_t
f427ee49 569get_task_page_table(task_t task)
39037602 570{
f427ee49
A
571 return get_task_ledger_balance(task, task_ledgers.page_table);
572}
39037602 573
f427ee49
A
574#if CONFIG_FREEZE
575uint64_t
576get_task_frozen_to_swap(task_t task)
577{
578 return get_task_ledger_balance(task, task_ledgers.frozen_to_swap);
579}
580#endif /* CONFIG_FREEZE */
39037602 581
f427ee49
A
582uint64_t
583get_task_iokit_mapped(task_t task)
584{
585 return get_task_ledger_balance(task, task_ledgers.iokit_mapped);
39037602
A
586}
587
0a7de745 588uint64_t
f427ee49 589get_task_network_nonvolatile(task_t task)
39037602 590{
f427ee49
A
591 return get_task_ledger_balance(task, task_ledgers.network_nonvolatile);
592}
39037602 593
f427ee49
A
594uint64_t
595get_task_network_nonvolatile_compressed(task_t task)
596{
597 return get_task_ledger_balance(task, task_ledgers.network_nonvolatile_compressed);
598}
39037602 599
f427ee49
A
600uint64_t
601get_task_wired_mem(task_t task)
602{
603 return get_task_ledger_balance(task, task_ledgers.wired_mem);
39037602
A
604}
605
0a7de745 606uint64_t
f427ee49 607get_task_tagged_footprint(task_t task)
39037602
A
608{
609 kern_return_t ret;
610 ledger_amount_t credit, debit;
611
f427ee49 612 ret = ledger_get_entries(task->ledger, task_ledgers.tagged_footprint, &credit, &debit);
39037602 613 if (KERN_SUCCESS == ret) {
0a7de745 614 return credit - debit;
39037602
A
615 }
616
617 return 0;
618}
619
0a7de745 620uint64_t
f427ee49 621get_task_tagged_footprint_compressed(task_t task)
39037602
A
622{
623 kern_return_t ret;
624 ledger_amount_t credit, debit;
625
f427ee49 626 ret = ledger_get_entries(task->ledger, task_ledgers.tagged_footprint_compressed, &credit, &debit);
39037602 627 if (KERN_SUCCESS == ret) {
0a7de745 628 return credit - debit;
39037602
A
629 }
630
631 return 0;
632}
633
0a7de745 634uint64_t
f427ee49 635get_task_media_footprint(task_t task)
39037602
A
636{
637 kern_return_t ret;
638 ledger_amount_t credit, debit;
639
f427ee49 640 ret = ledger_get_entries(task->ledger, task_ledgers.media_footprint, &credit, &debit);
39037602 641 if (KERN_SUCCESS == ret) {
0a7de745 642 return credit - debit;
39037602
A
643 }
644
645 return 0;
646}
647
0a7de745 648uint64_t
f427ee49 649get_task_media_footprint_compressed(task_t task)
39037602
A
650{
651 kern_return_t ret;
652 ledger_amount_t credit, debit;
653
f427ee49 654 ret = ledger_get_entries(task->ledger, task_ledgers.media_footprint_compressed, &credit, &debit);
39037602 655 if (KERN_SUCCESS == ret) {
0a7de745 656 return credit - debit;
39037602
A
657 }
658
659 return 0;
660}
661
0a7de745 662uint64_t
f427ee49 663get_task_graphics_footprint(task_t task)
d9a64523 664{
0a7de745
A
665 kern_return_t ret;
666 ledger_amount_t credit, debit;
d9a64523 667
f427ee49 668 ret = ledger_get_entries(task->ledger, task_ledgers.graphics_footprint, &credit, &debit);
0a7de745
A
669 if (KERN_SUCCESS == ret) {
670 return credit - debit;
671 }
d9a64523 672
0a7de745 673 return 0;
d9a64523
A
674}
675
f427ee49 676
0a7de745 677uint64_t
f427ee49 678get_task_graphics_footprint_compressed(task_t task)
d9a64523 679{
0a7de745
A
680 kern_return_t ret;
681 ledger_amount_t credit, debit;
d9a64523 682
f427ee49 683 ret = ledger_get_entries(task->ledger, task_ledgers.graphics_footprint_compressed, &credit, &debit);
0a7de745
A
684 if (KERN_SUCCESS == ret) {
685 return credit - debit;
686 }
d9a64523 687
0a7de745 688 return 0;
d9a64523
A
689}
690
0a7de745 691uint64_t
f427ee49 692get_task_neural_footprint(task_t task)
d9a64523 693{
0a7de745
A
694 kern_return_t ret;
695 ledger_amount_t credit, debit;
d9a64523 696
f427ee49 697 ret = ledger_get_entries(task->ledger, task_ledgers.neural_footprint, &credit, &debit);
0a7de745
A
698 if (KERN_SUCCESS == ret) {
699 return credit - debit;
700 }
d9a64523 701
0a7de745 702 return 0;
d9a64523
A
703}
704
0a7de745 705uint64_t
f427ee49 706get_task_neural_footprint_compressed(task_t task)
fe8ab488
A
707{
708 kern_return_t ret;
709 ledger_amount_t credit, debit;
0a7de745 710
f427ee49 711 ret = ledger_get_entries(task->ledger, task_ledgers.neural_footprint_compressed, &credit, &debit);
fe8ab488 712 if (KERN_SUCCESS == ret) {
0a7de745 713 return credit - debit;
fe8ab488
A
714 }
715
716 return 0;
717}
718
f427ee49
A
719uint64_t
720get_task_cpu_time(task_t task)
721{
722 return get_task_ledger_balance(task, task_ledgers.cpu_time);
723}
724
cb323159
A
725uint32_t
726get_task_loadTag(task_t task)
727{
728 return os_atomic_load(&task->loadTag, relaxed);
729}
730
731uint32_t
732set_task_loadTag(task_t task, uint32_t loadTag)
733{
734 return os_atomic_xchg(&task->loadTag, loadTag, relaxed);
735}
736
1c79356b
A
737/*
738 *
739 */
0a7de745
A
740task_t
741get_threadtask(thread_t th)
1c79356b 742{
0a7de745 743 return th->task;
1c79356b
A
744}
745
1c79356b
A
746/*
747 *
748 */
91447636 749vm_map_offset_t
1c79356b 750get_map_min(
0a7de745 751 vm_map_t map)
1c79356b 752{
0a7de745 753 return vm_map_min(map);
1c79356b
A
754}
755
756/*
757 *
758 */
91447636 759vm_map_offset_t
1c79356b 760get_map_max(
0a7de745 761 vm_map_t map)
1c79356b 762{
0a7de745 763 return vm_map_max(map);
1c79356b 764}
91447636 765vm_map_size_t
1c79356b 766get_vmmap_size(
0a7de745 767 vm_map_t map)
1c79356b 768{
f427ee49 769 return vm_map_adjusted_size(map);
1c79356b 770}
c3c9b80d
A
771int
772get_task_page_size(
773 task_t task)
774{
775 return vm_map_page_size(task->map);
776}
1c79356b 777
39037602
A
778#if CONFIG_COREDUMP
779
780static int
1c79356b 781get_vmsubmap_entries(
0a7de745
A
782 vm_map_t map,
783 vm_object_offset_t start,
784 vm_object_offset_t end)
1c79356b 785{
0a7de745
A
786 int total_entries = 0;
787 vm_map_entry_t entry;
1c79356b 788
0a7de745
A
789 if (not_in_kdp) {
790 vm_map_lock(map);
791 }
1c79356b 792 entry = vm_map_first_entry(map);
0a7de745 793 while ((entry != vm_map_to_entry(map)) && (entry->vme_start < start)) {
1c79356b
A
794 entry = entry->vme_next;
795 }
796
0a7de745
A
797 while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
798 if (entry->is_sub_map) {
799 total_entries +=
800 get_vmsubmap_entries(VME_SUBMAP(entry),
801 VME_OFFSET(entry),
802 (VME_OFFSET(entry) +
803 entry->vme_end -
804 entry->vme_start));
1c79356b
A
805 } else {
806 total_entries += 1;
807 }
808 entry = entry->vme_next;
809 }
0a7de745
A
810 if (not_in_kdp) {
811 vm_map_unlock(map);
812 }
813 return total_entries;
1c79356b
A
814}
815
816int
817get_vmmap_entries(
0a7de745 818 vm_map_t map)
1c79356b 819{
0a7de745
A
820 int total_entries = 0;
821 vm_map_entry_t entry;
1c79356b 822
0a7de745
A
823 if (not_in_kdp) {
824 vm_map_lock(map);
825 }
1c79356b
A
826 entry = vm_map_first_entry(map);
827
0a7de745
A
828 while (entry != vm_map_to_entry(map)) {
829 if (entry->is_sub_map) {
830 total_entries +=
831 get_vmsubmap_entries(VME_SUBMAP(entry),
832 VME_OFFSET(entry),
833 (VME_OFFSET(entry) +
834 entry->vme_end -
835 entry->vme_start));
1c79356b
A
836 } else {
837 total_entries += 1;
838 }
839 entry = entry->vme_next;
840 }
0a7de745
A
841 if (not_in_kdp) {
842 vm_map_unlock(map);
843 }
844 return total_entries;
1c79356b 845}
39037602 846#endif /* CONFIG_COREDUMP */
1c79356b
A
847
848/*
849 *
850 */
851/*
852 *
853 */
854int
855get_task_userstop(
856 task_t task)
857{
0a7de745 858 return task->user_stop_count;
1c79356b
A
859}
860
861/*
862 *
863 */
864int
865get_thread_userstop(
91447636 866 thread_t th)
1c79356b 867{
0a7de745 868 return th->user_stop_count;
1c79356b
A
869}
870
316670eb
A
871/*
872 *
873 */
874boolean_t
875get_task_pidsuspended(
876 task_t task)
877{
0a7de745 878 return task->pidsuspended;
316670eb
A
879}
880
881/*
882 *
883 */
0a7de745 884boolean_t
316670eb
A
885get_task_frozen(
886 task_t task)
887{
0a7de745 888 return task->frozen;
316670eb
A
889}
890
1c79356b
A
891/*
892 *
893 */
894boolean_t
895thread_should_abort(
55e303ae 896 thread_t th)
1c79356b 897{
0a7de745 898 return (th->sched_flags & TH_SFLAG_ABORTED_MASK) == TH_SFLAG_ABORT;
1c79356b
A
899}
900
901/*
9bccf70c
A
902 * This routine is like thread_should_abort() above. It checks to
903 * see if the current thread is aborted. But unlike above, it also
904 * checks to see if thread is safely aborted. If so, it returns
905 * that fact, and clears the condition (safe aborts only should
906 * have a single effect, and a poll of the abort status
907 * qualifies.
1c79356b
A
908 */
909boolean_t
0a7de745
A
910current_thread_aborted(
911 void)
1c79356b
A
912{
913 thread_t th = current_thread();
9bccf70c
A
914 spl_t s;
915
6d2010ae 916 if ((th->sched_flags & TH_SFLAG_ABORTED_MASK) == TH_SFLAG_ABORT &&
0a7de745
A
917 (th->options & TH_OPT_INTMASK) != THREAD_UNINT) {
918 return TRUE;
919 }
6d2010ae 920 if (th->sched_flags & TH_SFLAG_ABORTSAFELY) {
9bccf70c
A
921 s = splsched();
922 thread_lock(th);
0a7de745 923 if (th->sched_flags & TH_SFLAG_ABORTSAFELY) {
6d2010ae 924 th->sched_flags &= ~TH_SFLAG_ABORTED_MASK;
0a7de745 925 }
9bccf70c
A
926 thread_unlock(th);
927 splx(s);
928 }
929 return FALSE;
1c79356b
A
930}
931
932/*
933 *
934 */
935void
936task_act_iterate_wth_args(
0a7de745
A
937 task_t task,
938 void (*func_callback)(thread_t, void *),
939 void *func_arg)
1c79356b 940{
0a7de745 941 thread_t inc;
1c79356b
A
942
943 task_lock(task);
91447636 944
39236c6e 945 for (inc = (thread_t)(void *)queue_first(&task->threads);
0a7de745 946 !queue_end(&task->threads, (queue_entry_t)inc);) {
91447636 947 (void) (*func_callback)(inc, func_arg);
39236c6e 948 inc = (thread_t)(void *)queue_next(&inc->task_threads);
91447636
A
949 }
950
1c79356b
A
951 task_unlock(task);
952}
953
1c79356b 954
0c530ab8
A
955#include <sys/bsdtask_info.h>
956
957void
958fill_taskprocinfo(task_t task, struct proc_taskinfo_internal * ptinfo)
959{
960 vm_map_t map;
961 task_absolutetime_info_data_t tinfo;
962 thread_t thread;
6d2010ae
A
963 uint32_t cswitch = 0, numrunning = 0;
964 uint32_t syscalls_unix = 0;
965 uint32_t syscalls_mach = 0;
39236c6e 966
3e170ce0
A
967 task_lock(task);
968
0c530ab8
A
969 map = (task == kernel_task)? kernel_map: task->map;
970
f427ee49 971 ptinfo->pti_virtual_size = vm_map_adjusted_size(map);
2d21ac55 972 ptinfo->pti_resident_size =
0a7de745
A
973 (mach_vm_size_t)(pmap_resident_count(map->pmap))
974 * PAGE_SIZE_64;
0c530ab8 975
0c530ab8 976 ptinfo->pti_policy = ((task != kernel_task)?
0a7de745 977 POLICY_TIMESHARE: POLICY_RR);
0c530ab8
A
978
979 tinfo.threads_user = tinfo.threads_system = 0;
980 tinfo.total_user = task->total_user_time;
981 tinfo.total_system = task->total_system_time;
982
983 queue_iterate(&task->threads, thread, thread_t, task_threads) {
984 uint64_t tval;
316670eb
A
985 spl_t x;
986
0a7de745 987 if (thread->options & TH_OPT_IDLE_THREAD) {
39236c6e 988 continue;
0a7de745 989 }
39236c6e 990
316670eb
A
991 x = splsched();
992 thread_lock(thread);
0c530ab8 993
0a7de745 994 if ((thread->state & TH_RUN) == TH_RUN) {
0c530ab8 995 numrunning++;
0a7de745 996 }
2d21ac55 997 cswitch += thread->c_switch;
0c530ab8
A
998 tval = timer_grab(&thread->user_timer);
999 tinfo.threads_user += tval;
1000 tinfo.total_user += tval;
1001
1002 tval = timer_grab(&thread->system_timer);
316670eb
A
1003
1004 if (thread->precise_user_kernel_time) {
1005 tinfo.threads_system += tval;
1006 tinfo.total_system += tval;
1007 } else {
1008 /* system_timer may represent either sys or user */
1009 tinfo.threads_user += tval;
1010 tinfo.total_user += tval;
1011 }
6d2010ae
A
1012
1013 syscalls_unix += thread->syscalls_unix;
1014 syscalls_mach += thread->syscalls_mach;
316670eb
A
1015
1016 thread_unlock(thread);
1017 splx(x);
0c530ab8
A
1018 }
1019
1020 ptinfo->pti_total_system = tinfo.total_system;
1021 ptinfo->pti_total_user = tinfo.total_user;
1022 ptinfo->pti_threads_system = tinfo.threads_system;
1023 ptinfo->pti_threads_user = tinfo.threads_user;
0a7de745 1024
c3c9b80d 1025 ptinfo->pti_faults = (int32_t) MIN(counter_load(&task->faults), INT32_MAX);
0c530ab8
A
1026 ptinfo->pti_pageins = task->pageins;
1027 ptinfo->pti_cow_faults = task->cow_faults;
1028 ptinfo->pti_messages_sent = task->messages_sent;
1029 ptinfo->pti_messages_received = task->messages_received;
6d2010ae
A
1030 ptinfo->pti_syscalls_mach = task->syscalls_mach + syscalls_mach;
1031 ptinfo->pti_syscalls_unix = task->syscalls_unix + syscalls_unix;
2d21ac55 1032 ptinfo->pti_csw = task->c_switch + cswitch;
0c530ab8
A
1033 ptinfo->pti_threadnum = task->thread_count;
1034 ptinfo->pti_numrunning = numrunning;
1035 ptinfo->pti_priority = task->priority;
1036
1037 task_unlock(task);
1038}
1039
0a7de745 1040int
d9a64523 1041fill_taskthreadinfo(task_t task, uint64_t thaddr, bool thuniqueid, struct proc_threadinfo_internal * ptinfo, void * vpp, int *vidp)
0c530ab8
A
1042{
1043 thread_t thact;
0a7de745 1044 int err = 0;
2d21ac55 1045 mach_msg_type_number_t count;
0c530ab8
A
1046 thread_basic_info_data_t basic_info;
1047 kern_return_t kret;
316670eb 1048 uint64_t addr = 0;
0c530ab8
A
1049
1050 task_lock(task);
1051
39236c6e 1052 for (thact = (thread_t)(void *)queue_first(&task->threads);
0a7de745 1053 !queue_end(&task->threads, (queue_entry_t)thact);) {
d9a64523 1054 addr = (thuniqueid) ? thact->thread_id : thact->machine.cthread_self;
0a7de745 1055 if (addr == thaddr) {
0c530ab8 1056 count = THREAD_BASIC_INFO_COUNT;
2d21ac55 1057 if ((kret = thread_info_internal(thact, THREAD_BASIC_INFO, (thread_info_t)&basic_info, &count)) != KERN_SUCCESS) {
0c530ab8 1058 err = 1;
0a7de745 1059 goto out;
0c530ab8 1060 }
cb323159
A
1061 ptinfo->pth_user_time = (((uint64_t)basic_info.user_time.seconds * NSEC_PER_SEC) + ((uint64_t)basic_info.user_time.microseconds * NSEC_PER_USEC));
1062 ptinfo->pth_system_time = (((uint64_t)basic_info.system_time.seconds * NSEC_PER_SEC) + ((uint64_t)basic_info.system_time.microseconds * NSEC_PER_USEC));
0c530ab8 1063
0c530ab8
A
1064 ptinfo->pth_cpu_usage = basic_info.cpu_usage;
1065 ptinfo->pth_policy = basic_info.policy;
1066 ptinfo->pth_run_state = basic_info.run_state;
1067 ptinfo->pth_flags = basic_info.flags;
1068 ptinfo->pth_sleep_time = basic_info.sleep_time;
1069 ptinfo->pth_curpri = thact->sched_pri;
3e170ce0 1070 ptinfo->pth_priority = thact->base_pri;
0c530ab8 1071 ptinfo->pth_maxpriority = thact->max_priority;
0a7de745
A
1072
1073 if ((vpp != NULL) && (thact->uthread != NULL)) {
2d21ac55 1074 bsd_threadcdir(thact->uthread, vpp, vidp);
0a7de745
A
1075 }
1076 bsd_getthreadname(thact->uthread, ptinfo->pth_name);
0c530ab8 1077 err = 0;
0a7de745 1078 goto out;
0c530ab8 1079 }
39236c6e 1080 thact = (thread_t)(void *)queue_next(&thact->task_threads);
0c530ab8
A
1081 }
1082 err = 1;
1083
1084out:
1085 task_unlock(task);
0a7de745 1086 return err;
0c530ab8
A
1087}
1088
1089int
d9a64523 1090fill_taskthreadlist(task_t task, void * buffer, int thcount, bool thuniqueid)
0c530ab8 1091{
0a7de745 1092 int numthr = 0;
0c530ab8
A
1093 thread_t thact;
1094 uint64_t * uptr;
1095 uint64_t thaddr;
1096
1097 uptr = (uint64_t *)buffer;
1098
1099 task_lock(task);
1100
39236c6e 1101 for (thact = (thread_t)(void *)queue_first(&task->threads);
0a7de745 1102 !queue_end(&task->threads, (queue_entry_t)thact);) {
d9a64523 1103 thaddr = (thuniqueid) ? thact->thread_id : thact->machine.cthread_self;
0c530ab8
A
1104 *uptr++ = thaddr;
1105 numthr++;
0a7de745 1106 if (numthr >= thcount) {
0c530ab8 1107 goto out;
0a7de745 1108 }
39236c6e 1109 thact = (thread_t)(void *)queue_next(&thact->task_threads);
0c530ab8
A
1110 }
1111
1112out:
1113 task_unlock(task);
b0d623f7 1114 return (int)(numthr * sizeof(uint64_t));
0c530ab8
A
1115}
1116
1117int
1118get_numthreads(task_t task)
1119{
0a7de745 1120 return task->thread_count;
0c530ab8
A
1121}
1122
39236c6e 1123/*
0a7de745 1124 * Gather the various pieces of info about the designated task,
39236c6e
A
1125 * and collect it all into a single rusage_info.
1126 */
1127int
fe8ab488 1128fill_task_rusage(task_t task, rusage_info_current *ri)
39236c6e
A
1129{
1130 struct task_power_info powerinfo;
1131
cb323159
A
1132 uint64_t runnable_time = 0;
1133
39236c6e
A
1134 assert(task != TASK_NULL);
1135 task_lock(task);
1136
cb323159 1137 task_power_info_locked(task, &powerinfo, NULL, NULL, &runnable_time);
39236c6e
A
1138 ri->ri_pkg_idle_wkups = powerinfo.task_platform_idle_wakeups;
1139 ri->ri_interrupt_wkups = powerinfo.task_interrupt_wakeups;
1140 ri->ri_user_time = powerinfo.total_user;
1141 ri->ri_system_time = powerinfo.total_system;
cb323159 1142 ri->ri_runnable_time = runnable_time;
39236c6e 1143
f427ee49 1144 ri->ri_phys_footprint = get_task_phys_footprint(task);
39236c6e 1145 ledger_get_balance(task->ledger, task_ledgers.phys_mem,
0a7de745 1146 (ledger_amount_t *)&ri->ri_resident_size);
f427ee49 1147 ri->ri_wired_size = get_task_wired_mem(task);
39236c6e
A
1148
1149 ri->ri_pageins = task->pageins;
1150
1151 task_unlock(task);
0a7de745 1152 return 0;
39236c6e 1153}
fe8ab488
A
1154
1155void
1156fill_task_billed_usage(task_t task __unused, rusage_info_current *ri)
1157{
5ba3f43e
A
1158 bank_billed_balance_safe(task, &ri->ri_billed_system_time, &ri->ri_billed_energy);
1159 bank_serviced_balance_safe(task, &ri->ri_serviced_system_time, &ri->ri_serviced_energy);
fe8ab488
A
1160}
1161
1162int
1163fill_task_io_rusage(task_t task, rusage_info_current *ri)
1164{
1165 assert(task != TASK_NULL);
1166 task_lock(task);
1167
1168 if (task->task_io_stats) {
1169 ri->ri_diskio_bytesread = task->task_io_stats->disk_reads.size;
1170 ri->ri_diskio_byteswritten = (task->task_io_stats->total_io.size - task->task_io_stats->disk_reads.size);
1171 } else {
1172 /* I/O Stats unavailable */
1173 ri->ri_diskio_bytesread = 0;
1174 ri->ri_diskio_byteswritten = 0;
1175 }
1176 task_unlock(task);
0a7de745 1177 return 0;
fe8ab488
A
1178}
1179
1180int
1181fill_task_qos_rusage(task_t task, rusage_info_current *ri)
1182{
1183 thread_t thread;
1184
1185 assert(task != TASK_NULL);
1186 task_lock(task);
1187
a39ff7e2 1188 /* Rollup QoS time of all the threads to task */
fe8ab488 1189 queue_iterate(&task->threads, thread, thread_t, task_threads) {
0a7de745 1190 if (thread->options & TH_OPT_IDLE_THREAD) {
fe8ab488 1191 continue;
0a7de745 1192 }
fe8ab488 1193
39037602 1194 thread_update_qos_cpu_time(thread);
fe8ab488 1195 }
a39ff7e2
A
1196 ri->ri_cpu_time_qos_default = task->cpu_time_eqos_stats.cpu_time_qos_default;
1197 ri->ri_cpu_time_qos_maintenance = task->cpu_time_eqos_stats.cpu_time_qos_maintenance;
1198 ri->ri_cpu_time_qos_background = task->cpu_time_eqos_stats.cpu_time_qos_background;
1199 ri->ri_cpu_time_qos_utility = task->cpu_time_eqos_stats.cpu_time_qos_utility;
1200 ri->ri_cpu_time_qos_legacy = task->cpu_time_eqos_stats.cpu_time_qos_legacy;
1201 ri->ri_cpu_time_qos_user_initiated = task->cpu_time_eqos_stats.cpu_time_qos_user_initiated;
1202 ri->ri_cpu_time_qos_user_interactive = task->cpu_time_eqos_stats.cpu_time_qos_user_interactive;
fe8ab488
A
1203
1204 task_unlock(task);
0a7de745 1205 return 0;
fe8ab488 1206}
39037602 1207
5ba3f43e
A
1208void
1209fill_task_monotonic_rusage(task_t task, rusage_info_current *ri)
1210{
1211#if MONOTONIC
1212 if (!mt_core_supported) {
1213 return;
1214 }
1215
1216 assert(task != TASK_NULL);
1217
e8c3f781 1218 uint64_t counts[MT_CORE_NFIXED] = { 0 };
5ba3f43e
A
1219 mt_fixed_task_counts(task, counts);
1220#ifdef MT_CORE_INSTRS
1221 ri->ri_instructions = counts[MT_CORE_INSTRS];
1222#endif /* defined(MT_CORE_INSTRS) */
1223 ri->ri_cycles = counts[MT_CORE_CYCLES];
1224#else /* MONOTONIC */
1225#pragma unused(task, ri)
1226#endif /* !MONOTONIC */
1227}
1228
1229uint64_t
cb323159 1230get_task_logical_writes(task_t task, boolean_t external)
5ba3f43e 1231{
0a7de745
A
1232 assert(task != TASK_NULL);
1233 struct ledger_entry_info lei;
5ba3f43e 1234
0a7de745 1235 task_lock(task);
cb323159
A
1236
1237 if (external == FALSE) {
1238 ledger_get_entry_info(task->ledger, task_ledgers.logical_writes, &lei);
1239 } else {
1240 ledger_get_entry_info(task->ledger, task_ledgers.logical_writes_to_external, &lei);
1241 }
1242
0a7de745 1243 ledger_get_entry_info(task->ledger, task_ledgers.logical_writes, &lei);
5ba3f43e 1244
0a7de745
A
1245 task_unlock(task);
1246 return lei.lei_balance;
5ba3f43e
A
1247}
1248
39037602
A
1249uint64_t
1250get_task_dispatchqueue_serialno_offset(task_t task)
1251{
1252 uint64_t dq_serialno_offset = 0;
1253
1254 if (task->bsd_info) {
1255 dq_serialno_offset = get_dispatchqueue_serialno_offset_from_proc(task->bsd_info);
1256 }
1257
1258 return dq_serialno_offset;
1259}
1260
cb323159
A
1261uint64_t
1262get_task_dispatchqueue_label_offset(task_t task)
1263{
1264 uint64_t dq_label_offset = 0;
1265
1266 if (task->bsd_info) {
1267 dq_label_offset = get_dispatchqueue_label_offset_from_proc(task->bsd_info);
1268 }
1269
1270 return dq_label_offset;
1271}
1272
39037602
A
1273uint64_t
1274get_task_uniqueid(task_t task)
1275{
1276 if (task->bsd_info) {
1277 return proc_uniqueid(task->bsd_info);
1278 } else {
1279 return UINT64_MAX;
1280 }
1281}
1282
5ba3f43e
A
1283int
1284get_task_version(task_t task)
1285{
1286 if (task->bsd_info) {
1287 return proc_pidversion(task->bsd_info);
1288 } else {
1289 return INT_MAX;
1290 }
1291}
1292
39037602
A
1293#if CONFIG_MACF
1294struct label *
1295get_task_crash_label(task_t task)
1296{
1297 return task->crash_label;
1298}
39037602 1299#endif
cb323159
A
1300
1301int
1302fill_taskipctableinfo(task_t task, uint32_t *table_size, uint32_t *table_free)
1303{
1304 ipc_space_t space = task->itk_space;
1305 if (space == NULL) {
1306 return -1;
1307 }
1308
1309 is_read_lock(space);
1310 if (!is_active(space)) {
1311 is_read_unlock(space);
1312 return -1;
1313 }
1314
1315 *table_size = space->is_table_size;
1316 *table_free = space->is_table_free;
1317
1318 is_read_unlock(space);
1319
1320 return 0;
1321}
1322
1323int
1324get_task_cdhash(task_t task, char cdhash[static CS_CDHASH_LEN])
1325{
1326 int result = 0;
1327
1328 task_lock(task);
1329 result = task->bsd_info ? proc_getcdhash(task->bsd_info, cdhash) : ESRCH;
1330 task_unlock(task);
1331
1332 return result;
1333}