/*
 * Return loginclass structure with a corresponding name.  Not
 * performance critical, as it's used mainly by setloginclass(2),
 * which happens once per login session.  Caller has to use
 * loginclass_free() on the returned value when it's no longer
 * needed.
 */
struct loginclass *
loginclass_find(const char *name)
{
	struct loginclass *lc, *new_lc;

	if (name[0] == '\0' || strlen(name) >= MAXLOGNAME)
		return (NULL);

	lc = curthread->td_ucred->cr_loginclass;
	if (strcmp(name, lc->lc_name) == 0) {
		loginclass_hold(lc);
		return (lc);
	}

	rw_rlock(&loginclasses_lock);
	lc = loginclass_lookup(name);
	rw_runlock(&loginclasses_lock);
	if (lc != NULL)
		return (lc);

	new_lc = malloc(sizeof(*new_lc), M_LOGINCLASS, M_ZERO | M_WAITOK);
	racct_create(&new_lc->lc_racct);
	refcount_init(&new_lc->lc_refcount, 1);
	strcpy(new_lc->lc_name, name);

	rw_wlock(&loginclasses_lock);
	/*
	 * There's a chance someone created our loginclass while we
	 * were in malloc and not holding the lock, so we have to
	 * make sure we don't insert a duplicate loginclass.
	 */
	if ((lc = loginclass_lookup(name)) == NULL) {
		LIST_INSERT_HEAD(&loginclasses, new_lc, lc_next);
		rw_wunlock(&loginclasses_lock);
		lc = new_lc;
	} else {
		rw_wunlock(&loginclasses_lock);
		racct_destroy(&new_lc->lc_racct);
		free(new_lc, M_LOGINCLASS);
	}

	return (lc);
}
void
loginclass_free(struct loginclass *lc)
{

	if (refcount_release_if_not_last(&lc->lc_refcount))
		return;

	rw_wlock(&loginclasses_lock);
	if (!refcount_release(&lc->lc_refcount)) {
		rw_wunlock(&loginclasses_lock);
		return;
	}

	racct_destroy(&lc->lc_racct);
	LIST_REMOVE(lc, lc_next);
	rw_wunlock(&loginclasses_lock);

	free(lc, M_LOGINCLASS);
}
Esempio n. 3
0
void
loginclass_free(struct loginclass *lc)
{
	int old;

	old = lc->lc_refcount;
	if (old > 1 && atomic_cmpset_int(&lc->lc_refcount, old, old - 1))
		return;

	rw_wlock(&loginclasses_lock);
	if (!refcount_release(&lc->lc_refcount)) {
		rw_wunlock(&loginclasses_lock);
		return;
	}

	racct_destroy(&lc->lc_racct);
	LIST_REMOVE(lc, lc_next);
	rw_wunlock(&loginclasses_lock);

	free(lc, M_LOGINCLASS);
}
Esempio n. 4
0
void
racct_proc_exit(struct proc *p)
{
	int i;
	uint64_t runtime;

	PROC_LOCK(p);
	/*
	 * We don't need to calculate rux, proc_reap() has already done this.
	 */
	runtime = cputick2usec(p->p_rux.rux_runtime);
#ifdef notyet
	KASSERT(runtime >= p->p_prev_runtime, ("runtime < p_prev_runtime"));
#else
	if (runtime < p->p_prev_runtime)
		runtime = p->p_prev_runtime;
#endif
	mtx_lock(&racct_lock);
	racct_set_locked(p, RACCT_CPU, runtime);

	for (i = 0; i <= RACCT_MAX; i++) {
		if (p->p_racct->r_resources[i] == 0)
			continue;
	    	if (!RACCT_IS_RECLAIMABLE(i))
			continue;
		racct_set_locked(p, i, 0);
	}

	mtx_unlock(&racct_lock);
	PROC_UNLOCK(p);

#ifdef RCTL
	rctl_racct_release(p->p_racct);
#endif
	racct_destroy(&p->p_racct);
}