/*
- * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <vm/pmap.h>
#include <vm/vm_protos.h> /* last */
#include <sys/resource.h>
+#include <sys/signal.h>
+
+#if MONOTONIC
+#include <kern/monotonic.h>
+#include <machine/monotonic.h>
+#endif /* MONOTONIC */
+
+#include <machine/limits.h>
#undef thread_should_halt
/* BSD KERN COMPONENT INTERFACE */
-task_t bsd_init_task = TASK_NULL;
-boolean_t init_task_died;
-char init_task_failure_data[1024];
extern unsigned int not_in_kdp; /* Skip acquiring locks if we're in kdp */
thread_t get_firstthread(task_t);
boolean_t current_thread_aborted(void);
void task_act_iterate_wth_args(task_t, void(*)(thread_t, void *), void *);
kern_return_t get_signalact(task_t , thread_t *, int);
-int get_vmsubmap_entries(vm_map_t, vm_object_offset_t, vm_object_offset_t);
int fill_task_rusage(task_t task, rusage_info_current *ri);
int fill_task_io_rusage(task_t task, rusage_info_current *ri);
int fill_task_qos_rusage(task_t task, rusage_info_current *ri);
+void fill_task_monotonic_rusage(task_t task, rusage_info_current *ri);
+uint64_t get_task_logical_writes(task_t task);
void fill_task_billed_usage(task_t task, rusage_info_current *ri);
+void task_bsdtask_kill(task_t);
+
+extern uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p);
+extern uint64_t proc_uniqueid(void *p);
+extern int proc_pidversion(void *p);
+
+#if MACH_BSD
+extern void psignal(void *, int);
+#endif
/*
*
return(t->bsd_info);
}
+void task_bsdtask_kill(task_t t)
+{
+ void * bsd_info = get_bsdtask_info(t);
+ if (bsd_info != NULL) {
+ psignal(bsd_info, SIGKILL);
+ }
+}
/*
*
*/
/*
* This is only safe to call from a thread executing in
- * in the task's context or if the task is locked Otherwise,
+ * in the task's context or if the task is locked. Otherwise,
* the map could be switched for the task (and freed) before
- * we to return it here.
+ * we go to return it here.
*/
vm_map_t get_task_map(task_t t)
{
/* does this machine need 64bit register set for signal handler */
int is_64signalregset(void)
{
- if (task_has_64BitData(current_task())) {
+ if (task_has_64Bit_data(current_task())) {
return(1);
}
/*
* Swap in a new map for the task/thread pair; the old map reference is
- * returned.
+ * returned. Also does a pmap switch if thread provided is current thread.
*/
vm_map_t
-swap_task_map(task_t task, thread_t thread, vm_map_t map, boolean_t doswitch)
+swap_task_map(task_t task, thread_t thread, vm_map_t map)
{
vm_map_t old_map;
+ boolean_t doswitch = (thread == current_thread()) ? TRUE : FALSE;
if (task != thread->task)
panic("swap_task_map");
task_lock(task);
mp_disable_preemption();
+
old_map = task->map;
thread->map = task->map = map;
+ vm_commit_pagezero_status(map);
+
if (doswitch) {
+#if defined(__arm__) || defined(__arm64__)
+ PMAP_SWITCH_USER(thread, map, cpu_number())
+#else
pmap_switch(map->pmap);
+#endif
}
mp_enable_preemption();
task_unlock(task);
/*
*
+ * This is only safe to call from a thread executing in
+ * in the task's context or if the task is locked. Otherwise,
+ * the map could be switched for the task (and freed) before
+ * we go to return it here.
*/
pmap_t get_task_pmap(task_t t)
{
uint64_t get_task_purgeable_size(task_t task)
{
- vm_map_t map;
- mach_vm_size_t volatile_virtual_size;
- mach_vm_size_t volatile_resident_size;
- mach_vm_size_t volatile_pmap_size;
-
- map = (task == kernel_task) ? kernel_map: task->map;
- vm_map_query_volatile(map, &volatile_virtual_size, &volatile_resident_size, &volatile_pmap_size);
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+ uint64_t volatile_size = 0;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.purgeable_volatile, &credit, &debit);
+ if (ret != KERN_SUCCESS) {
+ return 0;
+ }
- return((uint64_t)volatile_resident_size);
+ volatile_size += (credit - debit);
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.purgeable_volatile_compressed, &credit, &debit);
+ if (ret != KERN_SUCCESS) {
+ return 0;
+ }
+
+ volatile_size += (credit - debit);
+
+ return volatile_size;
}
+
/*
*
*/
-uint64_t get_task_phys_footprint(task_t task)
-{
+uint64_t get_task_phys_footprint(task_t task)
+{
kern_return_t ret;
ledger_amount_t credit, debit;
-
+
ret = ledger_get_entries(task->ledger, task_ledgers.phys_footprint, &credit, &debit);
if (KERN_SUCCESS == ret) {
return (credit - debit);
return 0;
}
+#if CONFIG_LEDGER_INTERVAL_MAX
/*
*
*/
-uint64_t get_task_phys_footprint_max(task_t task)
-{
+uint64_t get_task_phys_footprint_interval_max(task_t task, int reset)
+{
kern_return_t ret;
ledger_amount_t max;
-
- ret = ledger_get_maximum(task->ledger, task_ledgers.phys_footprint, &max);
+
+ ret = ledger_get_interval_max(task->ledger, task_ledgers.phys_footprint, &max, reset);
+
+ if(KERN_SUCCESS == ret) {
+ return max;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_LEDGER_INTERVAL_MAX */
+
+/*
+ *
+ */
+uint64_t get_task_phys_footprint_lifetime_max(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t max;
+
+ ret = ledger_get_lifetime_max(task->ledger, task_ledgers.phys_footprint, &max);
+
+ if(KERN_SUCCESS == ret) {
+ return max;
+ }
+
+ return 0;
+}
+
+/*
+ *
+ */
+uint64_t get_task_phys_footprint_limit(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t max;
+
+ ret = ledger_get_limit(task->ledger, task_ledgers.phys_footprint, &max);
if (KERN_SUCCESS == ret) {
return max;
}
return 0;
}
+uint64_t get_task_internal(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.internal, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_internal_compressed(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.internal_compressed, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_purgeable_nonvolatile(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.purgeable_nonvolatile, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_purgeable_nonvolatile_compressed(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.purgeable_nonvolatile_compressed, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_alternate_accounting(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.alternate_accounting, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_alternate_accounting_compressed(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.alternate_accounting_compressed, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_page_table(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.page_table, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_iokit_mapped(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.iokit_mapped, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_network_nonvolatile(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.network_nonvolatile, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_network_nonvolatile_compressed(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.network_nonvolatile_compressed, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+uint64_t get_task_wired_mem(task_t task)
+{
+ kern_return_t ret;
+ ledger_amount_t credit, debit;
+
+ ret = ledger_get_entries(task->ledger, task_ledgers.wired_mem, &credit, &debit);
+ if (KERN_SUCCESS == ret) {
+ return (credit - debit);
+ }
+
+ return 0;
+}
+
+
uint64_t get_task_cpu_time(task_t task)
{
kern_return_t ret;
return 0;
}
-/*
- *
- */
-pmap_t get_map_pmap(vm_map_t map)
-{
- return(map->pmap);
-}
/*
*
*/
return(map->size);
}
-int
+#if CONFIG_COREDUMP
+
+static int
get_vmsubmap_entries(
vm_map_t map,
vm_object_offset_t start,
while((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
if(entry->is_sub_map) {
total_entries +=
- get_vmsubmap_entries(entry->object.sub_map,
- entry->offset,
- entry->offset +
- (entry->vme_end - entry->vme_start));
+ get_vmsubmap_entries(VME_SUBMAP(entry),
+ VME_OFFSET(entry),
+ (VME_OFFSET(entry) +
+ entry->vme_end -
+ entry->vme_start));
} else {
total_entries += 1;
}
while(entry != vm_map_to_entry(map)) {
if(entry->is_sub_map) {
total_entries +=
- get_vmsubmap_entries(entry->object.sub_map,
- entry->offset,
- entry->offset +
- (entry->vme_end - entry->vme_start));
+ get_vmsubmap_entries(VME_SUBMAP(entry),
+ VME_OFFSET(entry),
+ (VME_OFFSET(entry) +
+ entry->vme_end -
+ entry->vme_start));
} else {
total_entries += 1;
}
vm_map_unlock(map);
return(total_entries);
}
+#endif /* CONFIG_COREDUMP */
/*
*
}
-void
-astbsd_on(void)
-{
- boolean_t reenable;
-
- reenable = ml_set_interrupts_enabled(FALSE);
- ast_on_fast(AST_BSD);
- (void)ml_set_interrupts_enabled(reenable);
-}
-
-
#include <sys/bsdtask_info.h>
void
uint32_t syscalls_unix = 0;
uint32_t syscalls_mach = 0;
+ task_lock(task);
+
map = (task == kernel_task)? kernel_map: task->map;
ptinfo->pti_virtual_size = map->size;
(mach_vm_size_t)(pmap_resident_count(map->pmap))
* PAGE_SIZE_64;
- task_lock(task);
-
ptinfo->pti_policy = ((task != kernel_task)?
POLICY_TIMESHARE: POLICY_RR);
}
int
-fill_taskthreadinfo(task_t task, uint64_t thaddr, int thuniqueid, struct proc_threadinfo_internal * ptinfo, void * vpp, int *vidp)
+fill_taskthreadinfo(task_t task, uint64_t thaddr, bool thuniqueid, struct proc_threadinfo_internal * ptinfo, void * vpp, int *vidp)
{
thread_t thact;
int err=0;
for (thact = (thread_t)(void *)queue_first(&task->threads);
!queue_end(&task->threads, (queue_entry_t)thact); ) {
- addr = (thuniqueid==0)?thact->machine.cthread_self: thact->thread_id;
+ addr = (thuniqueid) ? thact->thread_id : thact->machine.cthread_self;
if (addr == thaddr)
{
ptinfo->pth_flags = basic_info.flags;
ptinfo->pth_sleep_time = basic_info.sleep_time;
ptinfo->pth_curpri = thact->sched_pri;
- ptinfo->pth_priority = thact->priority;
+ ptinfo->pth_priority = thact->base_pri;
ptinfo->pth_maxpriority = thact->max_priority;
if ((vpp != NULL) && (thact->uthread != NULL))
}
int
-fill_taskthreadlist(task_t task, void * buffer, int thcount)
+fill_taskthreadlist(task_t task, void * buffer, int thcount, bool thuniqueid)
{
int numthr=0;
thread_t thact;
for (thact = (thread_t)(void *)queue_first(&task->threads);
!queue_end(&task->threads, (queue_entry_t)thact); ) {
- thaddr = thact->machine.cthread_self;
+ thaddr = (thuniqueid) ? thact->thread_id : thact->machine.cthread_self;
*uptr++ = thaddr;
numthr++;
if (numthr >= thcount)
assert(task != TASK_NULL);
task_lock(task);
- task_power_info_locked(task, &powerinfo, NULL);
+ task_power_info_locked(task, &powerinfo, NULL, NULL);
ri->ri_pkg_idle_wkups = powerinfo.task_platform_idle_wakeups;
ri->ri_interrupt_wkups = powerinfo.task_interrupt_wakeups;
ri->ri_user_time = powerinfo.total_user;
void
fill_task_billed_usage(task_t task __unused, rusage_info_current *ri)
{
-#if CONFIG_BANK
- ri->ri_billed_system_time = bank_billed_time(task->bank_context);
- ri->ri_serviced_system_time = bank_serviced_time(task->bank_context);
-#else
- ri->ri_billed_system_time = 0;
- ri->ri_serviced_system_time = 0;
-#endif
+ bank_billed_balance_safe(task, &ri->ri_billed_system_time, &ri->ri_billed_energy);
+ bank_serviced_balance_safe(task, &ri->ri_serviced_system_time, &ri->ri_serviced_energy);
}
int
assert(task != TASK_NULL);
task_lock(task);
- /* Rollup Qos time of all the threads to task */
+ /* Rollup QoS time of all the threads to task */
queue_iterate(&task->threads, thread, thread_t, task_threads) {
if (thread->options & TH_OPT_IDLE_THREAD)
continue;
- thread_mtx_lock(thread);
- thread_update_qos_cpu_time(thread, TRUE);
- thread_mtx_unlock(thread);
-
+ thread_update_qos_cpu_time(thread);
}
- ri->ri_cpu_time_qos_default = task->cpu_time_qos_stats.cpu_time_qos_default;
- ri->ri_cpu_time_qos_maintenance = task->cpu_time_qos_stats.cpu_time_qos_maintenance;
- ri->ri_cpu_time_qos_background = task->cpu_time_qos_stats.cpu_time_qos_background;
- ri->ri_cpu_time_qos_utility = task->cpu_time_qos_stats.cpu_time_qos_utility;
- ri->ri_cpu_time_qos_legacy = task->cpu_time_qos_stats.cpu_time_qos_legacy;
- ri->ri_cpu_time_qos_user_initiated = task->cpu_time_qos_stats.cpu_time_qos_user_initiated;
- ri->ri_cpu_time_qos_user_interactive = task->cpu_time_qos_stats.cpu_time_qos_user_interactive;
+ ri->ri_cpu_time_qos_default = task->cpu_time_eqos_stats.cpu_time_qos_default;
+ ri->ri_cpu_time_qos_maintenance = task->cpu_time_eqos_stats.cpu_time_qos_maintenance;
+ ri->ri_cpu_time_qos_background = task->cpu_time_eqos_stats.cpu_time_qos_background;
+ ri->ri_cpu_time_qos_utility = task->cpu_time_eqos_stats.cpu_time_qos_utility;
+ ri->ri_cpu_time_qos_legacy = task->cpu_time_eqos_stats.cpu_time_qos_legacy;
+ ri->ri_cpu_time_qos_user_initiated = task->cpu_time_eqos_stats.cpu_time_qos_user_initiated;
+ ri->ri_cpu_time_qos_user_interactive = task->cpu_time_eqos_stats.cpu_time_qos_user_interactive;
task_unlock(task);
return (0);
}
+
+void
+fill_task_monotonic_rusage(task_t task, rusage_info_current *ri)
+{
+#if MONOTONIC
+ if (!mt_core_supported) {
+ return;
+ }
+
+ assert(task != TASK_NULL);
+
+ uint64_t counts[MT_CORE_NFIXED] = { 0 };
+ mt_fixed_task_counts(task, counts);
+#ifdef MT_CORE_INSTRS
+ ri->ri_instructions = counts[MT_CORE_INSTRS];
+#endif /* defined(MT_CORE_INSTRS) */
+ ri->ri_cycles = counts[MT_CORE_CYCLES];
+#else /* MONOTONIC */
+#pragma unused(task, ri)
+#endif /* !MONOTONIC */
+}
+
+uint64_t
+get_task_logical_writes(task_t task)
+{
+ assert(task != TASK_NULL);
+ struct ledger_entry_info lei;
+
+ task_lock(task);
+ ledger_get_entry_info(task->ledger, task_ledgers.logical_writes, &lei);
+
+ task_unlock(task);
+ return lei.lei_balance;
+}
+
+uint64_t
+get_task_dispatchqueue_serialno_offset(task_t task)
+{
+ uint64_t dq_serialno_offset = 0;
+
+ if (task->bsd_info) {
+ dq_serialno_offset = get_dispatchqueue_serialno_offset_from_proc(task->bsd_info);
+ }
+
+ return dq_serialno_offset;
+}
+
+uint64_t
+get_task_uniqueid(task_t task)
+{
+ if (task->bsd_info) {
+ return proc_uniqueid(task->bsd_info);
+ } else {
+ return UINT64_MAX;
+ }
+}
+
+int
+get_task_version(task_t task)
+{
+ if (task->bsd_info) {
+ return proc_pidversion(task->bsd_info);
+ } else {
+ return INT_MAX;
+ }
+}
+
+#if CONFIG_MACF
+struct label *
+get_task_crash_label(task_t task)
+{
+ return task->crash_label;
+}
+#endif