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/bsd/kern/kern_resource.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
   26 /*-
   27  * Copyright (c) 1982, 1986, 1991, 1993
   28  *      The Regents of the University of California.  All rights reserved.
   29  * (c) UNIX System Laboratories, Inc.
   30  * All or some portions of this file are derived from material licensed
   31  * to the University of California by American Telephone and Telegraph
   32  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   33  * the permission of UNIX System Laboratories, Inc.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgement:
   45  *      This product includes software developed by the University of
   46  *      California, Berkeley and its contributors.
   47  * 4. Neither the name of the University nor the names of its contributors
   48  *    may be used to endorse or promote products derived from this software
   49  *    without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   61  * SUCH DAMAGE.
   62  *
   63  *      @(#)kern_resource.c     8.5 (Berkeley) 1/21/94
   64  */
   65 
   66 #include <sys/param.h>
   67 #include <sys/systm.h>
   68 #include <sys/sysctl.h>
   69 #include <sys/kernel.h>
   70 #include <sys/file.h>
   71 #include <sys/resourcevar.h>
   72 #include <sys/malloc.h>
   73 #include <sys/proc.h>
   74 #include <machine/spl.h>
   75 
   76 #include <sys/mount.h>
   77 
   78 #include <machine/vmparam.h>
   79 
   80 #include <mach/mach_types.h>
   81 #include <mach/time_value.h>
   82 #include <mach/task_info.h>
   83 
   84 #include <vm/vm_map.h>
   85 
   86 int     donice __P((struct proc *curp, struct proc *chgp, int n));
   87 int     dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp));
   88 
   89 rlim_t maxdmap = MAXDSIZ;       /* XXX */ 
   90 rlim_t maxsmap = MAXSSIZ;       /* XXX */ 
   91 
   92 /*
   93  * Limits on the number of open files per process, and the number
   94  * of child processes per process.
   95  *
   96  * Note: would be in kern/subr_param.c in FreeBSD.
   97  */
   98 int maxprocperuid = CHILD_MAX;          /* max # of procs per user */
   99 int maxfilesperproc = OPEN_MAX;         /* per-proc open files limit */
  100 
  101 SYSCTL_INT( _kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW,
  102                 &maxprocperuid, 0, "Maximum processes allowed per userid" );
  103 
  104 SYSCTL_INT( _kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW,       
  105                 &maxfilesperproc, 0, "Maximum files allowed open per process" );
  106 
  107 
  108 /*
  109  * Resource controls and accounting.
  110  */
  111 struct getpriority_args  {
  112                 int which;
  113                 int who;
  114 };
  115 int
  116 getpriority(curp, uap, retval)
  117         struct proc *curp;
  118         register struct getpriority_args *uap;
  119         register_t *retval;
  120 {
  121         register struct proc *p;
  122         register int low = PRIO_MAX + 1;
  123 
  124         switch (uap->which) {
  125 
  126         case PRIO_PROCESS:
  127                 if (uap->who == 0)
  128                         p = curp;
  129                 else
  130                         p = pfind(uap->who);
  131                 if (p == 0)
  132                         break;
  133                 low = p->p_nice;
  134                 break;
  135 
  136         case PRIO_PGRP: {
  137                 register struct pgrp *pg;
  138 
  139                 if (uap->who == 0)
  140                         pg = curp->p_pgrp;
  141                 else if ((pg = pgfind(uap->who)) == NULL)
  142                         break;
  143                 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
  144                         if (p->p_nice < low)
  145                                 low = p->p_nice;
  146                 }
  147                 break;
  148         }
  149 
  150         case PRIO_USER:
  151                 if (uap->who == 0)
  152                         uap->who = curp->p_ucred->cr_uid;
  153                 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
  154                         if (p->p_ucred->cr_uid == uap->who &&
  155                             p->p_nice < low)
  156                                 low = p->p_nice;
  157                 break;
  158 
  159         default:
  160                 return (EINVAL);
  161         }
  162         if (low == PRIO_MAX + 1)
  163                 return (ESRCH);
  164         *retval = low;
  165         return (0);
  166 }
  167 
  168 struct setpriority_args {
  169                 int which;
  170                 int who;
  171                 int prio;
  172 };
  173 /* ARGSUSED */
  174 int
  175 setpriority(curp, uap, retval)
  176         struct proc *curp;
  177         register struct setpriority_args *uap;
  178         register_t *retval;
  179 {
  180         register struct proc *p;
  181         int found = 0, error = 0;
  182 
  183         switch (uap->which) {
  184 
  185         case PRIO_PROCESS:
  186                 if (uap->who == 0)
  187                         p = curp;
  188                 else
  189                         p = pfind(uap->who);
  190                 if (p == 0)
  191                         break;
  192                 error = donice(curp, p, uap->prio);
  193                 found++;
  194                 break;
  195 
  196         case PRIO_PGRP: {
  197                 register struct pgrp *pg;
  198                  
  199                 if (uap->who == 0)
  200                         pg = curp->p_pgrp;
  201                 else if ((pg = pgfind(uap->who)) == NULL)
  202                         break;
  203                 for (p = pg->pg_members.lh_first; p != 0;
  204                     p = p->p_pglist.le_next) {
  205                         error = donice(curp, p, uap->prio);
  206                         found++;
  207                 }
  208                 break;
  209         }
  210 
  211         case PRIO_USER:
  212                 if (uap->who == 0)
  213                         uap->who = curp->p_ucred->cr_uid;
  214                 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
  215                         if (p->p_ucred->cr_uid == uap->who) {
  216                                 error = donice(curp, p, uap->prio);
  217                                 found++;
  218                         }
  219                 break;
  220 
  221         default:
  222                 return (EINVAL);
  223         }
  224         if (found == 0)
  225                 return (ESRCH);
  226         return (error);
  227 }
  228 
  229 int
  230 donice(curp, chgp, n)
  231         register struct proc *curp, *chgp;
  232         register int n;
  233 {
  234         register struct pcred *pcred = curp->p_cred;
  235 
  236         if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
  237             pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
  238             pcred->p_ruid != chgp->p_ucred->cr_uid)
  239                 return (EPERM);
  240         if (n > PRIO_MAX)
  241                 n = PRIO_MAX;
  242         if (n < PRIO_MIN)
  243                 n = PRIO_MIN;
  244         if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
  245                 return (EACCES);
  246         chgp->p_nice = n;
  247         (void)resetpriority(chgp);
  248         return (0);
  249 }
  250 
  251 #if COMPAT_43
  252 struct osetrlimit_args {
  253                 u_int which;
  254                 struct ogetrlimit * rlp;
  255 };
  256 /* ARGSUSED */
  257 int
  258 osetrlimit(p, uap, retval)
  259         struct proc *p;
  260         struct osetrlimit_args *uap;
  261         register_t *retval;
  262 {
  263         struct orlimit olim;
  264         struct rlimit lim;
  265         int error;
  266 
  267         if (error = copyin((caddr_t)uap->rlp, (caddr_t)&olim,
  268             sizeof (struct orlimit)))
  269                 return (error);
  270         lim.rlim_cur = olim.rlim_cur;
  271         lim.rlim_max = olim.rlim_max;
  272         return (dosetrlimit(p, uap->which, &lim));
  273 }
  274 
  275 struct ogetrlimit_args {
  276                 u_int which;
  277                 struct ogetrlimit * rlp;
  278 };
  279 /* ARGSUSED */
  280 int
  281 ogetrlimit(p, uap, retval)
  282         struct proc *p;
  283         struct ogetrlimit_args *uap;
  284         register_t *retval;
  285 {
  286         struct orlimit olim;
  287 
  288         if (uap->which >= RLIM_NLIMITS)
  289                 return (EINVAL);
  290         olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur;
  291         if (olim.rlim_cur == -1)
  292                 olim.rlim_cur = 0x7fffffff;
  293         olim.rlim_max = p->p_rlimit[uap->which].rlim_max;
  294         if (olim.rlim_max == -1)
  295                 olim.rlim_max = 0x7fffffff;
  296         return (copyout((caddr_t)&olim, (caddr_t)uap->rlp,
  297             sizeof(olim)));
  298 }
  299 #endif /* COMPAT_43 */
  300 
  301 struct setrlimit_args {
  302                 u_int which;
  303                 struct rlimit * rlp;
  304 };
  305 /* ARGSUSED */
  306 int
  307 setrlimit(p, uap, retval)
  308         struct proc *p;
  309         register struct setrlimit_args *uap;
  310         register_t *retval;
  311 {
  312         struct rlimit alim;
  313         int error;
  314 
  315         if (error = copyin((caddr_t)uap->rlp, (caddr_t)&alim,
  316             sizeof (struct rlimit)))
  317                 return (error);
  318         return (dosetrlimit(p, uap->which, &alim));
  319 }
  320 
  321 int
  322 dosetrlimit(p, which, limp)
  323         struct proc *p;
  324         u_int which;
  325         struct rlimit *limp;
  326 {
  327         register struct rlimit *alimp;
  328         extern rlim_t maxdmap, maxsmap;
  329         int error;
  330 
  331         if (which >= RLIM_NLIMITS)
  332                 return (EINVAL);
  333         alimp = &p->p_rlimit[which];
  334         if (limp->rlim_cur > alimp->rlim_max || 
  335             limp->rlim_max > alimp->rlim_max)
  336                 if (error = suser(p->p_ucred, &p->p_acflag))
  337                         return (error);
  338         if (limp->rlim_cur > limp->rlim_max)
  339                 limp->rlim_cur = limp->rlim_max;
  340         if (p->p_limit->p_refcnt > 1 &&
  341             (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
  342                 p->p_limit->p_refcnt--;
  343                 p->p_limit = limcopy(p->p_limit);
  344                 alimp = &p->p_rlimit[which];
  345         }
  346 
  347         switch (which) {
  348 
  349         case RLIMIT_DATA:
  350                 if (limp->rlim_cur > maxdmap)
  351                         limp->rlim_cur = maxdmap;
  352                 if (limp->rlim_max > maxdmap)
  353                         limp->rlim_max = maxdmap;
  354                 break;
  355 
  356         case RLIMIT_STACK:
  357                 if (limp->rlim_cur > maxsmap)
  358                         limp->rlim_cur = maxsmap;
  359                 if (limp->rlim_max > maxsmap)
  360                         limp->rlim_max = maxsmap;
  361                 /*
  362                  * Stack is allocated to the max at exec time with only
  363                  * "rlim_cur" bytes accessible.  If stack limit is going
  364                  * up make more accessible, if going down make inaccessible.
  365                  */
  366                 if (limp->rlim_cur != alimp->rlim_cur) {
  367                         vm_offset_t addr;
  368                         vm_size_t size;
  369                         vm_prot_t prot;
  370                         
  371                         if (limp->rlim_cur > alimp->rlim_cur) {
  372                                 /* grow stack */
  373                                 size = round_page_64(limp->rlim_cur);
  374                                 size -= round_page_64(alimp->rlim_cur);
  375 
  376 #if STACK_GROWTH_UP
  377                                 /* go to top of current stack */
  378                                 addr = trunc_page((unsigned int)(p->user_stack + alimp->rlim_cur));
  379 #else STACK_GROWTH_UP
  380                                 addr = trunc_page_32((unsigned int)(p->user_stack - alimp->rlim_cur));
  381                                 addr -= size;
  382 #endif /* STACK_GROWTH_UP */
  383                                 if (vm_allocate(current_map(),
  384                                                 &addr, size, FALSE) != KERN_SUCCESS)
  385                                         return(EINVAL);
  386                         } else {
  387                                 /* shrink stack */
  388                         }
  389                 }
  390                 break;
  391 
  392         case RLIMIT_NOFILE:
  393                 /* 
  394                 * Only root can set the maxfiles limits, as it is systemwide resource
  395                 */
  396                 if ( is_suser() ) {
  397                         if (limp->rlim_cur > maxfiles)
  398                                 limp->rlim_cur = maxfiles;
  399                         if (limp->rlim_max > maxfiles)
  400                                 limp->rlim_max = maxfiles;
  401                 }
  402                 else {
  403                         if (limp->rlim_cur > maxfilesperproc)
  404                                 limp->rlim_cur = maxfilesperproc;
  405                         if (limp->rlim_max > maxfilesperproc)
  406                                 limp->rlim_max = maxfilesperproc;
  407                 }
  408                 break;
  409 
  410         case RLIMIT_NPROC:
  411                 /* 
  412                  * Only root can set to the maxproc limits, as it is
  413                  * systemwide resource; all others are limited to
  414                  * maxprocperuid (presumably less than maxproc).
  415                  */
  416                 if ( is_suser() ) {
  417                         if (limp->rlim_cur > maxproc)
  418                                 limp->rlim_cur = maxproc;
  419                         if (limp->rlim_max > maxproc)
  420                                 limp->rlim_max = maxproc;
  421                 } 
  422                 else {
  423                         if (limp->rlim_cur > maxprocperuid)
  424                                 limp->rlim_cur = maxprocperuid;
  425                         if (limp->rlim_max > maxprocperuid)
  426                                 limp->rlim_max = maxprocperuid;
  427                 }
  428                 break;
  429                 
  430         } /* switch... */
  431         *alimp = *limp;
  432         return (0);
  433 }
  434 
  435 struct getrlimit_args {
  436                 u_int which;
  437                 struct rlimit * rlp;
  438 };
  439 /* ARGSUSED */
  440 int
  441 getrlimit(p, uap, retval)
  442         struct proc *p;
  443         register struct getrlimit_args *uap;
  444         register_t *retval;
  445 {
  446 
  447         if (uap->which >= RLIM_NLIMITS)
  448                 return (EINVAL);
  449         return (copyout((caddr_t)&p->p_rlimit[uap->which],
  450             (caddr_t)uap->rlp, sizeof (struct rlimit)));
  451 }
  452 
  453 /*
  454  * Transform the running time and tick information in proc p into user,
  455  * system, and interrupt time usage.
  456  */
  457 void
  458 calcru(p, up, sp, ip)
  459         register struct proc *p;
  460         register struct timeval *up;
  461         register struct timeval *sp;
  462         register struct timeval *ip;
  463 {
  464         task_t                  task;
  465 
  466         timerclear(up);
  467         timerclear(sp);
  468         if (ip != NULL)
  469                 timerclear(ip);
  470 
  471         task = p->task;
  472         if (task) {
  473                 task_basic_info_data_t tinfo;
  474                 task_thread_times_info_data_t ttimesinfo;
  475                 int task_info_stuff, task_ttimes_stuff;
  476                 struct timeval ut,st;
  477 
  478                 task_info_stuff = TASK_BASIC_INFO_COUNT;
  479                 task_info(task, TASK_BASIC_INFO,
  480                           &tinfo, &task_info_stuff);
  481                 ut.tv_sec = tinfo.user_time.seconds;
  482                 ut.tv_usec = tinfo.user_time.microseconds;
  483                 st.tv_sec = tinfo.system_time.seconds;
  484                 st.tv_usec = tinfo.system_time.microseconds;
  485                 timeradd(&ut, up, up);
  486                 timeradd(&st, sp, sp);
  487 
  488                 task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT;
  489                 task_info(task, TASK_THREAD_TIMES_INFO,
  490                           &ttimesinfo, &task_ttimes_stuff);
  491 
  492                 ut.tv_sec = ttimesinfo.user_time.seconds;
  493                 ut.tv_usec = ttimesinfo.user_time.microseconds;
  494                 st.tv_sec = ttimesinfo.system_time.seconds;
  495                 st.tv_usec = ttimesinfo.system_time.microseconds;
  496                 timeradd(&ut, up, up);
  497                 timeradd(&st, sp, sp);
  498         }
  499 }
  500 
  501 struct getrusage_args {
  502                 int who;
  503                 struct rusage * rusage;
  504 };
  505 /* ARGSUSED */
  506 int
  507 getrusage(p, uap, retval)
  508         register struct proc *p;
  509         register struct getrusage_args *uap;
  510         register_t *retval;
  511 {
  512         struct rusage *rup, rubuf;
  513 
  514         switch (uap->who) {
  515 
  516         case RUSAGE_SELF:
  517                 rup = &p->p_stats->p_ru;
  518                 calcru(p, &rup->ru_utime, &rup->ru_stime, NULL);
  519                 rubuf = *rup;
  520                 break;
  521 
  522         case RUSAGE_CHILDREN:
  523                 rup = &p->p_stats->p_cru;
  524                 rubuf = *rup;
  525                 break;
  526 
  527         default:
  528                 return (EINVAL);
  529         }
  530         return (copyout((caddr_t)&rubuf, (caddr_t)uap->rusage,
  531             sizeof (struct rusage)));
  532 }
  533 
  534 void
  535 ruadd(ru, ru2)
  536         register struct rusage *ru, *ru2;
  537 {
  538         register long *ip, *ip2;
  539         register int i;
  540 
  541         timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
  542         timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
  543         if (ru->ru_maxrss < ru2->ru_maxrss)
  544                 ru->ru_maxrss = ru2->ru_maxrss;
  545         ip = &ru->ru_first; ip2 = &ru2->ru_first;
  546         for (i = &ru->ru_last - &ru->ru_first; i >= 0; i--)
  547                 *ip++ += *ip2++;
  548 }
  549 
  550 /*
  551  * Make a copy of the plimit structure.
  552  * We share these structures copy-on-write after fork,
  553  * and copy when a limit is changed.
  554  */
  555 struct plimit *
  556 limcopy(lim)
  557         struct plimit *lim;
  558 {
  559         register struct plimit *copy;
  560 
  561         MALLOC_ZONE(copy, struct plimit *,
  562                         sizeof(struct plimit), M_SUBPROC, M_WAITOK);
  563         bcopy(lim->pl_rlimit, copy->pl_rlimit,
  564             sizeof(struct rlimit) * RLIM_NLIMITS);
  565         copy->p_lflags = 0;
  566         copy->p_refcnt = 1;
  567         return (copy);
  568 }

Cache object: 6bb96b8bbe041beabc79565a5458742e


[ 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.