The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_resource.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * (c) UNIX System Laboratories, Inc.
    5  * All or some portions of this file are derived from material licensed
    6  * to the University of California by American Telephone and Telegraph
    7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    8  * the permission of UNIX System Laboratories, Inc.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)kern_resource.c     8.5 (Berkeley) 1/21/94
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/8.1/sys/kern/kern_resource.c 208580 2010-05-26 19:26:28Z kib $");
   39 
   40 #include "opt_compat.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/sysproto.h>
   45 #include <sys/file.h>
   46 #include <sys/kernel.h>
   47 #include <sys/lock.h>
   48 #include <sys/malloc.h>
   49 #include <sys/mutex.h>
   50 #include <sys/priv.h>
   51 #include <sys/proc.h>
   52 #include <sys/refcount.h>
   53 #include <sys/resourcevar.h>
   54 #include <sys/rwlock.h>
   55 #include <sys/sched.h>
   56 #include <sys/sx.h>
   57 #include <sys/syscallsubr.h>
   58 #include <sys/sysent.h>
   59 #include <sys/time.h>
   60 #include <sys/umtx.h>
   61 
   62 #include <vm/vm.h>
   63 #include <vm/vm_param.h>
   64 #include <vm/pmap.h>
   65 #include <vm/vm_map.h>
   66 
   67 
   68 static MALLOC_DEFINE(M_PLIMIT, "plimit", "plimit structures");
   69 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures");
   70 #define UIHASH(uid)     (&uihashtbl[(uid) & uihash])
   71 static struct rwlock uihashtbl_lock;
   72 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
   73 static u_long uihash;           /* size of hash table - 1 */
   74 
   75 static void     calcru1(struct proc *p, struct rusage_ext *ruxp,
   76                     struct timeval *up, struct timeval *sp);
   77 static int      donice(struct thread *td, struct proc *chgp, int n);
   78 static struct uidinfo *uilookup(uid_t uid);
   79 static void     ruxagg_locked(struct rusage_ext *rux, struct thread *td);
   80 
   81 /*
   82  * Resource controls and accounting.
   83  */
   84 #ifndef _SYS_SYSPROTO_H_
   85 struct getpriority_args {
   86         int     which;
   87         int     who;
   88 };
   89 #endif
   90 int
   91 getpriority(td, uap)
   92         struct thread *td;
   93         register struct getpriority_args *uap;
   94 {
   95         struct proc *p;
   96         struct pgrp *pg;
   97         int error, low;
   98 
   99         error = 0;
  100         low = PRIO_MAX + 1;
  101         switch (uap->which) {
  102 
  103         case PRIO_PROCESS:
  104                 if (uap->who == 0)
  105                         low = td->td_proc->p_nice;
  106                 else {
  107                         p = pfind(uap->who);
  108                         if (p == NULL)
  109                                 break;
  110                         if (p_cansee(td, p) == 0)
  111                                 low = p->p_nice;
  112                         PROC_UNLOCK(p);
  113                 }
  114                 break;
  115 
  116         case PRIO_PGRP:
  117                 sx_slock(&proctree_lock);
  118                 if (uap->who == 0) {
  119                         pg = td->td_proc->p_pgrp;
  120                         PGRP_LOCK(pg);
  121                 } else {
  122                         pg = pgfind(uap->who);
  123                         if (pg == NULL) {
  124                                 sx_sunlock(&proctree_lock);
  125                                 break;
  126                         }
  127                 }
  128                 sx_sunlock(&proctree_lock);
  129                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  130                         PROC_LOCK(p);
  131                         if (p_cansee(td, p) == 0) {
  132                                 if (p->p_nice < low)
  133                                         low = p->p_nice;
  134                         }
  135                         PROC_UNLOCK(p);
  136                 }
  137                 PGRP_UNLOCK(pg);
  138                 break;
  139 
  140         case PRIO_USER:
  141                 if (uap->who == 0)
  142                         uap->who = td->td_ucred->cr_uid;
  143                 sx_slock(&allproc_lock);
  144                 FOREACH_PROC_IN_SYSTEM(p) {
  145                         /* Do not bother to check PRS_NEW processes */
  146                         if (p->p_state == PRS_NEW)
  147                                 continue;
  148                         PROC_LOCK(p);
  149                         if (p_cansee(td, p) == 0 &&
  150                             p->p_ucred->cr_uid == uap->who) {
  151                                 if (p->p_nice < low)
  152                                         low = p->p_nice;
  153                         }
  154                         PROC_UNLOCK(p);
  155                 }
  156                 sx_sunlock(&allproc_lock);
  157                 break;
  158 
  159         default:
  160                 error = EINVAL;
  161                 break;
  162         }
  163         if (low == PRIO_MAX + 1 && error == 0)
  164                 error = ESRCH;
  165         td->td_retval[0] = low;
  166         return (error);
  167 }
  168 
  169 #ifndef _SYS_SYSPROTO_H_
  170 struct setpriority_args {
  171         int     which;
  172         int     who;
  173         int     prio;
  174 };
  175 #endif
  176 int
  177 setpriority(td, uap)
  178         struct thread *td;
  179         struct setpriority_args *uap;
  180 {
  181         struct proc *curp, *p;
  182         struct pgrp *pg;
  183         int found = 0, error = 0;
  184 
  185         curp = td->td_proc;
  186         switch (uap->which) {
  187         case PRIO_PROCESS:
  188                 if (uap->who == 0) {
  189                         PROC_LOCK(curp);
  190                         error = donice(td, curp, uap->prio);
  191                         PROC_UNLOCK(curp);
  192                 } else {
  193                         p = pfind(uap->who);
  194                         if (p == NULL)
  195                                 break;
  196                         error = p_cansee(td, p);
  197                         if (error == 0)
  198                                 error = donice(td, p, uap->prio);
  199                         PROC_UNLOCK(p);
  200                 }
  201                 found++;
  202                 break;
  203 
  204         case PRIO_PGRP:
  205                 sx_slock(&proctree_lock);
  206                 if (uap->who == 0) {
  207                         pg = curp->p_pgrp;
  208                         PGRP_LOCK(pg);
  209                 } else {
  210                         pg = pgfind(uap->who);
  211                         if (pg == NULL) {
  212                                 sx_sunlock(&proctree_lock);
  213                                 break;
  214                         }
  215                 }
  216                 sx_sunlock(&proctree_lock);
  217                 LIST_FOREACH(p, &pg->pg_members, p_pglist) {
  218                         PROC_LOCK(p);
  219                         if (p_cansee(td, p) == 0) {
  220                                 error = donice(td, p, uap->prio);
  221                                 found++;
  222                         }
  223                         PROC_UNLOCK(p);
  224                 }
  225                 PGRP_UNLOCK(pg);
  226                 break;
  227 
  228         case PRIO_USER:
  229                 if (uap->who == 0)
  230                         uap->who = td->td_ucred->cr_uid;
  231                 sx_slock(&allproc_lock);
  232                 FOREACH_PROC_IN_SYSTEM(p) {
  233                         PROC_LOCK(p);
  234                         if (p->p_ucred->cr_uid == uap->who &&
  235                             p_cansee(td, p) == 0) {
  236                                 error = donice(td, p, uap->prio);
  237                                 found++;
  238                         }
  239                         PROC_UNLOCK(p);
  240                 }
  241                 sx_sunlock(&allproc_lock);
  242                 break;
  243 
  244         default:
  245                 error = EINVAL;
  246                 break;
  247         }
  248         if (found == 0 && error == 0)
  249                 error = ESRCH;
  250         return (error);
  251 }
  252 
  253 /*
  254  * Set "nice" for a (whole) process.
  255  */
  256 static int
  257 donice(struct thread *td, struct proc *p, int n)
  258 {
  259         int error;
  260 
  261         PROC_LOCK_ASSERT(p, MA_OWNED);
  262         if ((error = p_cansched(td, p)))
  263                 return (error);
  264         if (n > PRIO_MAX)
  265                 n = PRIO_MAX;
  266         if (n < PRIO_MIN)
  267                 n = PRIO_MIN;
  268         if (n < p->p_nice && priv_check(td, PRIV_SCHED_SETPRIORITY) != 0)
  269                 return (EACCES);
  270         sched_nice(p, n);
  271         return (0);
  272 }
  273 
  274 /*
  275  * Set realtime priority for LWP.
  276  */
  277 #ifndef _SYS_SYSPROTO_H_
  278 struct rtprio_thread_args {
  279         int             function;
  280         lwpid_t         lwpid;
  281         struct rtprio   *rtp;
  282 };
  283 #endif
  284 int
  285 rtprio_thread(struct thread *td, struct rtprio_thread_args *uap)
  286 {
  287         struct proc *p;
  288         struct rtprio rtp;
  289         struct thread *td1;
  290         int cierror, error;
  291 
  292         /* Perform copyin before acquiring locks if needed. */
  293         if (uap->function == RTP_SET)
  294                 cierror = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
  295         else
  296                 cierror = 0;
  297 
  298         /*
  299          * Though lwpid is unique, only current process is supported
  300          * since there is no efficient way to look up a LWP yet.
  301          */
  302         p = td->td_proc;
  303         PROC_LOCK(p);
  304 
  305         switch (uap->function) {
  306         case RTP_LOOKUP:
  307                 if ((error = p_cansee(td, p)))
  308                         break;
  309                 if (uap->lwpid == 0 || uap->lwpid == td->td_tid)
  310                         td1 = td;
  311                 else
  312                         td1 = thread_find(p, uap->lwpid);
  313                 if (td1 != NULL)
  314                         pri_to_rtp(td1, &rtp);
  315                 else
  316                         error = ESRCH;
  317                 PROC_UNLOCK(p);
  318                 return (copyout(&rtp, uap->rtp, sizeof(struct rtprio)));
  319         case RTP_SET:
  320                 if ((error = p_cansched(td, p)) || (error = cierror))
  321                         break;
  322 
  323                 /* Disallow setting rtprio in most cases if not superuser. */
  324 /*
  325  * Realtime priority has to be restricted for reasons which should be
  326  * obvious.  However, for idle priority, there is a potential for
  327  * system deadlock if an idleprio process gains a lock on a resource
  328  * that other processes need (and the idleprio process can't run
  329  * due to a CPU-bound normal process).  Fix me!  XXX
  330  */
  331 #if 0
  332                 if (RTP_PRIO_IS_REALTIME(rtp.type)) {
  333 #else
  334                 if (rtp.type != RTP_PRIO_NORMAL) {
  335 #endif
  336                         error = priv_check(td, PRIV_SCHED_RTPRIO);
  337                         if (error)
  338                                 break;
  339                 }
  340 
  341                 if (uap->lwpid == 0 || uap->lwpid == td->td_tid)
  342                         td1 = td;
  343                 else
  344                         td1 = thread_find(p, uap->lwpid);
  345                 if (td1 != NULL)
  346                         error = rtp_to_pri(&rtp, td1);
  347                 else
  348                         error = ESRCH;
  349                 break;
  350         default:
  351                 error = EINVAL;
  352                 break;
  353         }
  354         PROC_UNLOCK(p);
  355         return (error);
  356 }
  357 
  358 /*
  359  * Set realtime priority.
  360  */
  361 #ifndef _SYS_SYSPROTO_H_
  362 struct rtprio_args {
  363         int             function;
  364         pid_t           pid;
  365         struct rtprio   *rtp;
  366 };
  367 #endif
  368 int
  369 rtprio(td, uap)
  370         struct thread *td;              /* curthread */
  371         register struct rtprio_args *uap;
  372 {
  373         struct proc *p;
  374         struct thread *tdp;
  375         struct rtprio rtp;
  376         int cierror, error;
  377 
  378         /* Perform copyin before acquiring locks if needed. */
  379         if (uap->function == RTP_SET)
  380                 cierror = copyin(uap->rtp, &rtp, sizeof(struct rtprio));
  381         else
  382                 cierror = 0;
  383 
  384         if (uap->pid == 0) {
  385                 p = td->td_proc;
  386                 PROC_LOCK(p);
  387         } else {
  388                 p = pfind(uap->pid);
  389                 if (p == NULL)
  390                         return (ESRCH);
  391         }
  392 
  393         switch (uap->function) {
  394         case RTP_LOOKUP:
  395                 if ((error = p_cansee(td, p)))
  396                         break;
  397                 /*
  398                  * Return OUR priority if no pid specified,
  399                  * or if one is, report the highest priority
  400                  * in the process.  There isn't much more you can do as
  401                  * there is only room to return a single priority.
  402                  * Note: specifying our own pid is not the same
  403                  * as leaving it zero.
  404                  */
  405                 if (uap->pid == 0) {
  406                         pri_to_rtp(td, &rtp);
  407                 } else {
  408                         struct rtprio rtp2;
  409 
  410                         rtp.type = RTP_PRIO_IDLE;
  411                         rtp.prio = RTP_PRIO_MAX;
  412                         FOREACH_THREAD_IN_PROC(p, tdp) {
  413                                 pri_to_rtp(tdp, &rtp2);
  414                                 if (rtp2.type <  rtp.type ||
  415                                     (rtp2.type == rtp.type &&
  416                                     rtp2.prio < rtp.prio)) {
  417                                         rtp.type = rtp2.type;
  418                                         rtp.prio = rtp2.prio;
  419                                 }
  420                         }
  421                 }
  422                 PROC_UNLOCK(p);
  423                 return (copyout(&rtp, uap->rtp, sizeof(struct rtprio)));
  424         case RTP_SET:
  425                 if ((error = p_cansched(td, p)) || (error = cierror))
  426                         break;
  427 
  428                 /* Disallow setting rtprio in most cases if not superuser. */
  429 /*
  430  * Realtime priority has to be restricted for reasons which should be
  431  * obvious.  However, for idle priority, there is a potential for
  432  * system deadlock if an idleprio process gains a lock on a resource
  433  * that other processes need (and the idleprio process can't run
  434  * due to a CPU-bound normal process).  Fix me!  XXX
  435  */
  436 #if 0
  437                 if (RTP_PRIO_IS_REALTIME(rtp.type)) {
  438 #else
  439                 if (rtp.type != RTP_PRIO_NORMAL) {
  440 #endif
  441                         error = priv_check(td, PRIV_SCHED_RTPRIO);
  442                         if (error)
  443                                 break;
  444                 }
  445 
  446                 /*
  447                  * If we are setting our own priority, set just our
  448                  * thread but if we are doing another process,
  449                  * do all the threads on that process. If we
  450                  * specify our own pid we do the latter.
  451                  */
  452                 if (uap->pid == 0) {
  453                         error = rtp_to_pri(&rtp, td);
  454                 } else {
  455                         FOREACH_THREAD_IN_PROC(p, td) {
  456                                 if ((error = rtp_to_pri(&rtp, td)) != 0)
  457                                         break;
  458                         }
  459                 }
  460                 break;
  461         default:
  462                 error = EINVAL;
  463                 break;
  464         }
  465         PROC_UNLOCK(p);
  466         return (error);
  467 }
  468 
  469 int
  470 rtp_to_pri(struct rtprio *rtp, struct thread *td)
  471 {
  472         u_char  newpri;
  473         u_char  oldpri;
  474 
  475         thread_lock(td);
  476         switch (RTP_PRIO_BASE(rtp->type)) {
  477         case RTP_PRIO_REALTIME:
  478                 if (rtp->prio > RTP_PRIO_MAX) {
  479                         thread_unlock(td);
  480                         return (EINVAL);
  481                 }
  482                 newpri = PRI_MIN_REALTIME + rtp->prio;
  483                 break;
  484         case RTP_PRIO_NORMAL:
  485                 if (rtp->prio >  (PRI_MAX_TIMESHARE - PRI_MIN_TIMESHARE)) {
  486                         thread_unlock(td);
  487                         return (EINVAL);
  488                 }
  489                 newpri = PRI_MIN_TIMESHARE + rtp->prio;
  490                 break;
  491         case RTP_PRIO_IDLE:
  492                 newpri = PRI_MIN_IDLE + rtp->prio;
  493                 break;
  494         default:
  495                 thread_unlock(td);
  496                 return (EINVAL);
  497         }
  498         sched_class(td, rtp->type);     /* XXX fix */
  499         oldpri = td->td_user_pri;
  500         sched_user_prio(td, newpri);
  501         if (curthread == td)
  502                 sched_prio(curthread, td->td_user_pri); /* XXX dubious */
  503         if (TD_ON_UPILOCK(td) && oldpri != newpri) {
  504                 thread_unlock(td);
  505                 umtx_pi_adjust(td, oldpri);
  506         } else
  507                 thread_unlock(td);
  508         return (0);
  509 }
  510 
  511 void
  512 pri_to_rtp(struct thread *td, struct rtprio *rtp)
  513 {
  514 
  515         thread_lock(td);
  516         switch (PRI_BASE(td->td_pri_class)) {
  517         case PRI_REALTIME:
  518                 rtp->prio = td->td_base_user_pri - PRI_MIN_REALTIME;
  519                 break;
  520         case PRI_TIMESHARE:
  521                 rtp->prio = td->td_base_user_pri - PRI_MIN_TIMESHARE;
  522                 break;
  523         case PRI_IDLE:
  524                 rtp->prio = td->td_base_user_pri - PRI_MIN_IDLE;
  525                 break;
  526         default:
  527                 break;
  528         }
  529         rtp->type = td->td_pri_class;
  530         thread_unlock(td);
  531 }
  532 
  533 #if defined(COMPAT_43)
  534 #ifndef _SYS_SYSPROTO_H_
  535 struct osetrlimit_args {
  536         u_int   which;
  537         struct  orlimit *rlp;
  538 };
  539 #endif
  540 int
  541 osetrlimit(td, uap)
  542         struct thread *td;
  543         register struct osetrlimit_args *uap;
  544 {
  545         struct orlimit olim;
  546         struct rlimit lim;
  547         int error;
  548 
  549         if ((error = copyin(uap->rlp, &olim, sizeof(struct orlimit))))
  550                 return (error);
  551         lim.rlim_cur = olim.rlim_cur;
  552         lim.rlim_max = olim.rlim_max;
  553         error = kern_setrlimit(td, uap->which, &lim);
  554         return (error);
  555 }
  556 
  557 #ifndef _SYS_SYSPROTO_H_
  558 struct ogetrlimit_args {
  559         u_int   which;
  560         struct  orlimit *rlp;
  561 };
  562 #endif
  563 int
  564 ogetrlimit(td, uap)
  565         struct thread *td;
  566         register struct ogetrlimit_args *uap;
  567 {
  568         struct orlimit olim;
  569         struct rlimit rl;
  570         struct proc *p;
  571         int error;
  572 
  573         if (uap->which >= RLIM_NLIMITS)
  574                 return (EINVAL);
  575         p = td->td_proc;
  576         PROC_LOCK(p);
  577         lim_rlimit(p, uap->which, &rl);
  578         PROC_UNLOCK(p);
  579 
  580         /*
  581          * XXX would be more correct to convert only RLIM_INFINITY to the
  582          * old RLIM_INFINITY and fail with EOVERFLOW for other larger
  583          * values.  Most 64->32 and 32->16 conversions, including not
  584          * unimportant ones of uids are even more broken than what we
  585          * do here (they blindly truncate).  We don't do this correctly
  586          * here since we have little experience with EOVERFLOW yet.
  587          * Elsewhere, getuid() can't fail...
  588          */
  589         olim.rlim_cur = rl.rlim_cur > 0x7fffffff ? 0x7fffffff : rl.rlim_cur;
  590         olim.rlim_max = rl.rlim_max > 0x7fffffff ? 0x7fffffff : rl.rlim_max;
  591         error = copyout(&olim, uap->rlp, sizeof(olim));
  592         return (error);
  593 }
  594 #endif /* COMPAT_43 */
  595 
  596 #ifndef _SYS_SYSPROTO_H_
  597 struct __setrlimit_args {
  598         u_int   which;
  599         struct  rlimit *rlp;
  600 };
  601 #endif
  602 int
  603 setrlimit(td, uap)
  604         struct thread *td;
  605         register struct __setrlimit_args *uap;
  606 {
  607         struct rlimit alim;
  608         int error;
  609 
  610         if ((error = copyin(uap->rlp, &alim, sizeof(struct rlimit))))
  611                 return (error);
  612         error = kern_setrlimit(td, uap->which, &alim);
  613         return (error);
  614 }
  615 
  616 static void
  617 lim_cb(void *arg)
  618 {
  619         struct rlimit rlim;
  620         struct thread *td;
  621         struct proc *p;
  622 
  623         p = arg;
  624         PROC_LOCK_ASSERT(p, MA_OWNED);
  625         /*
  626          * Check if the process exceeds its cpu resource allocation.  If
  627          * it reaches the max, arrange to kill the process in ast().
  628          */
  629         if (p->p_cpulimit == RLIM_INFINITY)
  630                 return;
  631         PROC_SLOCK(p);
  632         FOREACH_THREAD_IN_PROC(p, td) {
  633                 ruxagg(p, td);
  634         }
  635         PROC_SUNLOCK(p);
  636         if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) {
  637                 lim_rlimit(p, RLIMIT_CPU, &rlim);
  638                 if (p->p_rux.rux_runtime >= rlim.rlim_max * cpu_tickrate()) {
  639                         killproc(p, "exceeded maximum CPU limit");
  640                 } else {
  641                         if (p->p_cpulimit < rlim.rlim_max)
  642                                 p->p_cpulimit += 5;
  643                         psignal(p, SIGXCPU);
  644                 }
  645         }
  646         if ((p->p_flag & P_WEXIT) == 0)
  647                 callout_reset(&p->p_limco, hz, lim_cb, p);
  648 }
  649 
  650 int
  651 kern_setrlimit(td, which, limp)
  652         struct thread *td;
  653         u_int which;
  654         struct rlimit *limp;
  655 {
  656         struct plimit *newlim, *oldlim;
  657         struct proc *p;
  658         register struct rlimit *alimp;
  659         struct rlimit oldssiz;
  660         int error;
  661 
  662         if (which >= RLIM_NLIMITS)
  663                 return (EINVAL);
  664 
  665         /*
  666          * Preserve historical bugs by treating negative limits as unsigned.
  667          */
  668         if (limp->rlim_cur < 0)
  669                 limp->rlim_cur = RLIM_INFINITY;
  670         if (limp->rlim_max < 0)
  671                 limp->rlim_max = RLIM_INFINITY;
  672 
  673         oldssiz.rlim_cur = 0;
  674         p = td->td_proc;
  675         newlim = lim_alloc();
  676         PROC_LOCK(p);
  677         oldlim = p->p_limit;
  678         alimp = &oldlim->pl_rlimit[which];
  679         if (limp->rlim_cur > alimp->rlim_max ||
  680             limp->rlim_max > alimp->rlim_max)
  681                 if ((error = priv_check(td, PRIV_PROC_SETRLIMIT))) {
  682                         PROC_UNLOCK(p);
  683                         lim_free(newlim);
  684                         return (error);
  685                 }
  686         if (limp->rlim_cur > limp->rlim_max)
  687                 limp->rlim_cur = limp->rlim_max;
  688         lim_copy(newlim, oldlim);
  689         alimp = &newlim->pl_rlimit[which];
  690 
  691         switch (which) {
  692 
  693         case RLIMIT_CPU:
  694                 if (limp->rlim_cur != RLIM_INFINITY &&
  695                     p->p_cpulimit == RLIM_INFINITY)
  696                         callout_reset(&p->p_limco, hz, lim_cb, p);
  697                 p->p_cpulimit = limp->rlim_cur;
  698                 break;
  699         case RLIMIT_DATA:
  700                 if (limp->rlim_cur > maxdsiz)
  701                         limp->rlim_cur = maxdsiz;
  702                 if (limp->rlim_max > maxdsiz)
  703                         limp->rlim_max = maxdsiz;
  704                 break;
  705 
  706         case RLIMIT_STACK:
  707                 if (limp->rlim_cur > maxssiz)
  708                         limp->rlim_cur = maxssiz;
  709                 if (limp->rlim_max > maxssiz)
  710                         limp->rlim_max = maxssiz;
  711                 oldssiz = *alimp;
  712                 if (td->td_proc->p_sysent->sv_fixlimit != NULL)
  713                         td->td_proc->p_sysent->sv_fixlimit(&oldssiz,
  714                             RLIMIT_STACK);
  715                 break;
  716 
  717         case RLIMIT_NOFILE:
  718                 if (limp->rlim_cur > maxfilesperproc)
  719                         limp->rlim_cur = maxfilesperproc;
  720                 if (limp->rlim_max > maxfilesperproc)
  721                         limp->rlim_max = maxfilesperproc;
  722                 break;
  723 
  724         case RLIMIT_NPROC:
  725                 if (limp->rlim_cur > maxprocperuid)
  726                         limp->rlim_cur = maxprocperuid;
  727                 if (limp->rlim_max > maxprocperuid)
  728                         limp->rlim_max = maxprocperuid;
  729                 if (limp->rlim_cur < 1)
  730                         limp->rlim_cur = 1;
  731                 if (limp->rlim_max < 1)
  732                         limp->rlim_max = 1;
  733                 break;
  734         }
  735         if (td->td_proc->p_sysent->sv_fixlimit != NULL)
  736                 td->td_proc->p_sysent->sv_fixlimit(limp, which);
  737         *alimp = *limp;
  738         p->p_limit = newlim;
  739         PROC_UNLOCK(p);
  740         lim_free(oldlim);
  741 
  742         if (which == RLIMIT_STACK) {
  743                 /*
  744                  * Stack is allocated to the max at exec time with only
  745                  * "rlim_cur" bytes accessible.  If stack limit is going
  746                  * up make more accessible, if going down make inaccessible.
  747                  */
  748                 if (limp->rlim_cur != oldssiz.rlim_cur) {
  749                         vm_offset_t addr;
  750                         vm_size_t size;
  751                         vm_prot_t prot;
  752 
  753                         if (limp->rlim_cur > oldssiz.rlim_cur) {
  754                                 prot = p->p_sysent->sv_stackprot;
  755                                 size = limp->rlim_cur - oldssiz.rlim_cur;
  756                                 addr = p->p_sysent->sv_usrstack -
  757                                     limp->rlim_cur;
  758                         } else {
  759                                 prot = VM_PROT_NONE;
  760                                 size = oldssiz.rlim_cur - limp->rlim_cur;
  761                                 addr = p->p_sysent->sv_usrstack -
  762                                     oldssiz.rlim_cur;
  763                         }
  764                         addr = trunc_page(addr);
  765                         size = round_page(size);
  766                         (void)vm_map_protect(&p->p_vmspace->vm_map,
  767                             addr, addr + size, prot, FALSE);
  768                 }
  769         }
  770 
  771         return (0);
  772 }
  773 
  774 #ifndef _SYS_SYSPROTO_H_
  775 struct __getrlimit_args {
  776         u_int   which;
  777         struct  rlimit *rlp;
  778 };
  779 #endif
  780 /* ARGSUSED */
  781 int
  782 getrlimit(td, uap)
  783         struct thread *td;
  784         register struct __getrlimit_args *uap;
  785 {
  786         struct rlimit rlim;
  787         struct proc *p;
  788         int error;
  789 
  790         if (uap->which >= RLIM_NLIMITS)
  791                 return (EINVAL);
  792         p = td->td_proc;
  793         PROC_LOCK(p);
  794         lim_rlimit(p, uap->which, &rlim);
  795         PROC_UNLOCK(p);
  796         error = copyout(&rlim, uap->rlp, sizeof(struct rlimit));
  797         return (error);
  798 }
  799 
  800 /*
  801  * Transform the running time and tick information for children of proc p
  802  * into user and system time usage.
  803  */
  804 void
  805 calccru(p, up, sp)
  806         struct proc *p;
  807         struct timeval *up;
  808         struct timeval *sp;
  809 {
  810 
  811         PROC_LOCK_ASSERT(p, MA_OWNED);
  812         calcru1(p, &p->p_crux, up, sp);
  813 }
  814 
  815 /*
  816  * Transform the running time and tick information in proc p into user
  817  * and system time usage.  If appropriate, include the current time slice
  818  * on this CPU.
  819  */
  820 void
  821 calcru(struct proc *p, struct timeval *up, struct timeval *sp)
  822 {
  823         struct thread *td;
  824         uint64_t u;
  825 
  826         PROC_LOCK_ASSERT(p, MA_OWNED);
  827         PROC_SLOCK_ASSERT(p, MA_OWNED);
  828         /*
  829          * If we are getting stats for the current process, then add in the
  830          * stats that this thread has accumulated in its current time slice.
  831          * We reset the thread and CPU state as if we had performed a context
  832          * switch right here.
  833          */
  834         td = curthread;
  835         if (td->td_proc == p) {
  836                 u = cpu_ticks();
  837                 p->p_rux.rux_runtime += u - PCPU_GET(switchtime);
  838                 PCPU_SET(switchtime, u);
  839         }
  840         /* Make sure the per-thread stats are current. */
  841         FOREACH_THREAD_IN_PROC(p, td) {
  842                 if (td->td_incruntime == 0)
  843                         continue;
  844                 ruxagg(p, td);
  845         }
  846         calcru1(p, &p->p_rux, up, sp);
  847 }
  848 
  849 static void
  850 calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up,
  851     struct timeval *sp)
  852 {
  853         /* {user, system, interrupt, total} {ticks, usec}: */
  854         u_int64_t ut, uu, st, su, it, tt, tu;
  855 
  856         ut = ruxp->rux_uticks;
  857         st = ruxp->rux_sticks;
  858         it = ruxp->rux_iticks;
  859         tt = ut + st + it;
  860         if (tt == 0) {
  861                 /* Avoid divide by zero */
  862                 st = 1;
  863                 tt = 1;
  864         }
  865         tu = cputick2usec(ruxp->rux_runtime);
  866         if ((int64_t)tu < 0) {
  867                 /* XXX: this should be an assert /phk */
  868                 printf("calcru: negative runtime of %jd usec for pid %d (%s)\n",
  869                     (intmax_t)tu, p->p_pid, p->p_comm);
  870                 tu = ruxp->rux_tu;
  871         }
  872 
  873         if (tu >= ruxp->rux_tu) {
  874                 /*
  875                  * The normal case, time increased.
  876                  * Enforce monotonicity of bucketed numbers.
  877                  */
  878                 uu = (tu * ut) / tt;
  879                 if (uu < ruxp->rux_uu)
  880                         uu = ruxp->rux_uu;
  881                 su = (tu * st) / tt;
  882                 if (su < ruxp->rux_su)
  883                         su = ruxp->rux_su;
  884         } else if (tu + 3 > ruxp->rux_tu || 101 * tu > 100 * ruxp->rux_tu) {
  885                 /*
  886                  * When we calibrate the cputicker, it is not uncommon to
  887                  * see the presumably fixed frequency increase slightly over
  888                  * time as a result of thermal stabilization and NTP
  889                  * discipline (of the reference clock).  We therefore ignore
  890                  * a bit of backwards slop because we  expect to catch up
  891                  * shortly.  We use a 3 microsecond limit to catch low
  892                  * counts and a 1% limit for high counts.
  893                  */
  894                 uu = ruxp->rux_uu;
  895                 su = ruxp->rux_su;
  896                 tu = ruxp->rux_tu;
  897         } else { /* tu < ruxp->rux_tu */
  898                 /*
  899                  * What happened here was likely that a laptop, which ran at
  900                  * a reduced clock frequency at boot, kicked into high gear.
  901                  * The wisdom of spamming this message in that case is
  902                  * dubious, but it might also be indicative of something
  903                  * serious, so lets keep it and hope laptops can be made
  904                  * more truthful about their CPU speed via ACPI.
  905                  */
  906                 printf("calcru: runtime went backwards from %ju usec "
  907                     "to %ju usec for pid %d (%s)\n",
  908                     (uintmax_t)ruxp->rux_tu, (uintmax_t)tu,
  909                     p->p_pid, p->p_comm);
  910                 uu = (tu * ut) / tt;
  911                 su = (tu * st) / tt;
  912         }
  913 
  914         ruxp->rux_uu = uu;
  915         ruxp->rux_su = su;
  916         ruxp->rux_tu = tu;
  917 
  918         up->tv_sec = uu / 1000000;
  919         up->tv_usec = uu % 1000000;
  920         sp->tv_sec = su / 1000000;
  921         sp->tv_usec = su % 1000000;
  922 }
  923 
  924 #ifndef _SYS_SYSPROTO_H_
  925 struct getrusage_args {
  926         int     who;
  927         struct  rusage *rusage;
  928 };
  929 #endif
  930 int
  931 getrusage(td, uap)
  932         register struct thread *td;
  933         register struct getrusage_args *uap;
  934 {
  935         struct rusage ru;
  936         int error;
  937 
  938         error = kern_getrusage(td, uap->who, &ru);
  939         if (error == 0)
  940                 error = copyout(&ru, uap->rusage, sizeof(struct rusage));
  941         return (error);
  942 }
  943 
  944 int
  945 kern_getrusage(struct thread *td, int who, struct rusage *rup)
  946 {
  947         struct proc *p;
  948         int error;
  949 
  950         error = 0;
  951         p = td->td_proc;
  952         PROC_LOCK(p);
  953         switch (who) {
  954         case RUSAGE_SELF:
  955                 rufetchcalc(p, rup, &rup->ru_utime,
  956                     &rup->ru_stime);
  957                 break;
  958 
  959         case RUSAGE_CHILDREN:
  960                 *rup = p->p_stats->p_cru;
  961                 calccru(p, &rup->ru_utime, &rup->ru_stime);
  962                 break;
  963 
  964         case RUSAGE_THREAD:
  965                 PROC_SLOCK(p);
  966                 ruxagg(p, td);
  967                 PROC_SUNLOCK(p);
  968                 thread_lock(td);
  969                 *rup = td->td_ru;
  970                 calcru1(p, &td->td_rux, &rup->ru_utime, &rup->ru_stime);
  971                 thread_unlock(td);
  972                 break;
  973 
  974         default:
  975                 error = EINVAL;
  976         }
  977         PROC_UNLOCK(p);
  978         return (error);
  979 }
  980 
  981 void
  982 rucollect(struct rusage *ru, struct rusage *ru2)
  983 {
  984         long *ip, *ip2;
  985         int i;
  986 
  987         if (ru->ru_maxrss < ru2->ru_maxrss)
  988                 ru->ru_maxrss = ru2->ru_maxrss;
  989         ip = &ru->ru_first;
  990         ip2 = &ru2->ru_first;
  991         for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
  992                 *ip++ += *ip2++;
  993 }
  994 
  995 void
  996 ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2,
  997     struct rusage_ext *rux2)
  998 {
  999 
 1000         rux->rux_runtime += rux2->rux_runtime;
 1001         rux->rux_uticks += rux2->rux_uticks;
 1002         rux->rux_sticks += rux2->rux_sticks;
 1003         rux->rux_iticks += rux2->rux_iticks;
 1004         rux->rux_uu += rux2->rux_uu;
 1005         rux->rux_su += rux2->rux_su;
 1006         rux->rux_tu += rux2->rux_tu;
 1007         rucollect(ru, ru2);
 1008 }
 1009 
 1010 /*
 1011  * Aggregate tick counts into the proc's rusage_ext.
 1012  */
 1013 static void
 1014 ruxagg_locked(struct rusage_ext *rux, struct thread *td)
 1015 {
 1016 
 1017         THREAD_LOCK_ASSERT(td, MA_OWNED);
 1018         PROC_SLOCK_ASSERT(td->td_proc, MA_OWNED);
 1019         rux->rux_runtime += td->td_incruntime;
 1020         rux->rux_uticks += td->td_uticks;
 1021         rux->rux_sticks += td->td_sticks;
 1022         rux->rux_iticks += td->td_iticks;
 1023 }
 1024 
 1025 void
 1026 ruxagg(struct proc *p, struct thread *td)
 1027 {
 1028 
 1029         thread_lock(td);
 1030         ruxagg_locked(&p->p_rux, td);
 1031         ruxagg_locked(&td->td_rux, td);
 1032         td->td_incruntime = 0;
 1033         td->td_uticks = 0;
 1034         td->td_iticks = 0;
 1035         td->td_sticks = 0;
 1036         thread_unlock(td);
 1037 }
 1038 
 1039 /*
 1040  * Update the rusage_ext structure and fetch a valid aggregate rusage
 1041  * for proc p if storage for one is supplied.
 1042  */
 1043 void
 1044 rufetch(struct proc *p, struct rusage *ru)
 1045 {
 1046         struct thread *td;
 1047 
 1048         PROC_SLOCK_ASSERT(p, MA_OWNED);
 1049 
 1050         *ru = p->p_ru;
 1051         if (p->p_numthreads > 0)  {
 1052                 FOREACH_THREAD_IN_PROC(p, td) {
 1053                         ruxagg(p, td);
 1054                         rucollect(ru, &td->td_ru);
 1055                 }
 1056         }
 1057 }
 1058 
 1059 /*
 1060  * Atomically perform a rufetch and a calcru together.
 1061  * Consumers, can safely assume the calcru is executed only once
 1062  * rufetch is completed.
 1063  */
 1064 void
 1065 rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
 1066     struct timeval *sp)
 1067 {
 1068 
 1069         PROC_SLOCK(p);
 1070         rufetch(p, ru);
 1071         calcru(p, up, sp);
 1072         PROC_SUNLOCK(p);
 1073 }
 1074 
 1075 /*
 1076  * Allocate a new resource limits structure and initialize its
 1077  * reference count and mutex pointer.
 1078  */
 1079 struct plimit *
 1080 lim_alloc()
 1081 {
 1082         struct plimit *limp;
 1083 
 1084         limp = malloc(sizeof(struct plimit), M_PLIMIT, M_WAITOK);
 1085         refcount_init(&limp->pl_refcnt, 1);
 1086         return (limp);
 1087 }
 1088 
 1089 struct plimit *
 1090 lim_hold(limp)
 1091         struct plimit *limp;
 1092 {
 1093 
 1094         refcount_acquire(&limp->pl_refcnt);
 1095         return (limp);
 1096 }
 1097 
 1098 void
 1099 lim_fork(struct proc *p1, struct proc *p2)
 1100 {
 1101         p2->p_limit = lim_hold(p1->p_limit);
 1102         callout_init_mtx(&p2->p_limco, &p2->p_mtx, 0);
 1103         if (p1->p_cpulimit != RLIM_INFINITY)
 1104                 callout_reset(&p2->p_limco, hz, lim_cb, p2);
 1105 }
 1106 
 1107 void
 1108 lim_free(limp)
 1109         struct plimit *limp;
 1110 {
 1111 
 1112         KASSERT(limp->pl_refcnt > 0, ("plimit refcnt underflow"));
 1113         if (refcount_release(&limp->pl_refcnt))
 1114                 free((void *)limp, M_PLIMIT);
 1115 }
 1116 
 1117 /*
 1118  * Make a copy of the plimit structure.
 1119  * We share these structures copy-on-write after fork.
 1120  */
 1121 void
 1122 lim_copy(dst, src)
 1123         struct plimit *dst, *src;
 1124 {
 1125 
 1126         KASSERT(dst->pl_refcnt == 1, ("lim_copy to shared limit"));
 1127         bcopy(src->pl_rlimit, dst->pl_rlimit, sizeof(src->pl_rlimit));
 1128 }
 1129 
 1130 /*
 1131  * Return the hard limit for a particular system resource.  The
 1132  * which parameter specifies the index into the rlimit array.
 1133  */
 1134 rlim_t
 1135 lim_max(struct proc *p, int which)
 1136 {
 1137         struct rlimit rl;
 1138 
 1139         lim_rlimit(p, which, &rl);
 1140         return (rl.rlim_max);
 1141 }
 1142 
 1143 /*
 1144  * Return the current (soft) limit for a particular system resource.
 1145  * The which parameter which specifies the index into the rlimit array
 1146  */
 1147 rlim_t
 1148 lim_cur(struct proc *p, int which)
 1149 {
 1150         struct rlimit rl;
 1151 
 1152         lim_rlimit(p, which, &rl);
 1153         return (rl.rlim_cur);
 1154 }
 1155 
 1156 /*
 1157  * Return a copy of the entire rlimit structure for the system limit
 1158  * specified by 'which' in the rlimit structure pointed to by 'rlp'.
 1159  */
 1160 void
 1161 lim_rlimit(struct proc *p, int which, struct rlimit *rlp)
 1162 {
 1163 
 1164         PROC_LOCK_ASSERT(p, MA_OWNED);
 1165         KASSERT(which >= 0 && which < RLIM_NLIMITS,
 1166             ("request for invalid resource limit"));
 1167         *rlp = p->p_limit->pl_rlimit[which];
 1168         if (p->p_sysent->sv_fixlimit != NULL)
 1169                 p->p_sysent->sv_fixlimit(rlp, which);
 1170 }
 1171 
 1172 /*
 1173  * Find the uidinfo structure for a uid.  This structure is used to
 1174  * track the total resource consumption (process count, socket buffer
 1175  * size, etc.) for the uid and impose limits.
 1176  */
 1177 void
 1178 uihashinit()
 1179 {
 1180 
 1181         uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash);
 1182         rw_init(&uihashtbl_lock, "uidinfo hash");
 1183 }
 1184 
 1185 /*
 1186  * Look up a uidinfo struct for the parameter uid.
 1187  * uihashtbl_lock must be locked.
 1188  */
 1189 static struct uidinfo *
 1190 uilookup(uid)
 1191         uid_t uid;
 1192 {
 1193         struct uihashhead *uipp;
 1194         struct uidinfo *uip;
 1195 
 1196         rw_assert(&uihashtbl_lock, RA_LOCKED);
 1197         uipp = UIHASH(uid);
 1198         LIST_FOREACH(uip, uipp, ui_hash)
 1199                 if (uip->ui_uid == uid)
 1200                         break;
 1201 
 1202         return (uip);
 1203 }
 1204 
 1205 /*
 1206  * Find or allocate a struct uidinfo for a particular uid.
 1207  * Increase refcount on uidinfo struct returned.
 1208  * uifree() should be called on a struct uidinfo when released.
 1209  */
 1210 struct uidinfo *
 1211 uifind(uid)
 1212         uid_t uid;
 1213 {
 1214         struct uidinfo *old_uip, *uip;
 1215 
 1216         rw_rlock(&uihashtbl_lock);
 1217         uip = uilookup(uid);
 1218         if (uip == NULL) {
 1219                 rw_runlock(&uihashtbl_lock);
 1220                 uip = malloc(sizeof(*uip), M_UIDINFO, M_WAITOK | M_ZERO);
 1221                 rw_wlock(&uihashtbl_lock);
 1222                 /*
 1223                  * There's a chance someone created our uidinfo while we
 1224                  * were in malloc and not holding the lock, so we have to
 1225                  * make sure we don't insert a duplicate uidinfo.
 1226                  */
 1227                 if ((old_uip = uilookup(uid)) != NULL) {
 1228                         /* Someone else beat us to it. */
 1229                         free(uip, M_UIDINFO);
 1230                         uip = old_uip;
 1231                 } else {
 1232                         refcount_init(&uip->ui_ref, 0);
 1233                         uip->ui_uid = uid;
 1234                         mtx_init(&uip->ui_vmsize_mtx, "ui_vmsize", NULL,
 1235                             MTX_DEF);
 1236                         LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
 1237                 }
 1238         }
 1239         uihold(uip);
 1240         rw_unlock(&uihashtbl_lock);
 1241         return (uip);
 1242 }
 1243 
 1244 /*
 1245  * Place another refcount on a uidinfo struct.
 1246  */
 1247 void
 1248 uihold(uip)
 1249         struct uidinfo *uip;
 1250 {
 1251 
 1252         refcount_acquire(&uip->ui_ref);
 1253 }
 1254 
 1255 /*-
 1256  * Since uidinfo structs have a long lifetime, we use an
 1257  * opportunistic refcounting scheme to avoid locking the lookup hash
 1258  * for each release.
 1259  *
 1260  * If the refcount hits 0, we need to free the structure,
 1261  * which means we need to lock the hash.
 1262  * Optimal case:
 1263  *   After locking the struct and lowering the refcount, if we find
 1264  *   that we don't need to free, simply unlock and return.
 1265  * Suboptimal case:
 1266  *   If refcount lowering results in need to free, bump the count
 1267  *   back up, lose the lock and acquire the locks in the proper
 1268  *   order to try again.
 1269  */
 1270 void
 1271 uifree(uip)
 1272         struct uidinfo *uip;
 1273 {
 1274         int old;
 1275 
 1276         /* Prepare for optimal case. */
 1277         old = uip->ui_ref;
 1278         if (old > 1 && atomic_cmpset_int(&uip->ui_ref, old, old - 1))
 1279                 return;
 1280 
 1281         /* Prepare for suboptimal case. */
 1282         rw_wlock(&uihashtbl_lock);
 1283         if (refcount_release(&uip->ui_ref)) {
 1284                 LIST_REMOVE(uip, ui_hash);
 1285                 rw_wunlock(&uihashtbl_lock);
 1286                 if (uip->ui_sbsize != 0)
 1287                         printf("freeing uidinfo: uid = %d, sbsize = %ld\n",
 1288                             uip->ui_uid, uip->ui_sbsize);
 1289                 if (uip->ui_proccnt != 0)
 1290                         printf("freeing uidinfo: uid = %d, proccnt = %ld\n",
 1291                             uip->ui_uid, uip->ui_proccnt);
 1292                 if (uip->ui_vmsize != 0)
 1293                         printf("freeing uidinfo: uid = %d, swapuse = %lld\n",
 1294                             uip->ui_uid, (unsigned long long)uip->ui_vmsize);
 1295                 mtx_destroy(&uip->ui_vmsize_mtx);
 1296                 free(uip, M_UIDINFO);
 1297                 return;
 1298         }
 1299         /*
 1300          * Someone added a reference between atomic_cmpset_int() and
 1301          * rw_wlock(&uihashtbl_lock).
 1302          */
 1303         rw_wunlock(&uihashtbl_lock);
 1304 }
 1305 
 1306 /*
 1307  * Change the count associated with number of processes
 1308  * a given user is using.  When 'max' is 0, don't enforce a limit
 1309  */
 1310 int
 1311 chgproccnt(uip, diff, max)
 1312         struct  uidinfo *uip;
 1313         int     diff;
 1314         rlim_t  max;
 1315 {
 1316 
 1317         /* Don't allow them to exceed max, but allow subtraction. */
 1318         if (diff > 0 && max != 0) {
 1319                 if (atomic_fetchadd_long(&uip->ui_proccnt, (long)diff) + diff > max) {
 1320                         atomic_subtract_long(&uip->ui_proccnt, (long)diff);
 1321                         return (0);
 1322                 }
 1323         } else {
 1324                 atomic_add_long(&uip->ui_proccnt, (long)diff);
 1325                 if (uip->ui_proccnt < 0)
 1326                         printf("negative proccnt for uid = %d\n", uip->ui_uid);
 1327         }
 1328         return (1);
 1329 }
 1330 
 1331 /*
 1332  * Change the total socket buffer size a user has used.
 1333  */
 1334 int
 1335 chgsbsize(uip, hiwat, to, max)
 1336         struct  uidinfo *uip;
 1337         u_int  *hiwat;
 1338         u_int   to;
 1339         rlim_t  max;
 1340 {
 1341         int diff;
 1342 
 1343         diff = to - *hiwat;
 1344         if (diff > 0) {
 1345                 if (atomic_fetchadd_long(&uip->ui_sbsize, (long)diff) + diff > max) {
 1346                         atomic_subtract_long(&uip->ui_sbsize, (long)diff);
 1347                         return (0);
 1348                 }
 1349         } else {
 1350                 atomic_add_long(&uip->ui_sbsize, (long)diff);
 1351                 if (uip->ui_sbsize < 0)
 1352                         printf("negative sbsize for uid = %d\n", uip->ui_uid);
 1353         }
 1354         *hiwat = to;
 1355         return (1);
 1356 }
 1357 
 1358 /*
 1359  * Change the count associated with number of pseudo-terminals
 1360  * a given user is using.  When 'max' is 0, don't enforce a limit
 1361  */
 1362 int
 1363 chgptscnt(uip, diff, max)
 1364         struct  uidinfo *uip;
 1365         int     diff;
 1366         rlim_t  max;
 1367 {
 1368 
 1369         /* Don't allow them to exceed max, but allow subtraction. */
 1370         if (diff > 0 && max != 0) {
 1371                 if (atomic_fetchadd_long(&uip->ui_ptscnt, (long)diff) + diff > max) {
 1372                         atomic_subtract_long(&uip->ui_ptscnt, (long)diff);
 1373                         return (0);
 1374                 }
 1375         } else {
 1376                 atomic_add_long(&uip->ui_ptscnt, (long)diff);
 1377                 if (uip->ui_ptscnt < 0)
 1378                         printf("negative ptscnt for uid = %d\n", uip->ui_uid);
 1379         }
 1380         return (1);
 1381 }

Cache object: ba3e2ceb858fc109a888c385d0decbfb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.