-/* kern_resource.c 4.4 81/03/09 */
+/* kern_resource.c 4.18 82/12/17 */
#include "../h/param.h"
#include "../h/systm.h"
-#include "../h/acct.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/inode.h"
#include "../h/proc.h"
#include "../h/seg.h"
-
-struct inode *acctp;
+#include "../h/fs.h"
+#include "../h/uio.h"
+#include "../h/vm.h"
/*
- * Perform process accounting functions.
+ * Resource controls and accounting.
*/
-sysacct()
+
+getpriority()
{
- register struct inode *ip;
register struct a {
- char *fname;
- } *uap;
-
- uap = (struct a *)u.u_ap;
- if (suser()) {
- if (uap->fname==NULL) {
- if (ip = acctp) {
- plock(ip);
- iput(ip);
- acctp = NULL;
- }
+ int which;
+ int who;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p;
+
+ u.u_r.r_val1 = NZERO+20;
+ u.u_error = ESRCH;
+ switch (uap->which) {
+
+ case PRIO_PROCESS:
+ if (uap->who == 0)
+ p = u.u_procp;
+ else
+ p = pfind(uap->who);
+ if (p == 0)
return;
+ u.u_r.r_val1 = u.u_procp->p_nice;
+ u.u_error = 0;
+ break;
+
+ case PRIO_PGRP:
+ if (uap->who == 0)
+ uap->who = u.u_procp->p_pgrp;
+ for (p = proc; p < procNPROC; p++) {
+ if (p->p_stat == NULL)
+ continue;
+ if (p->p_pgrp == uap->who &&
+ p->p_nice < u.u_r.r_val1) {
+ u.u_r.r_val1 = p->p_nice;
+ u.u_error = 0;
+ }
}
- if (acctp) {
- u.u_error = EBUSY;
- return;
+ break;
+
+ case PRIO_USER:
+ if (uap->who == 0)
+ uap->who = u.u_uid;
+ for (p = proc; p < procNPROC; p++) {
+ if (p->p_stat == NULL)
+ continue;
+ if (p->p_uid == uap->who &&
+ p->p_nice < u.u_r.r_val1) {
+ u.u_r.r_val1 = p->p_nice;
+ u.u_error = 0;
+ }
}
- ip = namei(uchar, 0);
- if(ip == NULL)
+ break;
+
+ default:
+ u.u_error = EINVAL;
+ break;
+ }
+ u.u_r.r_val1 -= NZERO;
+}
+
+setpriority()
+{
+ register struct a {
+ int which;
+ int who;
+ int prio;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p;
+
+ u.u_error = ESRCH;
+ switch (uap->which) {
+
+ case PRIO_PROCESS:
+ if (uap->who == 0)
+ p = u.u_procp;
+ else
+ p = pfind(uap->who);
+ if (p == 0)
return;
- if((ip->i_mode & IFMT) != IFREG) {
- u.u_error = EACCES;
- iput(ip);
+ donice(p, uap->prio);
+ break;
+
+ case PRIO_PGRP:
+ if (uap->who == 0)
+ uap->who = u.u_procp->p_pgrp;
+ for (p = proc; p < procNPROC; p++)
+ if (p->p_pgrp == uap->who)
+ donice(p, uap->prio);
+ break;
+
+ case PRIO_USER:
+ if (uap->who == 0)
+ uap->who = u.u_uid;
+ for (p = proc; p < procNPROC; p++)
+ if (p->p_uid == uap->who)
+ donice(p, uap->prio);
+ break;
+
+ default:
+ u.u_error = EINVAL;
+ break;
+ }
+}
+
+donice(p, n)
+ register struct proc *p;
+ register int n;
+{
+
+ if (u.u_uid && u.u_ruid &&
+ u.u_uid != p->p_uid && u.u_ruid != p->p_uid) {
+ u.u_error = EACCES;
+ return;
+ }
+ n += NZERO;
+ if (n >= 2*NZERO)
+ n = 2*NZERO - 1;
+ if (n < 0)
+ n = 0;
+ if (n < p->p_nice && !suser()) {
+ u.u_error = EACCES;
+ return;
+ }
+ p->p_nice = n;
+ (void) setpri(p);
+ if (u.u_error == ESRCH)
+ u.u_error = 0;
+}
+
+setrlimit()
+{
+ register struct a {
+ u_int which;
+ struct rlimit *lim;
+ } *uap = (struct a *)u.u_ap;
+ struct rlimit alim;
+ register struct rlimit *alimp;
+
+ if (uap->which >= RLIM_NLIMITS) {
+ u.u_error = EINVAL;
+ return;
+ }
+ alimp = &u.u_rlimit[uap->which];
+ if (copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit))) {
+ u.u_error = EFAULT;
+ return;
+ }
+ if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
+ if (!suser())
return;
- }
- acctp = ip;
- prele(ip);
+ switch (uap->which) {
+
+ case RLIMIT_DATA:
+ if (alim.rlim_cur > ctob(MAXDSIZ))
+ alim.rlim_cur = ctob(MAXDSIZ);
+ break;
+
+ case RLIMIT_STACK:
+ if (alim.rlim_cur > ctob(MAXSSIZ))
+ alim.rlim_cur = ctob(MAXSSIZ);
+ break;
}
+ *alimp = alim;
+ if (uap->which == RLIMIT_RSS)
+ u.u_procp->p_maxrss = alim.rlim_cur/NBPG;
}
-struct acct acctbuf;
-/*
- * On exit, write a record on the accounting file.
- */
-acct()
+getrlimit()
+{
+ register struct a {
+ u_int which;
+ struct rlimit *rlp;
+ } *uap = (struct a *)u.u_ap;
+
+ if (uap->which >= RLIM_NLIMITS) {
+ u.u_error = EINVAL;
+ return;
+ }
+ if (copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp,
+ sizeof (struct rlimit))) {
+ u.u_error = EFAULT;
+ return;
+ }
+}
+
+getrusage()
{
- register i;
- register struct inode *ip;
- off_t siz;
- register struct acct *ap = &acctbuf;
+ register struct a {
+ int who;
+ struct rusage *rusage;
+ } *uap = (struct a *)u.u_ap;
+ register struct rusage *rup;
- if ((ip=acctp)==NULL)
+ switch (uap->who) {
+
+ case RUSAGE_SELF:
+ rup = &u.u_ru;
+ break;
+
+ case RUSAGE_CHILDREN:
+ rup = &u.u_cru;
+ break;
+
+ default:
+ u.u_error = EINVAL;
return;
- plock(ip);
- for (i=0; i<sizeof(ap->ac_comm); i++)
- ap->ac_comm[i] = u.u_comm[i];
- ap->ac_utime = compress((long)u.u_vm.vm_utime);
- ap->ac_stime = compress((long)u.u_vm.vm_stime);
- ap->ac_etime = compress((long)(time - u.u_start));
- ap->ac_btime = u.u_start;
- ap->ac_uid = u.u_ruid;
- ap->ac_gid = u.u_rgid;
- ap->ac_mem = 0;
- if (i = u.u_vm.vm_utime + u.u_vm.vm_stime)
- ap->ac_mem = (u.u_vm.vm_ixrss + u.u_vm.vm_idsrss) / i;
- ap->ac_io = compress((long)(u.u_vm.vm_inblk + u.u_vm.vm_oublk));
- ap->ac_tty = u.u_ttyd;
- ap->ac_flag = u.u_acflag;
- siz = ip->i_size;
- u.u_offset = siz;
- u.u_base = (caddr_t)ap;
- u.u_count = sizeof(acctbuf);
- u.u_segflg = 1;
- u.u_error = 0;
- writei(ip);
- if(u.u_error)
- ip->i_size = siz;
- prele(ip);
+ }
+ if (copyout((caddr_t)rup, (caddr_t)uap->rusage,
+ sizeof (struct rusage))) {
+ u.u_error = EFAULT;
+ return;
+ }
}
-/*
- * Produce a pseudo-floating point representation
- * with 3 bits base-8 exponent, 13 bits fraction.
- */
-compress(t)
-register long t;
+ruadd(ru, ru2)
+ register struct rusage *ru, *ru2;
+{
+ register long *ip, *ip2;
+ register int i;
+
+ timevaladd(&ru->ru_utime, &ru2->ru_utime);
+ timevaladd(&ru->ru_stime, &ru2->ru_stime);
+ if (ru->ru_maxrss < ru2->ru_maxrss)
+ ru->ru_maxrss = ru2->ru_maxrss;
+ ip = &ru->ru_first; ip2 = &ru2->ru_first;
+ for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
+ *ip++ += *ip2++;
+}
+
+#ifndef NOCOMPAT
+onice()
+{
+ register struct a {
+ int niceness;
+ } *uap = (struct a *)u.u_ap;
+ register struct proc *p = u.u_procp;
+
+ donice(p, (p->p_nice-NZERO)+uap->niceness);
+}
+
+#include "../h/times.h"
+
+otimes()
{
- register exp = 0, round = 0;
+ register struct a {
+ struct tms *tmsb;
+ } *uap = (struct a *)u.u_ap;
+ struct tms atms;
+
+ atms.tms_utime = scale60(&u.u_ru.ru_utime);
+ atms.tms_stime = scale60(&u.u_ru.ru_stime);
+ atms.tms_cutime = scale60(&u.u_cru.ru_utime);
+ atms.tms_cstime = scale60(&u.u_cru.ru_stime);
+ if (copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms))) {
+ u.u_error = EFAULT;
+ return;
+ }
+}
+
+scale60(tvp)
+ register struct timeval *tvp;
+{
+
+ return (tvp->tv_sec * 60 + tvp->tv_usec / 16667);
+}
+
+#include "../h/vtimes.h"
+
+ovtimes()
+{
+ register struct a {
+ struct vtimes *par;
+ struct vtimes *chi;
+ } *uap = (struct a *)u.u_ap;
+ struct vtimes avt;
- while (t >= 8192) {
- exp++;
- round = t&04;
- t >>= 3;
+ if (uap->par) {
+ getvtimes(&u.u_ru, &avt);
+ if (copyout((caddr_t)&avt, (caddr_t)uap->par, sizeof (avt))) {
+ u.u_error = EFAULT;
+ return;
+ }
}
- if (round) {
- t++;
- if (t >= 8192) {
- t >>= 3;
- exp++;
+ if (uap->chi) {
+ getvtimes(&u.u_cru, &avt);
+ if (copyout((caddr_t)&avt, (caddr_t)uap->chi, sizeof (avt))) {
+ u.u_error = EFAULT;
+ return;
}
}
- return((exp<<13) + t);
+}
+
+getvtimes(aru, avt)
+ register struct rusage *aru;
+ register struct vtimes *avt;
+{
+
+ avt->vm_utime = scale60(&aru->ru_utime);
+ avt->vm_stime = scale60(&aru->ru_stime);
+ avt->vm_idsrss = ((aru->ru_idrss+aru->ru_isrss) / hz) * 60;
+ avt->vm_ixrss = aru->ru_ixrss / hz * 60;
+ avt->vm_maxrss = aru->ru_maxrss;
+ avt->vm_majflt = aru->ru_majflt;
+ avt->vm_minflt = aru->ru_minflt;
+ avt->vm_nswap = aru->ru_nswap;
+ avt->vm_inblk = aru->ru_inblock;
+ avt->vm_oublk = aru->ru_oublock;
+}
+
+ovlimit()
+{
+
+ u.u_error = EACCES;
}