/*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <sys/malloc.h>
#include <sys/proc_internal.h>
#include <sys/kauth.h>
-#include <machine/spl.h>
-
#include <sys/mount_internal.h>
#include <sys/sysproto.h>
#include <kern/clock.h> /* for absolutetime_to_microtime() */
#include <netinet/in.h> /* for TRAFFIC_MGT_SO_* */
#include <sys/socketvar.h> /* for struct socket */
+#if NECP
+#include <net/necp.h>
+#endif /* NECP */
#include <vm/vm_map.h>
#include <sys/priv.h>
#include <IOKit/IOBSD.h>
+#if CONFIG_MACF
+#include <security/mac_framework.h>
+#endif
+
int donice(struct proc *curp, struct proc *chgp, int n);
int dosetrlimit(struct proc *p, u_int which, struct rlimit *limp);
int uthread_get_background_state(uthread_t);
void fill_task_billed_usage(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);
-static void rusage_info_conversion(rusage_info_t ri_info, rusage_info_current *ri_current, int flavor);
+uint64_t get_task_logical_writes(task_t task);
+void fill_task_monotonic_rusage(task_t task, rusage_info_current *ri);
int proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie);
proc_set_darwin_role(proc_t curp, proc_t targetp, int priority)
{
int error = 0;
- uint32_t flagsp;
+ uint32_t flagsp = 0;
kauth_cred_t ucred, target_cred;
fdp = p->p_fd;
for (i = 0; i < fdp->fd_nfiles; i++) {
- struct socket *sockp;
-
fp = fdp->fd_ofiles[i];
- if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0 ||
- FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET) {
+ if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0) {
continue;
}
- sockp = (struct socket *)fp->f_fglob->fg_data;
- socket_set_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND);
- sockp->so_background_thread = NULL;
+ if (FILEGLOB_DTYPE(fp->f_fglob) == DTYPE_SOCKET) {
+ struct socket *sockp = (struct socket *)fp->f_fglob->fg_data;
+ socket_set_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND);
+ sockp->so_background_thread = NULL;
+ }
+#if NECP
+ else if (FILEGLOB_DTYPE(fp->f_fglob) == DTYPE_NETPOLICY) {
+ necp_set_client_as_background(p, fp, background);
+ }
+#endif /* NECP */
}
}
} else {
struct socket *sockp;
fp = fdp->fd_ofiles[ i ];
- if ( fp == NULL || (fdp->fd_ofileflags[ i ] & UF_RESERVED) != 0 ||
- FILEGLOB_DTYPE(fp->f_fglob) != DTYPE_SOCKET ) {
+ if (fp == NULL || (fdp->fd_ofileflags[ i ] & UF_RESERVED) != 0) {
continue;
}
- sockp = (struct socket *)fp->f_fglob->fg_data;
- /* skip if only clearing this thread's sockets */
- if ((thread) && (sockp->so_background_thread != thread)) {
- continue;
+ if (FILEGLOB_DTYPE(fp->f_fglob) == DTYPE_SOCKET) {
+ sockp = (struct socket *)fp->f_fglob->fg_data;
+ /* skip if only clearing this thread's sockets */
+ if ((thread) && (sockp->so_background_thread != thread)) {
+ continue;
+ }
+ socket_clear_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND);
+ sockp->so_background_thread = NULL;
}
- socket_clear_traffic_mgt_flags(sockp, TRAFFIC_MGT_SO_BACKGROUND);
- sockp->so_background_thread = NULL;
+#if NECP
+ else if (FILEGLOB_DTYPE(fp->f_fglob) == DTYPE_NETPOLICY) {
+ necp_set_client_as_background(p, fp, background);
+ }
+#endif /* NECP */
}
}
break;
case IOPOL_SCOPE_DARWIN_BG:
+#if CONFIG_EMBEDDED
+ /* Embedded doesn't want this as BG is always IOPOL_THROTTLE */
+ error = ENOTSUP;
+ goto out;
+#else /* CONFIG_EMBEDDED */
thread = THREAD_NULL;
policy_flavor = TASK_POLICY_DARWIN_BG_IOPOL;
break;
+#endif /* CONFIG_EMBEDDED */
default:
error = EINVAL;
struct rusage_info_child *ri_child;
assert(p->p_stats != NULL);
+ memset(ru, 0, sizeof(*ru));
switch(flavor) {
+ case RUSAGE_INFO_V4:
+ ru->ri_logical_writes = get_task_logical_writes(p->task);
+ ru->ri_lifetime_max_phys_footprint = get_task_phys_footprint_lifetime_max(p->task);
+ fill_task_monotonic_rusage(p->task, ru);
+ /* fall through */
case RUSAGE_INFO_V3:
fill_task_qos_rusage(p->task, ru);
}
}
-static void
-rusage_info_conversion(rusage_info_t ri_info, rusage_info_current *ri_current, int flavor)
-{
- struct rusage_info_v0 *ri_v0;
- struct rusage_info_v1 *ri_v1;
- struct rusage_info_v2 *ri_v2;
-
- switch (flavor) {
-
- case RUSAGE_INFO_V2:
- ri_v2 = (struct rusage_info_v2 *)ri_info;
- ri_v2->ri_diskio_bytesread = ri_current->ri_diskio_bytesread;
- ri_v2->ri_diskio_byteswritten = ri_current->ri_diskio_byteswritten;
- /* fall through */
-
- case RUSAGE_INFO_V1:
- ri_v1 = (struct rusage_info_v1 *)ri_info;
- ri_v1->ri_child_user_time = ri_current->ri_child_user_time;
- ri_v1->ri_child_system_time = ri_current->ri_child_system_time;
- ri_v1->ri_child_pkg_idle_wkups = ri_current->ri_child_pkg_idle_wkups;
- ri_v1->ri_child_interrupt_wkups = ri_current->ri_child_interrupt_wkups;
- ri_v1->ri_child_pageins = ri_current->ri_child_pageins;
- ri_v1->ri_child_elapsed_abstime = ri_current->ri_child_elapsed_abstime;
- /* fall through */
-
- case RUSAGE_INFO_V0:
- ri_v0 = (struct rusage_info_v0 *)ri_info;
- memcpy(&ri_v0->ri_uuid[0], &ri_current->ri_uuid[0], sizeof(ri_v0->ri_uuid));
- ri_v0->ri_user_time = ri_current->ri_user_time;
- ri_v0->ri_system_time = ri_current->ri_system_time;
- ri_v0->ri_pkg_idle_wkups = ri_current->ri_pkg_idle_wkups;
- ri_v0->ri_interrupt_wkups = ri_current->ri_interrupt_wkups;
- ri_v0->ri_pageins = ri_current->ri_pageins;
- ri_v0->ri_wired_size = ri_current->ri_wired_size;
- ri_v0->ri_resident_size = ri_current->ri_resident_size;
- ri_v0->ri_phys_footprint = ri_current->ri_phys_footprint;
- ri_v0->ri_proc_start_abstime = ri_current->ri_proc_start_abstime;
- ri_v0->ri_proc_exit_abstime = ri_current->ri_proc_exit_abstime;
-
- break;
-
- default:
- break;
- }
-}
-
-
int
proc_get_rusage(proc_t p, int flavor, user_addr_t buffer, __unused int is_zombie)
{
- struct rusage_info_v0 ri_v0;
- struct rusage_info_v1 ri_v1;
- struct rusage_info_v2 ri_v2;
- struct rusage_info_v3 ri_v3;
-
rusage_info_current ri_current;
int error = 0;
+ size_t size = 0;
switch (flavor) {
case RUSAGE_INFO_V0:
- /*
- * If task is still alive, collect info from the live task itself.
- * Otherwise, look to the cached info in the zombie proc.
- */
- if (p->p_ru == NULL) {
- gather_rusage_info(p, &ri_current, flavor);
- ri_current.ri_proc_exit_abstime = 0;
- rusage_info_conversion(&ri_v0, &ri_current, flavor);
- } else {
- rusage_info_conversion(&ri_v0, &p->p_ru->ri, flavor);
- }
- error = copyout(&ri_v0, buffer, sizeof (ri_v0));
+ size = sizeof(struct rusage_info_v0);
break;
case RUSAGE_INFO_V1:
- /*
- * If task is still alive, collect info from the live task itself.
- * Otherwise, look to the cached info in the zombie proc.
- */
- if (p->p_ru == NULL) {
- gather_rusage_info(p, &ri_current, flavor);
- ri_current.ri_proc_exit_abstime = 0;
- rusage_info_conversion(&ri_v1, &ri_current, flavor);
- } else {
- rusage_info_conversion(&ri_v1, &p->p_ru->ri, flavor);
- }
- error = copyout(&ri_v1, buffer, sizeof (ri_v1));
+ size = sizeof(struct rusage_info_v1);
break;
case RUSAGE_INFO_V2:
- /*
- * If task is still alive, collect info from the live task itself.
- * Otherwise, look to the cached info in the zombie proc.
- */
- if (p->p_ru == NULL) {
- gather_rusage_info(p, &ri_current, flavor);
- ri_current.ri_proc_exit_abstime = 0;
- rusage_info_conversion(&ri_v2, &ri_current, flavor);
- } else {
- rusage_info_conversion(&ri_v2, &p->p_ru->ri, flavor);
- }
- error = copyout(&ri_v2, buffer, sizeof (ri_v2));
+ size = sizeof(struct rusage_info_v2);
break;
case RUSAGE_INFO_V3:
- /*
- * If task is still alive, collect info from the live task itself.
- * Otherwise, look to the cached info in the zombie proc.
- */
- if (p->p_ru == NULL) {
- gather_rusage_info(p, &ri_v3, flavor);
- ri_v3.ri_proc_exit_abstime = 0;
- } else {
- ri_v3 = p->p_ru->ri;
- }
- error = copyout(&ri_v3, buffer, sizeof (ri_v3));
+ size = sizeof(struct rusage_info_v3);
break;
- default:
- error = EINVAL;
+ case RUSAGE_INFO_V4:
+ size = sizeof(struct rusage_info_v4);
break;
+
+ default:
+ return EINVAL;
+ }
+
+ if(size == 0) {
+ return EINVAL;
}
- return (error);
+ /*
+ * If task is still alive, collect info from the live task itself.
+ * Otherwise, look to the cached info in the zombie proc.
+ */
+ if (p->p_ru == NULL) {
+ gather_rusage_info(p, &ri_current, flavor);
+ ri_current.ri_proc_exit_abstime = 0;
+ error = copyout(&ri_current, buffer, size);
+ } else {
+ ri_current = p->p_ru->ri;
+ error = copyout(&p->p_ru->ri, buffer, size);
+ }
+
+ return (error);
}
static int
return (0);
}
+
+#if !MONOTONIC
+int thread_selfcounts(__unused struct proc *p, __unused struct thread_selfcounts_args *uap, __unused int *ret_out)
+{
+ return ENOTSUP;
+}
+#endif /* !MONOTONIC */