sys/kern/kern_plimit.c
struct plimit *
plimit_fork(struct proc *p1)
{
	struct plimit *olimit = p1->p_limit;
	struct plimit *nlimit = NULL;
	struct plimit *rlimit;

	/*
	 * If we are exclusive (but not threaded-exclusive), but have only
	 * one reference, we can convert the structure to copy-on-write
	 * again.
	 *
	 * If we were threaded but are no longer threaded we can do the same
	 * thing.
	 */
	if (olimit->p_exclusive == 1) {
		KKASSERT(olimit->p_refcnt == 1);
		olimit->p_exclusive = 0;
	} else if (olimit->p_exclusive == 2 && p1->p_nthreads == 1) {
		KKASSERT(olimit->p_refcnt == 1);
		olimit->p_exclusive = 0;
	}

	/*
	 * Take a short-cut that requires limited spin locks.  If we aren't
	 * exclusive we will not be threaded and we can just bump the ref
	 * count.  If that is true and we also have only one ref then there
	 * can be no other accessors.
	 */
	if (olimit->p_exclusive == 0) {
		if (olimit->p_refcnt == 1) {
			++olimit->p_refcnt;
		} else {
			spin_lock(&olimit->p_spin);
			++olimit->p_refcnt;
			spin_unlock(&olimit->p_spin);
		}
		return(olimit);
	}

	/*
	 * Full-blown code-up.
	 */
	nlimit = NULL;
	spin_lock(&olimit->p_spin);

	for (;;) {
		if (olimit->p_exclusive == 0) {
			++olimit->p_refcnt;
			rlimit = olimit;
			break;
		}
		if (nlimit) {
			plimit_copy(olimit, nlimit);
			rlimit = nlimit;
			nlimit = NULL;
			break;
		}
		spin_unlock(&olimit->p_spin);
		nlimit = kmalloc(sizeof(*nlimit), M_SUBPROC, M_WAITOK);
		spin_lock(&olimit->p_spin);
	}
	spin_unlock(&olimit->p_spin);
	if (nlimit)
		kfree(nlimit, M_SUBPROC);
	return(rlimit);
}
/*
 * Return a plimit for use by a new forked process given the one
 * contained in the parent process.
 *
 * MPSAFE
 */
Return a plimit for use by a new forked process given the one
contained in the parent process.

MPSAFE
Return a plimit for use by a new forked process given the one contained in the parent process . MPSAFE
struct plimit *
plimit_fork(struct proc *p1)
{
	struct plimit *olimit = p1->p_limit;
	struct plimit *nlimit = NULL;
	struct plimit *rlimit;
	if (olimit->p_exclusive == 1) {
		KKASSERT(olimit->p_refcnt == 1);
		olimit->p_exclusive = 0;
	} else if (olimit->p_exclusive == 2 && p1->p_nthreads == 1) {
		KKASSERT(olimit->p_refcnt == 1);
		olimit->p_exclusive = 0;
	}
	if (olimit->p_exclusive == 0) {
		if (olimit->p_refcnt == 1) {
			++olimit->p_refcnt;
		} else {
			spin_lock(&olimit->p_spin);
			++olimit->p_refcnt;
			spin_unlock(&olimit->p_spin);
		}
		return(olimit);
	}
	nlimit = NULL;
	spin_lock(&olimit->p_spin);
	for (;;) {
		if (olimit->p_exclusive == 0) {
			++olimit->p_refcnt;
			rlimit = olimit;
			break;
		}
		if (nlimit) {
			plimit_copy(olimit, nlimit);
			rlimit = nlimit;
			nlimit = NULL;
			break;
		}
		spin_unlock(&olimit->p_spin);
		nlimit = kmalloc(sizeof(*nlimit), M_SUBPROC, M_WAITOK);
		spin_lock(&olimit->p_spin);
	}
	spin_unlock(&olimit->p_spin);
	if (nlimit)
		kfree(nlimit, M_SUBPROC);
	return(rlimit);
}
struct plimit * plimit_fork ( struct proc * p1 ) { struct plimit * olimit = p1 -> p_limit ; struct plimit * nlimit = NULL ; struct plimit * rlimit ; if ( olimit -> p_exclusive == 1 ) { KKASSERT ( olimit -> p_refcnt == 1 ) ; olimit -> p_exclusive = 0 ; } else if ( olimit -> p_exclusive == 2 && p1 -> p_nthreads == 1 ) { KKASSERT ( olimit -> p_refcnt == 1 ) ; olimit -> p_exclusive = 0 ; } if ( olimit -> p_exclusive == 0 ) { if ( olimit -> p_refcnt == 1 ) { ++ olimit -> p_refcnt ; } else { spin_lock ( & olimit -> p_spin ) ; ++ olimit -> p_refcnt ; spin_unlock ( & olimit -> p_spin ) ; } return ( olimit ) ; } nlimit = NULL ; spin_lock ( & olimit -> p_spin ) ; for ( ; ; ) { if ( olimit -> p_exclusive == 0 ) { ++ olimit -> p_refcnt ; rlimit = olimit ; break ; } if ( nlimit ) { plimit_copy ( olimit , nlimit ) ; rlimit = nlimit ; nlimit = NULL ; break ; } spin_unlock ( & olimit -> p_spin ) ; nlimit = kmalloc ( sizeof ( * nlimit ) , M_SUBPROC , M_WAITOK ) ; spin_lock ( & olimit -> p_spin ) ; } spin_unlock ( & olimit -> p_spin ) ; if ( nlimit ) kfree ( nlimit , M_SUBPROC ) ; return ( rlimit ) ; }
Return a plimit for use by a new forked process given the one
 contained in the parent process.
Return a plimit for use by a new forked process given the one contained in the parent process .
/*
	 * If we are exclusive (but not threaded-exclusive), but have only
	 * one reference, we can convert the structure to copy-on-write
	 * again.
	 *
	 * If we were threaded but are no longer threaded we can do the same
	 * thing.
	 */ /*
	 * Take a short-cut that requires limited spin locks.  If we aren't
	 * exclusive we will not be threaded and we can just bump the ref
	 * count.  If that is true and we also have only one ref then there
	 * can be no other accessors.
	 */ /*
	 * Full-blown code-up.
	 */