static int pset_bind_thread(kthread_t *tp, psetid_t pset, psetid_t *oldpset, void *projbuf, void *zonebuf) { int error = 0; ASSERT(pool_lock_held()); ASSERT(MUTEX_HELD(&cpu_lock)); ASSERT(MUTEX_HELD(&ttoproc(tp)->p_lock)); *oldpset = tp->t_bind_pset; switch (pset) { case PS_SOFT: TB_PSET_SOFT_SET(tp); break; case PS_HARD: TB_PSET_HARD_SET(tp); break; case PS_QUERY: break; case PS_QUERY_TYPE: *oldpset = TB_PSET_IS_SOFT(tp) ? PS_SOFT : PS_HARD; break; default: /* * Must have the same UID as the target process or * have PRIV_PROC_OWNER privilege. */ if (!hasprocperm(tp->t_cred, CRED())) return (EPERM); /* * Unbinding of an unbound thread should always succeed. */ if (*oldpset == PS_NONE && pset == PS_NONE) return (0); /* * Only privileged processes can move threads from psets with * PSET_NOESCAPE attribute. */ if ((tp->t_cpupart->cp_attr & PSET_NOESCAPE) && secpolicy_pset(CRED()) != 0) return (EPERM); if ((error = cpupart_bind_thread(tp, pset, 0, projbuf, zonebuf)) == 0) tp->t_bind_pset = pset; break; } return (error); }
/* * Move threads from specified partition to cp_default. If `force' is specified, * move all threads, otherwise move only soft-bound threads. */ static int cpupart_unbind_threads(cpupart_t *pp, boolean_t unbind_all) { void *projbuf, *zonebuf; kthread_t *t; proc_t *p; int err = 0; psetid_t psid = pp->cp_id; ASSERT(pool_lock_held()); ASSERT(MUTEX_HELD(&cpu_lock)); if (pp == NULL || pp == &cp_default) { return (EINVAL); } /* * Pre-allocate enough buffers for FSS for all active projects and * for all active zones on the system. Unused buffers will be * freed later by fss_freebuf(). */ projbuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_PROJ); zonebuf = fss_allocbuf(FSS_NPROJ_BUF, FSS_ALLOC_ZONE); mutex_enter(&pidlock); t = curthread; do { if (t->t_bind_pset == psid) { again: p = ttoproc(t); mutex_enter(&p->p_lock); if (ttoproc(t) != p) { /* * lwp_exit has changed this thread's process * pointer before we grabbed its p_lock. */ mutex_exit(&p->p_lock); goto again; } /* * Can only unbind threads which have revocable binding * unless force unbinding requested. */ if (unbind_all || TB_PSET_IS_SOFT(t)) { err = cpupart_bind_thread(t, PS_NONE, 1, projbuf, zonebuf); if (err) { mutex_exit(&p->p_lock); mutex_exit(&pidlock); fss_freebuf(projbuf, FSS_ALLOC_PROJ); fss_freebuf(zonebuf, FSS_ALLOC_ZONE); return (err); } t->t_bind_pset = PS_NONE; } mutex_exit(&p->p_lock); } t = t->t_next; } while (t != curthread); mutex_exit(&pidlock); fss_freebuf(projbuf, FSS_ALLOC_PROJ); fss_freebuf(zonebuf, FSS_ALLOC_ZONE); return (err); }