Ultrix-3.1/sys/sys/acct.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
/*
* SCCSID: @(#)acct.c 3.0 4/21/86
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/acct.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/inode.h>
#include <sys/proc.h>
#include <sys/seg.h>
#include <sys/text.h>
#include <sys/lock.h>
#ifdef ACCT
/*
* Perform process accounting functions.
*/
sysacct()
{
register struct inode *ip;
register struct a {
char *fname;
} *uap;
uap = (struct a *)u.u_ap;
if (suser()) {
if (uap->fname==NULL) {
if (acctp) {
plock(acctp);
iput(acctp);
acctp = NULL;
}
return;
}
if (acctp) {
u.u_error = EBUSY;
return;
}
#ifdef UCB_SYMLINKS
ip = namei(uchar, LOOKUP, 1);
#else UCB_SYMLINKS
ip = namei(uchar, LOOKUP);
#endif UCB_SYMLINKS
if(ip == NULL)
return;
if((ip->i_mode & IFMT) != IFREG) {
u.u_error = EACCES;
iput(ip);
return;
}
acctp = ip;
prele(ip);
}
}
#endif ACCT
/*
* On exit, write a record on the accounting file.
*/
acct()
{
#ifdef ACCT
register i;
register struct inode *ip;
off_t siz;
if ((ip=acctp)==NULL)
return;
plock(ip);
for (i=0; i<sizeof(acctbuf.ac_comm); i++)
acctbuf.ac_comm[i] = u.u_comm[i];
acctbuf.ac_utime = compress(u.u_utime);
acctbuf.ac_stime = compress(u.u_stime);
acctbuf.ac_etime = compress(time - u.u_start);
acctbuf.ac_btime = u.u_start;
acctbuf.ac_uid = u.u_ruid;
acctbuf.ac_gid = u.u_rgid;
acctbuf.ac_mem = 0;
acctbuf.ac_io = 0;
acctbuf.ac_tty = u.u_ttyd;
acctbuf.ac_flag = u.u_acflag;
siz = ip->i_size;
u.u_offset = siz;
u.u_base = (caddr_t)&acctbuf;
u.u_count = sizeof(acctbuf);
u.u_segflg = 1;
u.u_error = 0;
u.u_limit = (daddr_t)5000;
writei(ip);
if(u.u_error)
ip->i_size = siz;
prele(ip);
#endif ACCT
}
#ifdef ACCT
/*
* Produce a pseudo-floating point representation
* with 3 bits base-8 exponent, 13 bits fraction.
*/
static
compress(t)
register time_t t;
{
register exp = 0, round = 0;
while (t >= 8192) {
exp++;
round = t&04;
t >>= 3;
}
if (round) {
t++;
if (t >= 8192) {
t >>= 3;
exp++;
}
}
return((exp<<13) + t);
}
#endif ACCT
/*
* lock user into core as much
* as possible. swapping may still
* occur if core grows.
*/
char runlock; /* used to tell sched when to call shuffle */
syslock()
{
register struct proc *p;
register struct a {
int flag;
} *uap;
register struct text *xp;
uap = (struct a *)u.u_ap;
if (suser()) {
p = u.u_procp;
xp = p->p_textp;
switch(uap->flag) {
case UNLOCK: /* unlock a process */
if (p->p_flag&(SULKMSK)) {
punlock();
return;
}
goto bad;
case TXTLOCK: /* lock text segment of a shared text */
if ((p->p_flag&(SULOCKT)) || (u.u_procp->p_textp==NULL))
goto bad;
p->p_flag |= (SULOCKT);
if (xp->x_lcount++ == 0) {
runlock++;
xp->x_ccount++;
}
break;
case DATLOCK: /* lock data segment of a shared text */
if ((p->p_flag&(SULOCKD)) || (u.u_procp->p_textp==NULL))
goto bad;
p->p_flag |= (SULOCKD);
runlock++;
break;
/* The v7 lock call will satisfy this case */
case PROCLOCK: /* lock text and data of a process */
if (p->p_flag&(SULKMSK))
goto bad;
p->p_flag |= (SULKMSK);
if (u.u_procp->p_textp != NULL)
if (xp->x_lcount++ == 0) {
xp->x_ccount++;
}
runlock++;
break;
default:
goto bad;
}
if (runlock==0)
return;
if (runout) { /* wakeup sched to shuffle */
runout = 0;
wakeup((caddr_t)&runout);
}
sleep((caddr_t)&runlock,PZERO-1); /* shuffle will wake us up */
return;
bad:
u.u_error = EINVAL;
}
}
punlock()
{
struct text *xp;
u.u_procp->p_flag &= ~(SULKMSK);
if (((xp=u.u_procp->p_textp) != NULL) && ( --(xp->x_lcount) == 0))
xccdec(xp);
runlock++;
}