]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/sys_generic.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / kern / sys_generic.c
index 77b32e3d47405bce68a3c2cd6c1ffd5fd7562aaf..1d88f75a81ce811fde65f7977e631e6c93065793 100644 (file)
 
 /* for entitlement check */
 #include <IOKit/IOBSD.h>
+/*
+ * 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 <pexpert/pexpert.h>
 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;