1*8031Sroot /* kern_resource.c 4.12 82/09/04 */ 27Sbill 37Sbill #include "../h/param.h" 47Sbill #include "../h/systm.h" 57Sbill #include "../h/acct.h" 67Sbill #include "../h/dir.h" 77Sbill #include "../h/user.h" 87Sbill #include "../h/inode.h" 97Sbill #include "../h/proc.h" 107Sbill #include "../h/seg.h" 117499Sroot #include "../h/fs.h" 127817Sroot #include "../h/uio.h" 13*8031Sroot #include "../h/vm.h" 147Sbill 15*8031Sroot getpriority() 16*8031Sroot { 17*8031Sroot register struct a { 18*8031Sroot int which; 19*8031Sroot int who; 20*8031Sroot } *uap = (struct a *)u.u_ap; 21*8031Sroot register struct proc *p; 22*8031Sroot 23*8031Sroot u.u_r.r_val1 = NZERO+20; 24*8031Sroot u.u_error = ESRCH; 25*8031Sroot switch (uap->which) { 26*8031Sroot 27*8031Sroot case PRIO_PROCESS: 28*8031Sroot if (uap->who == 0) 29*8031Sroot p = u.u_procp; 30*8031Sroot else 31*8031Sroot p = pfind(uap->who); 32*8031Sroot if (p == 0) 33*8031Sroot return; 34*8031Sroot u.u_r.r_val1 = u.u_procp->p_nice; 35*8031Sroot break; 36*8031Sroot 37*8031Sroot case PRIO_PGRP: 38*8031Sroot if (uap->who == 0) 39*8031Sroot uap->who = u.u_procp->p_pgrp; 40*8031Sroot for (p = proc; p < procNPROC; p++) 41*8031Sroot if (p->p_pgrp == uap->who && 42*8031Sroot p->p_nice < u.u_r.r_val1) { 43*8031Sroot u.u_r.r_val1 = p->p_nice; 44*8031Sroot u.u_error = 0; 45*8031Sroot } 46*8031Sroot break; 47*8031Sroot 48*8031Sroot default: 49*8031Sroot u.u_error = EINVAL; 50*8031Sroot break; 51*8031Sroot } 52*8031Sroot u.u_r.r_val1 -= NZERO; 53*8031Sroot } 54*8031Sroot 55*8031Sroot setpriority() 56*8031Sroot { 57*8031Sroot register struct a { 58*8031Sroot int which; 59*8031Sroot int who; 60*8031Sroot int prio; 61*8031Sroot } *uap = (struct a *)u.u_ap; 62*8031Sroot register struct proc *p; 63*8031Sroot 64*8031Sroot u.u_error = ESRCH; 65*8031Sroot switch (uap->which) { 66*8031Sroot 67*8031Sroot case PRIO_PROCESS: 68*8031Sroot p = pfind(uap->who); 69*8031Sroot if (p == 0) 70*8031Sroot return; 71*8031Sroot donice(p, uap->prio); 72*8031Sroot break; 73*8031Sroot 74*8031Sroot case PRIO_PGRP: 75*8031Sroot for (p = proc; p < procNPROC; p++) 76*8031Sroot if (p->p_pgrp == uap->who) 77*8031Sroot donice(p, uap->prio); 78*8031Sroot break; 79*8031Sroot 80*8031Sroot default: 81*8031Sroot u.u_error = EINVAL; 82*8031Sroot break; 83*8031Sroot } 84*8031Sroot } 85*8031Sroot 86*8031Sroot donice(p, n) 87*8031Sroot register struct proc *p; 88*8031Sroot register int n; 89*8031Sroot { 90*8031Sroot 91*8031Sroot if (u.u_uid && u.u_ruid && 92*8031Sroot u.u_uid != p->p_uid && u.u_ruid != p->p_uid) { 93*8031Sroot u.u_error = EPERM; 94*8031Sroot return; 95*8031Sroot } 96*8031Sroot n += p->p_nice; 97*8031Sroot if (n >= 2*NZERO) 98*8031Sroot n = 2*NZERO - 1; 99*8031Sroot if (n < 0) 100*8031Sroot n = 0; 101*8031Sroot if (n < p->p_nice && !suser()) 102*8031Sroot return; 103*8031Sroot p->p_nice = n; 104*8031Sroot (void) setpri(p); 105*8031Sroot if (u.u_error == ESRCH) 106*8031Sroot u.u_error = 0; 107*8031Sroot } 108*8031Sroot 109*8031Sroot setlimit() 110*8031Sroot { 111*8031Sroot register struct a { 112*8031Sroot u_int which; 113*8031Sroot struct rlimit *lim; 114*8031Sroot } *uap = (struct a *)u.u_ap; 115*8031Sroot struct rlimit alim; 116*8031Sroot register struct rlimit *alimp; 117*8031Sroot 118*8031Sroot if (uap->which >= RLIM_NLIMITS) { 119*8031Sroot u.u_error = EINVAL; 120*8031Sroot return; 121*8031Sroot } 122*8031Sroot alimp = &u.u_rlimit[uap->which]; 123*8031Sroot if (copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) { 124*8031Sroot u.u_error = EFAULT; 125*8031Sroot return; 126*8031Sroot } 127*8031Sroot if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max) 128*8031Sroot if (!suser()) 129*8031Sroot return; 130*8031Sroot switch (uap->which) { 131*8031Sroot 132*8031Sroot case RLIMIT_DATA: 133*8031Sroot if (alim.rlim_cur > ctob(MAXDSIZ)) 134*8031Sroot alim.rlim_cur = ctob(MAXDSIZ); 135*8031Sroot break; 136*8031Sroot 137*8031Sroot case RLIMIT_STACK: 138*8031Sroot if (alim.rlim_cur > ctob(MAXSSIZ)) 139*8031Sroot alim.rlim_cur = ctob(MAXSSIZ); 140*8031Sroot break; 141*8031Sroot } 142*8031Sroot *alimp = alim; 143*8031Sroot if (uap->which == RLIMIT_RSS) 144*8031Sroot u.u_procp->p_maxrss = alim.rlim_cur/NBPG; 145*8031Sroot } 146*8031Sroot 147*8031Sroot getlimit() 148*8031Sroot { 149*8031Sroot register struct a { 150*8031Sroot u_int which; 151*8031Sroot struct rlimit *rlp; 152*8031Sroot } *uap = (struct a *)u.u_ap; 153*8031Sroot 154*8031Sroot if (uap->which >= RLIM_NLIMITS) { 155*8031Sroot u.u_error = EINVAL; 156*8031Sroot return; 157*8031Sroot } 158*8031Sroot if (copyout((caddr_t)&u.u_rlimit[uap->which], uap->rlp, 159*8031Sroot sizeof (struct rlimit))) { 160*8031Sroot u.u_error = EFAULT; 161*8031Sroot return; 162*8031Sroot } 163*8031Sroot } 164*8031Sroot 165*8031Sroot getrusage() 166*8031Sroot { 167*8031Sroot register struct a { 168*8031Sroot int who; 169*8031Sroot struct rusage *rusage; 170*8031Sroot } *uap = (struct a *)u.u_ap; 171*8031Sroot register struct rusage *rup; 172*8031Sroot 173*8031Sroot switch (uap->who) { 174*8031Sroot 175*8031Sroot case RUSAGE_SELF: 176*8031Sroot rup = &u.u_ru; 177*8031Sroot break; 178*8031Sroot 179*8031Sroot case RUSAGE_CHILDREN: 180*8031Sroot rup = &u.u_cru; 181*8031Sroot break; 182*8031Sroot 183*8031Sroot default: 184*8031Sroot u.u_error = EINVAL; 185*8031Sroot return; 186*8031Sroot } 187*8031Sroot if (copyout((caddr_t)rup, uap->rusage, sizeof (struct rusage))) { 188*8031Sroot u.u_error = EFAULT; 189*8031Sroot return; 190*8031Sroot } 191*8031Sroot } 192*8031Sroot 193*8031Sroot ruadd(ru, ru2) 194*8031Sroot register struct rusage *ru, *ru2; 195*8031Sroot { 196*8031Sroot register int *ip, *ip2; 197*8031Sroot register int i; 198*8031Sroot 199*8031Sroot timevaladd(&ru->ru_utime, &ru2->ru_utime); 200*8031Sroot timevaladd(&ru->ru_stime, &ru2->ru_stime); 201*8031Sroot if (ru->ru_maxrss < ru2->ru_maxrss) 202*8031Sroot ru->ru_maxrss = ru2->ru_maxrss; 203*8031Sroot ip = &ru->ru_first; ip2 = &ru2->ru_first; 204*8031Sroot for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) 205*8031Sroot *ip++ += *ip2++; 206*8031Sroot } 207*8031Sroot 2083098Swnj struct inode *acctp; 2097499Sroot struct inode *savacctp; 2103098Swnj 2117499Sroot long acctlow = 2; /* stop accounting when < 2% data space left */ 2127499Sroot long accthigh = 4; /* resume when space risen to > 4% */ 2137499Sroot 2147Sbill /* 2157Sbill * Perform process accounting functions. 2167Sbill */ 2177Sbill sysacct() 2187Sbill { 2197Sbill register struct inode *ip; 2207Sbill register struct a { 2217Sbill char *fname; 2227Sbill } *uap; 2237Sbill 2247Sbill uap = (struct a *)u.u_ap; 2257Sbill if (suser()) { 2267499Sroot if (savacctp) { 2277499Sroot acctp = savacctp; 2287499Sroot savacctp = NULL; 2297499Sroot } 2307Sbill if (uap->fname==NULL) { 2313109Swnj if (ip = acctp) { 2327141Smckusick irele(ip); 2337Sbill acctp = NULL; 2347Sbill } 2357Sbill return; 2367Sbill } 2375990Swnj ip = namei(uchar, 0, 1); 2387Sbill if(ip == NULL) 2397Sbill return; 2407Sbill if((ip->i_mode & IFMT) != IFREG) { 2417Sbill u.u_error = EACCES; 2427Sbill iput(ip); 2437Sbill return; 2447Sbill } 2457376Skre if (acctp && (acctp->i_number != ip->i_number || 2467376Skre acctp->i_dev != ip->i_dev)) 2477376Skre irele(acctp); 2487Sbill acctp = ip; 2497121Smckusick iunlock(ip); 2507Sbill } 2517Sbill } 2527Sbill 2533098Swnj struct acct acctbuf; 2547Sbill /* 2557Sbill * On exit, write a record on the accounting file. 2567Sbill */ 2577Sbill acct() 2587Sbill { 2597Sbill register i; 2607Sbill register struct inode *ip; 2617Sbill off_t siz; 2623098Swnj register struct acct *ap = &acctbuf; 2637Sbill 2647499Sroot if (savacctp && savacctp->i_fs->fs_cstotal.cs_nbfree > 2657499Sroot accthigh * savacctp->i_fs->fs_dsize / 100) { 2667499Sroot acctp = savacctp; 2677499Sroot savacctp = NULL; 2687499Sroot printf("Accounting resumed\n"); 2697499Sroot } 2707Sbill if ((ip=acctp)==NULL) 2717Sbill return; 2727499Sroot if (acctp->i_fs->fs_cstotal.cs_nbfree < 2737499Sroot acctlow * acctp->i_fs->fs_dsize / 100) { 2747499Sroot savacctp = acctp; 2757499Sroot acctp = NULL; 2767499Sroot printf("Accounting suspended\n"); 2777499Sroot return; 2787499Sroot } 2794816Swnj ilock(ip); 2803098Swnj for (i=0; i<sizeof(ap->ac_comm); i++) 2813098Swnj ap->ac_comm[i] = u.u_comm[i]; 282*8031Sroot ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec); 283*8031Sroot ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec); 2843098Swnj ap->ac_etime = compress((long)(time - u.u_start)); 2853098Swnj ap->ac_btime = u.u_start; 2863098Swnj ap->ac_uid = u.u_ruid; 2873098Swnj ap->ac_gid = u.u_rgid; 2883098Swnj ap->ac_mem = 0; 289*8031Sroot if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec) 290*8031Sroot ap->ac_mem = 291*8031Sroot (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i; 292*8031Sroot ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock)); 2937376Skre if (u.u_ttyp) 2947376Skre ap->ac_tty = u.u_ttyd; 2957376Skre else 2967376Skre ap->ac_tty = NODEV; 2973098Swnj ap->ac_flag = u.u_acflag; 2987Sbill siz = ip->i_size; 2997817Sroot u.u_error = 3007817Sroot rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz, 3017817Sroot 1, (int *)0); 3027817Sroot if (u.u_error) 3037Sbill ip->i_size = siz; 3047121Smckusick iunlock(ip); 3057Sbill } 3067Sbill 3077Sbill /* 3087Sbill * Produce a pseudo-floating point representation 3097Sbill * with 3 bits base-8 exponent, 13 bits fraction. 3107Sbill */ 3117Sbill compress(t) 3121784Sbill register long t; 3137Sbill { 3147Sbill register exp = 0, round = 0; 3157Sbill 3167Sbill while (t >= 8192) { 3177Sbill exp++; 3187Sbill round = t&04; 3197Sbill t >>= 3; 3207Sbill } 3217Sbill if (round) { 3227Sbill t++; 3237Sbill if (t >= 8192) { 3247Sbill t >>= 3; 3257Sbill exp++; 3267Sbill } 3277Sbill } 3287Sbill return((exp<<13) + t); 3297Sbill } 3307499Sroot 331*8031Sroot #ifndef NOCOMPAT 332*8031Sroot onice() 3337499Sroot { 3347499Sroot register struct a { 335*8031Sroot int niceness; 336*8031Sroot } *uap; 3377499Sroot 338*8031Sroot uap = (struct a *)u.u_ap; 339*8031Sroot donice(u.u_procp, uap->niceness); 3407499Sroot } 341*8031Sroot #endif 342