home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_resource.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-09  |  7.7 KB  |  340 lines

  1. /*-
  2.  * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)kern_resource.c    7.13 (Berkeley) 5/9/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "resourcevar.h"
  38. #include "malloc.h"
  39. #include "proc.h"
  40.  
  41. #include "vm/vm.h"
  42.  
  43. /*
  44.  * Resource controls and accounting.
  45.  */
  46.  
  47. getpriority(curp, uap, retval)
  48.     struct proc *curp;
  49.     register struct args {
  50.         int    which;
  51.         int    who;
  52.     } *uap;
  53.     int *retval;
  54. {
  55.     register struct proc *p;
  56.     register int low = PRIO_MAX + 1;
  57.  
  58.     switch (uap->which) {
  59.  
  60.     case PRIO_PROCESS:
  61.         if (uap->who == 0)
  62.             p = curp;
  63.         else
  64.             p = pfind(uap->who);
  65.         if (p == 0)
  66.             break;
  67.         low = p->p_nice;
  68.         break;
  69.  
  70.     case PRIO_PGRP: {
  71.         register struct pgrp *pg;
  72.  
  73.         if (uap->who == 0)
  74.             pg = curp->p_pgrp;
  75.         else if ((pg = pgfind(uap->who)) == NULL)
  76.             break;
  77.         for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
  78.             if (p->p_nice < low)
  79.                 low = p->p_nice;
  80.         }
  81.         break;
  82.     }
  83.  
  84.     case PRIO_USER:
  85.         if (uap->who == 0)
  86.             uap->who = curp->p_ucred->cr_uid;
  87.         for (p = allproc; p != NULL; p = p->p_nxt) {
  88.             if (p->p_ucred->cr_uid == uap->who &&
  89.                 p->p_nice < low)
  90.                 low = p->p_nice;
  91.         }
  92.         break;
  93.  
  94.     default:
  95.         return (EINVAL);
  96.     }
  97.     if (low == PRIO_MAX + 1)
  98.         return (ESRCH);
  99.     *retval = low;
  100.     return (0);
  101. }
  102.  
  103. /* ARGSUSED */
  104. setpriority(curp, uap, retval)
  105.     struct proc *curp;
  106.     register struct args {
  107.         int    which;
  108.         int    who;
  109.         int    prio;
  110.     } *uap;
  111.     int *retval;
  112. {
  113.     register struct proc *p;
  114.     int found = 0, error = 0;
  115.  
  116.     switch (uap->which) {
  117.  
  118.     case PRIO_PROCESS:
  119.         if (uap->who == 0)
  120.             p = curp;
  121.         else
  122.             p = pfind(uap->who);
  123.         if (p == 0)
  124.             break;
  125.         error = donice(curp, p, uap->prio);
  126.         found++;
  127.         break;
  128.  
  129.     case PRIO_PGRP: {
  130.         register struct pgrp *pg;
  131.          
  132.         if (uap->who == 0)
  133.             pg = curp->p_pgrp;
  134.         else if ((pg = pgfind(uap->who)) == NULL)
  135.             break;
  136.         for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
  137.             error = donice(curp, p, uap->prio);
  138.             found++;
  139.         }
  140.         break;
  141.     }
  142.  
  143.     case PRIO_USER:
  144.         if (uap->who == 0)
  145.             uap->who = curp->p_ucred->cr_uid;
  146.         for (p = allproc; p != NULL; p = p->p_nxt)
  147.             if (p->p_ucred->cr_uid == uap->who) {
  148.                 error = donice(curp, p, uap->prio);
  149.                 found++;
  150.             }
  151.         break;
  152.  
  153.     default:
  154.         return (EINVAL);
  155.     }
  156.     if (found == 0)
  157.         return (ESRCH);
  158.     return (0);
  159. }
  160.  
  161. donice(curp, chgp, n)
  162.     register struct proc *curp, *chgp;
  163.     register int n;
  164. {
  165.     register struct pcred *pcred = curp->p_cred;
  166.  
  167.     if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
  168.         pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
  169.         pcred->p_ruid != chgp->p_ucred->cr_uid)
  170.         return (EPERM);
  171.     if (n > PRIO_MAX)
  172.         n = PRIO_MAX;
  173.     if (n < PRIO_MIN)
  174.         n = PRIO_MIN;
  175.     if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
  176.         return (EACCES);
  177.     chgp->p_nice = n;
  178.     (void) setpri(chgp);
  179.     return (0);
  180. }
  181.  
  182. /* ARGSUSED */
  183. setrlimit(p, uap, retval)
  184.     struct proc *p;
  185.     register struct args {
  186.         u_int    which;
  187.         struct    rlimit *lim;
  188.     } *uap;
  189.     int *retval;
  190. {
  191.     struct rlimit alim;
  192.     register struct rlimit *alimp;
  193.     extern unsigned maxdmap;
  194.     int error;
  195.  
  196.     if (uap->which >= RLIM_NLIMITS)
  197.         return (EINVAL);
  198.     alimp = &p->p_rlimit[uap->which];
  199.     if (error =
  200.         copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
  201.         return (error);
  202.     if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
  203.         if (error = suser(p->p_ucred, &p->p_acflag))
  204.             return (error);
  205.     if (p->p_limit->p_refcnt > 1 &&
  206.         (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
  207.         p->p_limit->p_refcnt--;
  208.         p->p_limit = limcopy(p->p_limit);
  209.     }
  210.  
  211.     switch (uap->which) {
  212.  
  213.     case RLIMIT_DATA:
  214.         if (alim.rlim_cur > maxdmap)
  215.             alim.rlim_cur = maxdmap;
  216.         if (alim.rlim_max > maxdmap)
  217.             alim.rlim_max = maxdmap;
  218.         break;
  219.  
  220.     case RLIMIT_STACK:
  221.         if (alim.rlim_cur > maxdmap)
  222.             alim.rlim_cur = maxdmap;
  223.         if (alim.rlim_max > maxdmap)
  224.             alim.rlim_max = maxdmap;
  225.         /*
  226.          * Stack is allocated to the max at exec time with only
  227.          * "rlim_cur" bytes accessible.  If stack limit is going
  228.          * up make more accessible, if going down make inaccessible.
  229.          */
  230.         if (alim.rlim_cur != alimp->rlim_cur) {
  231.             vm_offset_t addr;
  232.             vm_size_t size;
  233.             vm_prot_t prot;
  234.  
  235.             if (alim.rlim_cur > alimp->rlim_cur) {
  236.                 prot = VM_PROT_ALL;
  237.                 size = alim.rlim_cur - alimp->rlim_cur;
  238.                 addr = USRSTACK - alim.rlim_cur;
  239.             } else {
  240.                 prot = VM_PROT_NONE;
  241.                 size = alimp->rlim_cur - alim.rlim_cur;
  242.                 addr = USRSTACK - alimp->rlim_cur;
  243.             }
  244.             addr = trunc_page(addr);
  245.             size = round_page(size);
  246.             (void) vm_map_protect(&p->p_vmspace->vm_map,
  247.                           addr, addr+size, prot, FALSE);
  248.         }
  249.         break;
  250.     }
  251.     p->p_rlimit[uap->which] = alim;
  252.     return (0);
  253. }
  254.  
  255. /* ARGSUSED */
  256. getrlimit(p, uap, retval)
  257.     struct proc *p;
  258.     register struct args {
  259.         u_int    which;
  260.         struct    rlimit *rlp;
  261.     } *uap;
  262.     int *retval;
  263. {
  264.  
  265.     if (uap->which >= RLIM_NLIMITS)
  266.         return (EINVAL);
  267.     return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
  268.         sizeof (struct rlimit)));
  269. }
  270.  
  271. /* ARGSUSED */
  272. getrusage(p, uap, retval)
  273.     register struct proc *p;
  274.     register struct args {
  275.         int    who;
  276.         struct    rusage *rusage;
  277.     } *uap;
  278.     int *retval;
  279. {
  280.     register struct rusage *rup;
  281.  
  282.     switch (uap->who) {
  283.  
  284.     case RUSAGE_SELF: {
  285.         int s;
  286.  
  287.         rup = &p->p_stats->p_ru;
  288.         s = splclock();
  289.         rup->ru_stime = p->p_stime;
  290.         rup->ru_utime = p->p_utime;
  291.         splx(s);
  292.         break;
  293.     }
  294.  
  295.     case RUSAGE_CHILDREN:
  296.         rup = &p->p_stats->p_cru;
  297.         break;
  298.  
  299.     default:
  300.         return (EINVAL);
  301.     }
  302.     return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
  303.         sizeof (struct rusage)));
  304. }
  305.  
  306. ruadd(ru, ru2)
  307.     register struct rusage *ru, *ru2;
  308. {
  309.     register long *ip, *ip2;
  310.     register int i;
  311.  
  312.     timevaladd(&ru->ru_utime, &ru2->ru_utime);
  313.     timevaladd(&ru->ru_stime, &ru2->ru_stime);
  314.     if (ru->ru_maxrss < ru2->ru_maxrss)
  315.         ru->ru_maxrss = ru2->ru_maxrss;
  316.     ip = &ru->ru_first; ip2 = &ru2->ru_first;
  317.     for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
  318.         *ip++ += *ip2++;
  319. }
  320.  
  321. /*
  322.  * Make a copy of the plimit structure.
  323.  * We share these structures copy-on-write after fork,
  324.  * and copy when a limit is changed.
  325.  */
  326. struct plimit *
  327. limcopy(lim)
  328.     struct plimit *lim;
  329. {
  330.     register struct plimit *copy;
  331.  
  332.     MALLOC(copy, struct plimit *, sizeof(struct plimit),
  333.         M_SUBPROC, M_WAITOK);
  334.     bcopy(lim->pl_rlimit, copy->pl_rlimit,
  335.         sizeof(struct rlimit) * RLIM_NLIMITS);
  336.     copy->p_lflags = 0;
  337.     copy->p_refcnt = 1;
  338.     return (copy);
  339. }
  340.