예제 #1
0
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);
}
예제 #2
0
/*
 * 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);
}