X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/a991bd8d3e7fe02dbca0644054bab73c5b75324a..HEAD:/bsd/kern/sys_generic.c diff --git a/bsd/kern/sys_generic.c b/bsd/kern/sys_generic.c index 77b32e3d4..1d88f75a8 100644 --- a/bsd/kern/sys_generic.c +++ b/bsd/kern/sys_generic.c @@ -152,6 +152,11 @@ /* for entitlement check */ #include +/* + * If you need accounting for KM_SELECT consider using + * KALLOC_HEAP_DEFINE to define a view. + */ +#define KM_SELECT KHEAP_DEFAULT /* XXX should be in a header file somewhere */ extern kern_return_t IOBSDGetPlatformUUID(__darwin_uuid_t uuid, mach_timespec_t timeoutp); @@ -1210,6 +1215,36 @@ pselect_nocancel(struct proc *p, struct pselect_nocancel_args *uap, int32_t *ret return err; } +void +select_cleanup_uthread(struct _select *sel) +{ + kheap_free(KHEAP_DATA_BUFFERS, sel->ibits, 2 * sel->nbytes); + sel->ibits = sel->obits = NULL; + sel->nbytes = 0; +} + +static int +select_grow_uthread_cache(struct _select *sel, uint32_t nbytes) +{ + uint32_t *buf; + + buf = kheap_alloc(KHEAP_DATA_BUFFERS, 2 * nbytes, Z_WAITOK | Z_ZERO); + if (buf) { + select_cleanup_uthread(sel); + sel->ibits = buf; + sel->obits = buf + nbytes / sizeof(uint32_t); + sel->nbytes = nbytes; + return true; + } + return false; +} + +static void +select_bzero_uthread_cache(struct _select *sel) +{ + bzero(sel->ibits, sel->nbytes * 2); +} + /* * Generic implementation of {,p}select. Care: we type-pun uap across the two * syscalls, which differ slightly. The first 4 arguments (nfds and the fd sets) @@ -1226,7 +1261,6 @@ select_internal(struct proc *p, struct select_nocancel_args *uap, uint64_t timeo struct uthread *uth; struct _select *sel; struct _select_data *seldata; - int needzerofill = 1; int count = 0; size_t sz = 0; @@ -1266,35 +1300,11 @@ select_internal(struct proc *p, struct select_nocancel_args *uap, uint64_t timeo * it is not a POSIX compliant error code for select(). */ if (sel->nbytes < (3 * ni)) { - int nbytes = 3 * ni; - - /* Free previous allocation, if any */ - if (sel->ibits != NULL) { - FREE(sel->ibits, M_TEMP); - } - if (sel->obits != NULL) { - FREE(sel->obits, M_TEMP); - /* NULL out; subsequent ibits allocation may fail */ - sel->obits = NULL; - } - - MALLOC(sel->ibits, u_int32_t *, nbytes, M_TEMP, M_WAITOK | M_ZERO); - if (sel->ibits == NULL) { - return EAGAIN; - } - MALLOC(sel->obits, u_int32_t *, nbytes, M_TEMP, M_WAITOK | M_ZERO); - if (sel->obits == NULL) { - FREE(sel->ibits, M_TEMP); - sel->ibits = NULL; + if (!select_grow_uthread_cache(sel, 3 * ni)) { return EAGAIN; } - sel->nbytes = nbytes; - needzerofill = 0; - } - - if (needzerofill) { - bzero((caddr_t)sel->ibits, sel->nbytes); - bzero((caddr_t)sel->obits, sel->nbytes); + } else { + select_bzero_uthread_cache(sel); } /* @@ -1347,14 +1357,14 @@ select_internal(struct proc *p, struct select_nocancel_args *uap, uint64_t timeo if (waitq_set_is_valid(uth->uu_wqset)) { waitq_set_deinit(uth->uu_wqset); } - FREE(uth->uu_wqset, M_SELECT); + kheap_free(KM_SELECT, uth->uu_wqset, uth->uu_wqstate_sz); } else if (uth->uu_wqstate_sz && !uth->uu_wqset) { panic("select: thread structure corrupt! " "uu_wqstate_sz:%ld, wqstate_buf == NULL", uth->uu_wqstate_sz); } uth->uu_wqstate_sz = sz; - MALLOC(uth->uu_wqset, struct waitq_set *, sz, M_SELECT, M_WAITOK); + uth->uu_wqset = kheap_alloc(KM_SELECT, sz, Z_WAITOK); if (!uth->uu_wqset) { panic("can't allocate %ld bytes for wqstate buffer", uth->uu_wqstate_sz); @@ -1834,6 +1844,7 @@ poll_nocancel(struct proc *p, struct poll_nocancel_args *uap, int32_t *retval) u_int nfds = uap->nfds; u_int rfds = 0; rlim_t nofile = proc_limitgetcur(p, RLIMIT_NOFILE, TRUE); + size_t ni = nfds * sizeof(struct pollfd); /* * This is kinda bogus. We have fd limits, but that is not @@ -1853,8 +1864,7 @@ poll_nocancel(struct proc *p, struct poll_nocancel_args *uap, int32_t *retval) } if (nfds) { - size_t ni = nfds * sizeof(struct pollfd); - MALLOC(fds, struct pollfd *, ni, M_TEMP, M_WAITOK); + fds = kheap_alloc(KHEAP_TEMP, ni, Z_WAITOK); if (NULL == fds) { error = EAGAIN; goto out; @@ -1979,9 +1989,7 @@ done: } out: - if (NULL != fds) { - FREE(fds, M_TEMP); - } + kheap_free(KHEAP_TEMP, fds, ni); kqueue_dealloc(kq); return error; @@ -3231,15 +3239,21 @@ SYSCTL_PROC(_machdep_remotetime, OID_AUTO, conversion_params, #endif /* CONFIG_MACH_BRIDGE_RECV_TIME */ #if DEVELOPMENT || DEBUG -#if __AMP__ + #include extern int32_t sysctl_get_bound_cpuid(void); -extern void sysctl_thread_bind_cpuid(int32_t cpuid); +extern kern_return_t sysctl_thread_bind_cpuid(int32_t cpuid); static int sysctl_kern_sched_thread_bind_cpu SYSCTL_HANDLER_ARGS { #pragma unused(oidp, arg1, arg2) + /* + * DO NOT remove this bootarg guard or make this non-development. + * This kind of binding should only be used for tests and + * experiments in a custom configuration, never shipping code. + */ + if (!PE_parse_boot_argn("enable_skstb", NULL, 0)) { return ENOENT; } @@ -3254,7 +3268,15 @@ sysctl_kern_sched_thread_bind_cpu SYSCTL_HANDLER_ARGS } if (changed) { - sysctl_thread_bind_cpuid(new_value); + kern_return_t kr = sysctl_thread_bind_cpuid(new_value); + + if (kr == KERN_NOT_SUPPORTED) { + return ENOTSUP; + } + + if (kr == KERN_INVALID_VALUE) { + return ERANGE; + } } return error; @@ -3263,6 +3285,7 @@ sysctl_kern_sched_thread_bind_cpu SYSCTL_HANDLER_ARGS SYSCTL_PROC(_kern, OID_AUTO, sched_thread_bind_cpu, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_kern_sched_thread_bind_cpu, "I", ""); +#if __AMP__ extern char sysctl_get_bound_cluster_type(void); extern void sysctl_thread_bind_cluster_type(char cluster_type); static int @@ -3404,6 +3427,12 @@ SYSCTL_INT(_kern, OID_AUTO, sched_edge_migrate_ipi_immediate, CTLFLAG_RW | CTLFL #endif /* CONFIG_SCHED_EDGE */ #endif /* __AMP__ */ + +/* used for testing by exception_tests */ +extern uint32_t ipc_control_port_options; +SYSCTL_INT(_kern, OID_AUTO, ipc_control_port_options, + CTLFLAG_RD | CTLFLAG_LOCKED, &ipc_control_port_options, 0, ""); + #endif /* DEVELOPMENT || DEBUG */ extern uint32_t task_exc_guard_default;