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