123373Smckusick /* 229093Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323373Smckusick * All rights reserved. The Berkeley software License Agreement 423373Smckusick * specifies the terms and conditions for redistribution. 523373Smckusick * 6*43365Smckusick * @(#)kern_resource.c 7.8 (Berkeley) 06/21/90 723373Smckusick */ 87Sbill 917092Sbloom #include "param.h" 10*43365Smckusick #include "syscontext.h" 1117092Sbloom #include "proc.h" 127Sbill 138176Sroot /* 148176Sroot * Resource controls and accounting. 158176Sroot */ 168176Sroot 17*43365Smckusick getpriority(curp, uap, retval) 18*43365Smckusick struct proc *curp; 19*43365Smckusick register struct args { 208031Sroot int which; 218031Sroot int who; 22*43365Smckusick } *uap; 23*43365Smckusick int *retval; 24*43365Smckusick { 258031Sroot register struct proc *p; 2635810Smarc register int low = PRIO_MAX + 1; 278031Sroot 288031Sroot switch (uap->which) { 298031Sroot 308031Sroot case PRIO_PROCESS: 318031Sroot if (uap->who == 0) 32*43365Smckusick p = curp; 338031Sroot else 348031Sroot p = pfind(uap->who); 358031Sroot if (p == 0) 3628149Skarels break; 3717400Skarels low = p->p_nice; 388031Sroot break; 398031Sroot 4035810Smarc case PRIO_PGRP: { 4135810Smarc register struct pgrp *pg; 4235810Smarc 438031Sroot if (uap->who == 0) 44*43365Smckusick pg = curp->p_pgrp; 4535810Smarc else if ((pg = pgfind(uap->who)) == NULL) 4635810Smarc break; 4735810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 4835810Smarc if (p->p_nice < low) 4917400Skarels low = p->p_nice; 508176Sroot } 518031Sroot break; 5235810Smarc } 538031Sroot 548176Sroot case PRIO_USER: 558176Sroot if (uap->who == 0) 56*43365Smckusick uap->who = p->p_uid; 5716530Skarels for (p = allproc; p != NULL; p = p->p_nxt) { 588176Sroot if (p->p_uid == uap->who && 5917400Skarels p->p_nice < low) 6017400Skarels low = p->p_nice; 618176Sroot } 628176Sroot break; 638176Sroot 648031Sroot default: 65*43365Smckusick RETURN (EINVAL); 668031Sroot } 67*43365Smckusick if (low == PRIO_MAX + 1) 68*43365Smckusick RETURN (ESRCH); 69*43365Smckusick *retval = low; 70*43365Smckusick RETURN (0); 718031Sroot } 728031Sroot 73*43365Smckusick /* ARGSUSED */ 74*43365Smckusick setpriority(curp, uap, retval) 75*43365Smckusick struct proc *curp; 76*43365Smckusick register struct args { 778031Sroot int which; 788031Sroot int who; 798031Sroot int prio; 80*43365Smckusick } *uap; 81*43365Smckusick int *retval; 82*43365Smckusick { 838031Sroot register struct proc *p; 84*43365Smckusick int found = 0, error = 0; 858031Sroot 868031Sroot switch (uap->which) { 878031Sroot 888031Sroot case PRIO_PROCESS: 898176Sroot if (uap->who == 0) 90*43365Smckusick p = curp; 918176Sroot else 928176Sroot p = pfind(uap->who); 938031Sroot if (p == 0) 9428149Skarels break; 95*43365Smckusick error = donice(curp, p, uap->prio); 9617400Skarels found++; 978031Sroot break; 988031Sroot 9935810Smarc case PRIO_PGRP: { 10035810Smarc register struct pgrp *pg; 10135810Smarc 1028176Sroot if (uap->who == 0) 103*43365Smckusick pg = curp->p_pgrp; 10435810Smarc else if ((pg = pgfind(uap->who)) == NULL) 10535810Smarc break; 10635810Smarc for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) { 107*43365Smckusick error = donice(curp, p, uap->prio); 10835810Smarc found++; 10935810Smarc } 1108031Sroot break; 11135810Smarc } 1128031Sroot 1138176Sroot case PRIO_USER: 1148176Sroot if (uap->who == 0) 115*43365Smckusick uap->who = p->p_uid; 11616530Skarels for (p = allproc; p != NULL; p = p->p_nxt) 11717400Skarels if (p->p_uid == uap->who) { 118*43365Smckusick error = donice(curp, p, uap->prio); 11917400Skarels found++; 12017400Skarels } 1218176Sroot break; 1228176Sroot 1238031Sroot default: 124*43365Smckusick RETURN (EINVAL); 1258031Sroot } 12617400Skarels if (found == 0) 127*43365Smckusick RETURN (ESRCH); 128*43365Smckusick RETURN (0); 1298031Sroot } 1308031Sroot 131*43365Smckusick donice(curp, chgp, n) 132*43365Smckusick register struct proc *curp, *chgp; 1338031Sroot register int n; 1348031Sroot { 1358031Sroot 136*43365Smckusick if (curp->p_uid && curp->p_ruid && 137*43365Smckusick curp->p_uid != chgp->p_uid && curp->p_ruid != chgp->p_uid) 138*43365Smckusick return (EPERM); 13917400Skarels if (n > PRIO_MAX) 14017400Skarels n = PRIO_MAX; 14117400Skarels if (n < PRIO_MIN) 14217400Skarels n = PRIO_MIN; 143*43365Smckusick if (n < chgp->p_nice && suser(u.u_cred, &u.u_acflag)) 144*43365Smckusick return (EACCES); 145*43365Smckusick chgp->p_nice = n; 146*43365Smckusick (void) setpri(chgp); 147*43365Smckusick return (0); 1488031Sroot } 1498031Sroot 150*43365Smckusick /* ARGSUSED */ 151*43365Smckusick setrlimit(p, uap, retval) 152*43365Smckusick struct proc *p; 153*43365Smckusick register struct args { 1548031Sroot u_int which; 1558031Sroot struct rlimit *lim; 156*43365Smckusick } *uap; 157*43365Smckusick int *retval; 158*43365Smckusick { 1598031Sroot struct rlimit alim; 1608031Sroot register struct rlimit *alimp; 16125257Skarels extern unsigned maxdmap; 162*43365Smckusick int error; 1638031Sroot 164*43365Smckusick if (uap->which >= RLIM_NLIMITS) 165*43365Smckusick RETURN (EINVAL); 1668031Sroot alimp = &u.u_rlimit[uap->which]; 167*43365Smckusick if (error = 168*43365Smckusick copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) 169*43365Smckusick RETURN (error); 1708031Sroot if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 171*43365Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 172*43365Smckusick RETURN (error); 1738031Sroot switch (uap->which) { 1748031Sroot 1758031Sroot case RLIMIT_DATA: 17618279Smckusick if (alim.rlim_cur > maxdmap) 17718279Smckusick alim.rlim_cur = maxdmap; 17818279Smckusick if (alim.rlim_max > maxdmap) 17918279Smckusick alim.rlim_max = maxdmap; 1808031Sroot break; 1818031Sroot 1828031Sroot case RLIMIT_STACK: 18318279Smckusick if (alim.rlim_cur > maxdmap) 18418279Smckusick alim.rlim_cur = maxdmap; 18518279Smckusick if (alim.rlim_max > maxdmap) 18618279Smckusick alim.rlim_max = maxdmap; 1878031Sroot break; 1888031Sroot } 1898031Sroot *alimp = alim; 1908031Sroot if (uap->which == RLIMIT_RSS) 191*43365Smckusick p->p_maxrss = alim.rlim_cur/NBPG; 192*43365Smckusick RETURN (0); 1938031Sroot } 1948031Sroot 195*43365Smckusick /* ARGSUSED */ 196*43365Smckusick getrlimit(p, uap, retval) 197*43365Smckusick struct proc *p; 198*43365Smckusick register struct args { 1998031Sroot u_int which; 2008031Sroot struct rlimit *rlp; 201*43365Smckusick } *uap; 202*43365Smckusick int *retval; 203*43365Smckusick { 2048031Sroot 205*43365Smckusick if (uap->which >= RLIM_NLIMITS) 206*43365Smckusick RETURN (EINVAL); 207*43365Smckusick RETURN (copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp, 208*43365Smckusick sizeof (struct rlimit))); 2098031Sroot } 2108031Sroot 211*43365Smckusick /* ARGSUSED */ 212*43365Smckusick getrusage(p, uap, retval) 213*43365Smckusick register struct proc *p; 214*43365Smckusick register struct args { 2158031Sroot int who; 2168031Sroot struct rusage *rusage; 217*43365Smckusick } *uap; 218*43365Smckusick int *retval; 219*43365Smckusick { 2208031Sroot register struct rusage *rup; 2218031Sroot 2228031Sroot switch (uap->who) { 2238031Sroot 22440705Skarels case RUSAGE_SELF: { 22540705Skarels int s; 22640705Skarels 2278031Sroot rup = &u.u_ru; 22840705Skarels s = splclock(); 22940705Skarels rup->ru_stime = p->p_stime; 23040705Skarels rup->ru_utime = p->p_utime; 23140705Skarels splx(s); 2328031Sroot break; 23340705Skarels } 2348031Sroot 2358031Sroot case RUSAGE_CHILDREN: 2368031Sroot rup = &u.u_cru; 2378031Sroot break; 2388031Sroot 2398031Sroot default: 240*43365Smckusick RETURN (EINVAL); 2418031Sroot } 242*43365Smckusick RETURN (copyout((caddr_t)rup, (caddr_t)uap->rusage, 243*43365Smckusick sizeof (struct rusage))); 2448031Sroot } 2458031Sroot 2468031Sroot ruadd(ru, ru2) 2478031Sroot register struct rusage *ru, *ru2; 2488031Sroot { 2498666Sroot register long *ip, *ip2; 2508031Sroot register int i; 2518031Sroot 2528031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 2538031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 2548031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 2558031Sroot ru->ru_maxrss = ru2->ru_maxrss; 2568031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 2578031Sroot for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 2588031Sroot *ip++ += *ip2++; 2598031Sroot } 260