xref: /inferno-os/emu/Irix/os.c (revision 1343b7e5fc7e671a93eb5ed909dde7bb5f6c87cf)
137da2899SCharles.Forsyth /* Link with -lfpe. See man pages for fpc
237da2899SCharles.Forsyth  * and /usr/include/sigfpe.h, sys/fpu.h.
337da2899SCharles.Forsyth  */
437da2899SCharles.Forsyth #include	"dat.h"
537da2899SCharles.Forsyth #include	"fns.h"
637da2899SCharles.Forsyth #include	"error.h"
737da2899SCharles.Forsyth #include	<time.h>
837da2899SCharles.Forsyth #include	<ulocks.h>
937da2899SCharles.Forsyth #include	<termios.h>
1037da2899SCharles.Forsyth #include 	<sigfpe.h>
1137da2899SCharles.Forsyth #include	<sys/prctl.h>
1237da2899SCharles.Forsyth #include 	<sys/fpu.h>
1337da2899SCharles.Forsyth #include	<sys/cachectl.h>
1437da2899SCharles.Forsyth #undef _POSIX_SOURCE		/* SGI incompetence */
1537da2899SCharles.Forsyth #include	<signal.h>
1637da2899SCharles.Forsyth #define _BSD_TIME
1737da2899SCharles.Forsyth /* for gettimeofday(), which isn't POSIX,
1837da2899SCharles.Forsyth  * but is fairly common
1937da2899SCharles.Forsyth  */
2037da2899SCharles.Forsyth #include 	<sys/time.h>
2137da2899SCharles.Forsyth #define _POSIX_SOURCE
2237da2899SCharles.Forsyth #include 	<pwd.h>
2337da2899SCharles.Forsyth 
2437da2899SCharles.Forsyth extern	int	rebootargc;
2537da2899SCharles.Forsyth extern	char**	rebootargv;
2637da2899SCharles.Forsyth 
2737da2899SCharles.Forsyth int	gidnobody = -1;
2837da2899SCharles.Forsyth int	uidnobody = -1;
2937da2899SCharles.Forsyth Proc**	Xup;
3037da2899SCharles.Forsyth 
3137da2899SCharles.Forsyth #define MAXSPROC 30000	/* max procs == MAXPID */
3237da2899SCharles.Forsyth static int	sproctbl[MAXSPROC];
3337da2899SCharles.Forsyth 
3437da2899SCharles.Forsyth enum
3537da2899SCharles.Forsyth {
3637da2899SCharles.Forsyth 	KSTACK	= 64*1024,
3737da2899SCharles.Forsyth 	DELETE	= 0x7F
3837da2899SCharles.Forsyth };
3937da2899SCharles.Forsyth char *hosttype = "Irix";
4037da2899SCharles.Forsyth char *cputype = "mips";
4137da2899SCharles.Forsyth 
4237da2899SCharles.Forsyth extern int dflag;
4337da2899SCharles.Forsyth 
4437da2899SCharles.Forsyth void
pexit(char * msg,int t)4537da2899SCharles.Forsyth pexit(char *msg, int t)
4637da2899SCharles.Forsyth {
4737da2899SCharles.Forsyth 	Osenv *e;
4837da2899SCharles.Forsyth 
4937da2899SCharles.Forsyth 	lock(&procs.l);
5037da2899SCharles.Forsyth 	if(up->prev)
5137da2899SCharles.Forsyth 		up->prev->next = up->next;
5237da2899SCharles.Forsyth 	else
5337da2899SCharles.Forsyth 		procs.head = up->next;
5437da2899SCharles.Forsyth 
5537da2899SCharles.Forsyth 	if(up->next)
5637da2899SCharles.Forsyth 		up->next->prev = up->prev;
5737da2899SCharles.Forsyth 	else
5837da2899SCharles.Forsyth 		procs.tail = up->prev;
5937da2899SCharles.Forsyth 
6037da2899SCharles.Forsyth 	sproctbl[getpid()] = -1;
6137da2899SCharles.Forsyth 
6237da2899SCharles.Forsyth 	unlock(&procs.l);
6337da2899SCharles.Forsyth 
6437da2899SCharles.Forsyth /*	print("pexit: %s: %s\n", up->text, msg); /**/
6537da2899SCharles.Forsyth 	e = up->env;
6637da2899SCharles.Forsyth 	if(e != nil) {
6737da2899SCharles.Forsyth 		closefgrp(e->fgrp);
6837da2899SCharles.Forsyth 		closepgrp(e->pgrp);
6937da2899SCharles.Forsyth 		closeegrp(e->egrp);
7037da2899SCharles.Forsyth 		closesigs(e->sigs);
7137da2899SCharles.Forsyth 	}
7237da2899SCharles.Forsyth 	free(up->prog);
7337da2899SCharles.Forsyth 	free(up);
7437da2899SCharles.Forsyth 	exit(0);
7537da2899SCharles.Forsyth }
7637da2899SCharles.Forsyth 
7737da2899SCharles.Forsyth static void
tramp(void * p,size_t stacksz)7837da2899SCharles.Forsyth tramp(void *p, size_t stacksz)
7937da2899SCharles.Forsyth {
8037da2899SCharles.Forsyth 	up = p;
8137da2899SCharles.Forsyth 	up->sigid = getpid();
8237da2899SCharles.Forsyth 	up->func(up->arg);
8337da2899SCharles.Forsyth 	pexit("", 0);
8437da2899SCharles.Forsyth }
8537da2899SCharles.Forsyth 
86*1343b7e5Sforsyth void
kproc(char * name,void (* func)(void *),void * arg,int flags)8737da2899SCharles.Forsyth kproc(char *name, void (*func)(void*), void *arg, int flags)
8837da2899SCharles.Forsyth {
8937da2899SCharles.Forsyth 	Proc *p;
9037da2899SCharles.Forsyth 	Pgrp *pg;
9137da2899SCharles.Forsyth 	Fgrp *fg;
9237da2899SCharles.Forsyth 	Egrp *eg;
9337da2899SCharles.Forsyth 	int pid;
9437da2899SCharles.Forsyth 	int id;
9537da2899SCharles.Forsyth 	int i;
9637da2899SCharles.Forsyth 
9737da2899SCharles.Forsyth 	p = newproc();
9837da2899SCharles.Forsyth 
9937da2899SCharles.Forsyth 	if(flags & KPDUPPG) {
10037da2899SCharles.Forsyth 		pg = up->env->pgrp;
10137da2899SCharles.Forsyth 		incref(&pg->r);
10237da2899SCharles.Forsyth 		p->env->pgrp = pg;
10337da2899SCharles.Forsyth 	}
10437da2899SCharles.Forsyth 	if(flags & KPDUPFDG) {
10537da2899SCharles.Forsyth 		fg = up->env->fgrp;
10637da2899SCharles.Forsyth 		incref(&fg->r);
10737da2899SCharles.Forsyth 		p->env->fgrp = fg;
10837da2899SCharles.Forsyth 	}
10937da2899SCharles.Forsyth 	if(flags & KPDUPENVG) {
11037da2899SCharles.Forsyth 		eg = up->env->egrp;
11137da2899SCharles.Forsyth 		incref(&eg->r);
11237da2899SCharles.Forsyth 		p->env->egrp = eg;
11337da2899SCharles.Forsyth 	}
11437da2899SCharles.Forsyth 
11537da2899SCharles.Forsyth 	p->env->uid = up->env->uid;
11637da2899SCharles.Forsyth 	p->env->gid = up->env->gid;
11737da2899SCharles.Forsyth 	kstrdup(&p->env->user, up->env->user);
11837da2899SCharles.Forsyth 
11937da2899SCharles.Forsyth 	strcpy(p->text, name);
12037da2899SCharles.Forsyth 
12137da2899SCharles.Forsyth 	p->func = func;
12237da2899SCharles.Forsyth 	p->arg = arg;
12337da2899SCharles.Forsyth 
12437da2899SCharles.Forsyth 	lock(&procs.l);
12537da2899SCharles.Forsyth 	if(procs.tail != nil) {
12637da2899SCharles.Forsyth 		p->prev = procs.tail;
12737da2899SCharles.Forsyth 		procs.tail->next = p;
12837da2899SCharles.Forsyth 	}
12937da2899SCharles.Forsyth 	else {
13037da2899SCharles.Forsyth 		procs.head = p;
13137da2899SCharles.Forsyth 		p->prev = nil;
13237da2899SCharles.Forsyth 	}
13337da2899SCharles.Forsyth 	procs.tail = p;
13437da2899SCharles.Forsyth 
13537da2899SCharles.Forsyth 	for(i = 1; i < MAXSPROC; i++) {
13637da2899SCharles.Forsyth 		if(sproctbl[i] == -1) {
13737da2899SCharles.Forsyth 			break;
13837da2899SCharles.Forsyth 		}
13937da2899SCharles.Forsyth 	}
14037da2899SCharles.Forsyth 
14137da2899SCharles.Forsyth 	if(i==MAXSPROC)
14237da2899SCharles.Forsyth 		return -1;
14337da2899SCharles.Forsyth 
14437da2899SCharles.Forsyth 	sproctbl[i] = -i - 1; /* temporary hold of table index outside of lock */
14537da2899SCharles.Forsyth 
14637da2899SCharles.Forsyth 	unlock(&procs.l);
14737da2899SCharles.Forsyth 
14837da2899SCharles.Forsyth 	pid = sprocsp(tramp, PR_SALL, p, 0, KSTACK);
14937da2899SCharles.Forsyth 
150*1343b7e5Sforsyth 	if(pid >= 0)
15137da2899SCharles.Forsyth 		sproctbl[i] = pid;
15237da2899SCharles.Forsyth 	else
15337da2899SCharles.Forsyth 		sproctbl[i] = -1;
15437da2899SCharles.Forsyth }
15537da2899SCharles.Forsyth 
15637da2899SCharles.Forsyth void
osblock(void)15737da2899SCharles.Forsyth osblock(void)
15837da2899SCharles.Forsyth {
15937da2899SCharles.Forsyth 	blockproc(up->sigid);
16037da2899SCharles.Forsyth }
16137da2899SCharles.Forsyth 
16237da2899SCharles.Forsyth void
osready(Proc * p)16337da2899SCharles.Forsyth osready(Proc *p)
16437da2899SCharles.Forsyth {
16537da2899SCharles.Forsyth 	unblockproc(p->sigid);
16637da2899SCharles.Forsyth }
16737da2899SCharles.Forsyth 
16837da2899SCharles.Forsyth void
trapUSR1(void)16937da2899SCharles.Forsyth trapUSR1(void)
17037da2899SCharles.Forsyth {
17137da2899SCharles.Forsyth 	int intwait;
17237da2899SCharles.Forsyth 
17337da2899SCharles.Forsyth 	intwait = up->intwait;
17437da2899SCharles.Forsyth 	up->intwait = 0;	/* clear it to let proc continue in osleave */
17537da2899SCharles.Forsyth 
17637da2899SCharles.Forsyth 	if(up->type != Interp)		/* Used to unblock pending I/O */
17737da2899SCharles.Forsyth 		return;
17837da2899SCharles.Forsyth 
17937da2899SCharles.Forsyth 	if(intwait == 0)		/* Not posted so it's a sync error */
18037da2899SCharles.Forsyth 		disfault(nil, Eintr);	/* Should never happen */
18137da2899SCharles.Forsyth }
18237da2899SCharles.Forsyth 
18337da2899SCharles.Forsyth void
trapILL(void)18437da2899SCharles.Forsyth trapILL(void)
18537da2899SCharles.Forsyth {
18637da2899SCharles.Forsyth 	disfault(nil, "Illegal instruction");
18737da2899SCharles.Forsyth }
18837da2899SCharles.Forsyth 
18937da2899SCharles.Forsyth void
trapBUS(void)19037da2899SCharles.Forsyth trapBUS(void)
19137da2899SCharles.Forsyth {
19237da2899SCharles.Forsyth 	disfault(nil, "Bus error");
19337da2899SCharles.Forsyth }
19437da2899SCharles.Forsyth 
19537da2899SCharles.Forsyth void
trapSEGV(void)19637da2899SCharles.Forsyth trapSEGV(void)
19737da2899SCharles.Forsyth {
19837da2899SCharles.Forsyth 	disfault(nil, "Segmentation violation");
19937da2899SCharles.Forsyth }
20037da2899SCharles.Forsyth 
20137da2899SCharles.Forsyth /*
20237da2899SCharles.Forsyth  * This is not a signal handler but rather a vector from real/FPcontrol-Irix.c
20337da2899SCharles.Forsyth  */
20437da2899SCharles.Forsyth void
trapFPE(unsigned exception[5],int value[2])20537da2899SCharles.Forsyth trapFPE(unsigned exception[5], int value[2])
20637da2899SCharles.Forsyth {
20737da2899SCharles.Forsyth 	disfault(nil, "Floating point exception");
20837da2899SCharles.Forsyth }
20937da2899SCharles.Forsyth 
21037da2899SCharles.Forsyth void
oshostintr(Proc * p)21137da2899SCharles.Forsyth oshostintr(Proc *p)
21237da2899SCharles.Forsyth {
21337da2899SCharles.Forsyth 	kill(p->sigid, SIGUSR1);
21437da2899SCharles.Forsyth }
21537da2899SCharles.Forsyth 
21637da2899SCharles.Forsyth void
oslongjmp(void * regs,osjmpbuf env,int val)21737da2899SCharles.Forsyth oslongjmp(void *regs, osjmpbuf env, int val)
21837da2899SCharles.Forsyth {
21937da2899SCharles.Forsyth 	USED(regs);
22037da2899SCharles.Forsyth 	siglongjmp(env, val);
22137da2899SCharles.Forsyth }
22237da2899SCharles.Forsyth 
22337da2899SCharles.Forsyth static struct termios tinit;
22437da2899SCharles.Forsyth 
22537da2899SCharles.Forsyth static void
termset(void)22637da2899SCharles.Forsyth termset(void)
22737da2899SCharles.Forsyth {
22837da2899SCharles.Forsyth 	struct termios t;
22937da2899SCharles.Forsyth 
23037da2899SCharles.Forsyth 	tcgetattr(0, &t);
23137da2899SCharles.Forsyth 	tinit = t;
23237da2899SCharles.Forsyth 	t.c_lflag &= ~(ICANON|ECHO|ISIG);
23337da2899SCharles.Forsyth 	t.c_cc[VMIN] = 1;
23437da2899SCharles.Forsyth 	t.c_cc[VTIME] = 0;
23537da2899SCharles.Forsyth 	tcsetattr(0, TCSANOW, &t);
23637da2899SCharles.Forsyth }
23737da2899SCharles.Forsyth 
23837da2899SCharles.Forsyth static void
termrestore(void)23937da2899SCharles.Forsyth termrestore(void)
24037da2899SCharles.Forsyth {
24137da2899SCharles.Forsyth 	tcsetattr(0, TCSANOW, &tinit);
24237da2899SCharles.Forsyth 
24337da2899SCharles.Forsyth /*	if(sproctbl[0] < 0)
24437da2899SCharles.Forsyth 		panic("corrupt sproc tbl");
24537da2899SCharles.Forsyth 
24637da2899SCharles.Forsyth 	kill(sproctbl[0], SIGUSR2);
24737da2899SCharles.Forsyth 	sginap(10000); */
24837da2899SCharles.Forsyth }
24937da2899SCharles.Forsyth 
25037da2899SCharles.Forsyth void
trapUSR2(void)25137da2899SCharles.Forsyth trapUSR2(void)
25237da2899SCharles.Forsyth {
25337da2899SCharles.Forsyth 	int i;
25437da2899SCharles.Forsyth 
25537da2899SCharles.Forsyth 	for(i = MAXSPROC - 1; i > 0; i--) {
25637da2899SCharles.Forsyth 		if(sproctbl[i] != -1)
25737da2899SCharles.Forsyth 			kill(sproctbl[i], SIGKILL);
25837da2899SCharles.Forsyth 		sproctbl[i] = -1;
25937da2899SCharles.Forsyth 	}
26037da2899SCharles.Forsyth 
26137da2899SCharles.Forsyth 	execvp(rebootargv[0], rebootargv);
26237da2899SCharles.Forsyth 	panic("reboot failure");
26337da2899SCharles.Forsyth }
26437da2899SCharles.Forsyth 
26537da2899SCharles.Forsyth void
cleanexit(int x)26637da2899SCharles.Forsyth cleanexit(int x)
26737da2899SCharles.Forsyth {
26837da2899SCharles.Forsyth 	USED(x);
26937da2899SCharles.Forsyth 
27037da2899SCharles.Forsyth 	if(up->intwait) {
27137da2899SCharles.Forsyth 		up->intwait = 0;
27237da2899SCharles.Forsyth 		return;
27337da2899SCharles.Forsyth 	}
27437da2899SCharles.Forsyth 
27537da2899SCharles.Forsyth 	if(dflag == 0)
27637da2899SCharles.Forsyth 		termrestore();
27737da2899SCharles.Forsyth 	kill(0, SIGKILL);
27837da2899SCharles.Forsyth 	exit(0);
27937da2899SCharles.Forsyth }
28037da2899SCharles.Forsyth 
28137da2899SCharles.Forsyth void
getnobody(void)28237da2899SCharles.Forsyth getnobody(void)
28337da2899SCharles.Forsyth {
28437da2899SCharles.Forsyth 	struct passwd *pwd;
28537da2899SCharles.Forsyth 
28637da2899SCharles.Forsyth 	pwd = getpwnam("nobody");
28737da2899SCharles.Forsyth 	if(pwd != nil) {
28837da2899SCharles.Forsyth 		uidnobody = pwd->pw_uid;
28937da2899SCharles.Forsyth 		gidnobody = pwd->pw_gid;
29037da2899SCharles.Forsyth 	}
29137da2899SCharles.Forsyth }
29237da2899SCharles.Forsyth 
29337da2899SCharles.Forsyth void
osreboot(char * file,char ** argv)29437da2899SCharles.Forsyth osreboot(char *file, char **argv)
29537da2899SCharles.Forsyth {
29637da2899SCharles.Forsyth 	if(dflag == 0)
29737da2899SCharles.Forsyth 		termrestore();
29837da2899SCharles.Forsyth 	execvp(file, argv);
29937da2899SCharles.Forsyth 	panic("reboot failure");
30037da2899SCharles.Forsyth }
30137da2899SCharles.Forsyth 
30237da2899SCharles.Forsyth void
libinit(char * imod)30337da2899SCharles.Forsyth libinit(char *imod)
30437da2899SCharles.Forsyth {
30537da2899SCharles.Forsyth 	struct sigaction act;
30637da2899SCharles.Forsyth 	struct passwd *pw;
30737da2899SCharles.Forsyth 	int i;
30837da2899SCharles.Forsyth 	char sys[64];
30937da2899SCharles.Forsyth 
31037da2899SCharles.Forsyth 	setsid();
31137da2899SCharles.Forsyth 
31237da2899SCharles.Forsyth 	for(i=0; i<MAXSPROC; i++)
31337da2899SCharles.Forsyth 		sproctbl[i] = -1;
31437da2899SCharles.Forsyth 
31537da2899SCharles.Forsyth 	sproctbl[0] = getpid();
31637da2899SCharles.Forsyth 
31737da2899SCharles.Forsyth 	gethostname(sys, sizeof(sys));
31837da2899SCharles.Forsyth 	kstrdup(&ossysname, sys);
31937da2899SCharles.Forsyth 
32037da2899SCharles.Forsyth 	if(dflag == 0)
32137da2899SCharles.Forsyth 		termset();
32237da2899SCharles.Forsyth 
32337da2899SCharles.Forsyth 	if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
32437da2899SCharles.Forsyth 		signal(SIGTERM, cleanexit);
32537da2899SCharles.Forsyth 	if(signal(SIGINT, SIG_IGN) != SIG_IGN)
32637da2899SCharles.Forsyth 		signal(SIGINT, cleanexit);
32737da2899SCharles.Forsyth 	signal(SIGUSR2, trapUSR2);
32837da2899SCharles.Forsyth 	/* For the correct functioning of devcmd in the
32937da2899SCharles.Forsyth 	 * face of exiting slaves
33037da2899SCharles.Forsyth 	 */
33137da2899SCharles.Forsyth 	signal(SIGCLD, SIG_IGN);
33237da2899SCharles.Forsyth 	signal(SIGPIPE, SIG_IGN);
33337da2899SCharles.Forsyth 	memset(&act, 0 , sizeof(act));
33437da2899SCharles.Forsyth 	act.sa_handler=trapUSR1;
33537da2899SCharles.Forsyth 	sigaction(SIGUSR1, &act, nil);
33637da2899SCharles.Forsyth 	if(sflag == 0) {
33737da2899SCharles.Forsyth 		act.sa_handler=trapBUS;
33837da2899SCharles.Forsyth 		sigaction(SIGBUS, &act, nil);
33937da2899SCharles.Forsyth 		act.sa_handler=trapILL;
34037da2899SCharles.Forsyth 		sigaction(SIGILL, &act, nil);
34137da2899SCharles.Forsyth 		act.sa_handler=trapSEGV;
34237da2899SCharles.Forsyth 		sigaction(SIGSEGV, &act, nil);
34337da2899SCharles.Forsyth 	}
34437da2899SCharles.Forsyth 
34537da2899SCharles.Forsyth 	if(usconfig(CONF_INITUSERS, 1000) < 0)
34637da2899SCharles.Forsyth 		panic("usconfig");
34737da2899SCharles.Forsyth 
34837da2899SCharles.Forsyth 	Xup = (Proc**)PRDA->usr_prda.fill;
34937da2899SCharles.Forsyth 	up = newproc();
35037da2899SCharles.Forsyth 
35137da2899SCharles.Forsyth 	pw = getpwuid(getuid());
35237da2899SCharles.Forsyth 	if(pw != nil) {
35337da2899SCharles.Forsyth 		if (strlen(pw->pw_name) + 1 <= KNAMELEN)
35437da2899SCharles.Forsyth 			strcpy(eve, pw->pw_name);
35537da2899SCharles.Forsyth 		else
35637da2899SCharles.Forsyth 			print("pw_name too long\n");
35737da2899SCharles.Forsyth 	}
35837da2899SCharles.Forsyth 	else
35937da2899SCharles.Forsyth 		print("cannot getpwuid\n");
36037da2899SCharles.Forsyth 
36137da2899SCharles.Forsyth 	/* after setting up, since this takes locks */
36237da2899SCharles.Forsyth 	getnobody();
36337da2899SCharles.Forsyth 	up->env->uid = getuid();
36437da2899SCharles.Forsyth 	up->env->gid = getgid();
36537da2899SCharles.Forsyth 	emuinit(imod);
36637da2899SCharles.Forsyth }
36737da2899SCharles.Forsyth 
36837da2899SCharles.Forsyth int
readkbd(void)36937da2899SCharles.Forsyth readkbd(void)
37037da2899SCharles.Forsyth {
37137da2899SCharles.Forsyth 	int n;
37237da2899SCharles.Forsyth 	char buf[1];
37337da2899SCharles.Forsyth 
37437da2899SCharles.Forsyth 	n = read(0, buf, sizeof(buf));
37537da2899SCharles.Forsyth 	if(n < 0)
37637da2899SCharles.Forsyth 		fprint(2, "keyboard read error: %s\n", strerror(errno));
37737da2899SCharles.Forsyth 	if(n <= 0)
37837da2899SCharles.Forsyth 		pexit("keyboard thread", 0);
37937da2899SCharles.Forsyth 	switch(buf[0]) {
38037da2899SCharles.Forsyth 	case '\r':
38137da2899SCharles.Forsyth 		buf[0] = '\n';
38237da2899SCharles.Forsyth 		break;
38337da2899SCharles.Forsyth 	case DELETE:
38437da2899SCharles.Forsyth 		cleanexit(0);
38537da2899SCharles.Forsyth 		break;
38637da2899SCharles.Forsyth 	}
38737da2899SCharles.Forsyth 	return buf[0];
38837da2899SCharles.Forsyth }
38937da2899SCharles.Forsyth 
39037da2899SCharles.Forsyth int
segflush(void * a,ulong n)39137da2899SCharles.Forsyth segflush(void *a, ulong n)
39237da2899SCharles.Forsyth {
39337da2899SCharles.Forsyth 	cacheflush(a, n, BCACHE);
39437da2899SCharles.Forsyth 	return 0;
39537da2899SCharles.Forsyth }
39637da2899SCharles.Forsyth 
39737da2899SCharles.Forsyth /*
39837da2899SCharles.Forsyth  * Return an abitrary millisecond clock time
39937da2899SCharles.Forsyth  */
40037da2899SCharles.Forsyth long
osmillisec(void)40137da2899SCharles.Forsyth osmillisec(void)
40237da2899SCharles.Forsyth {
40337da2899SCharles.Forsyth 	static long sec0 = 0, usec0;
40437da2899SCharles.Forsyth 	struct timeval t;
40537da2899SCharles.Forsyth 
40637da2899SCharles.Forsyth 	if(gettimeofday(&t,(struct timezone*)0)<0)
40737da2899SCharles.Forsyth 		return(0);
40837da2899SCharles.Forsyth 	if(sec0==0){
40937da2899SCharles.Forsyth 		sec0 = t.tv_sec;
41037da2899SCharles.Forsyth 		usec0 = t.tv_usec;
41137da2899SCharles.Forsyth 	}
41237da2899SCharles.Forsyth 	return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000);
41337da2899SCharles.Forsyth }
41437da2899SCharles.Forsyth 
41537da2899SCharles.Forsyth /*
41637da2899SCharles.Forsyth  * Return the time since the epoch in nanoseconds and microseconds
41737da2899SCharles.Forsyth  * The epoch is defined at 1 Jan 1970
41837da2899SCharles.Forsyth  */
41937da2899SCharles.Forsyth vlong
osnsec(void)42037da2899SCharles.Forsyth osnsec(void)
42137da2899SCharles.Forsyth {
42237da2899SCharles.Forsyth 	struct timeval t;
42337da2899SCharles.Forsyth 
42437da2899SCharles.Forsyth 	gettimeofday(&t, nil);
42537da2899SCharles.Forsyth 	return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
42637da2899SCharles.Forsyth }
42737da2899SCharles.Forsyth 
42837da2899SCharles.Forsyth vlong
osusectime(void)42937da2899SCharles.Forsyth osusectime(void)
43037da2899SCharles.Forsyth {
43137da2899SCharles.Forsyth 	struct timeval t;
43237da2899SCharles.Forsyth 
43337da2899SCharles.Forsyth 	gettimeofday(&t, nil);
43437da2899SCharles.Forsyth 	return (vlong)t.tv_sec * 1000000 + t.tv_usec;
43537da2899SCharles.Forsyth }
43637da2899SCharles.Forsyth 
43737da2899SCharles.Forsyth int
osmillisleep(ulong milsec)43837da2899SCharles.Forsyth osmillisleep(ulong milsec)
43937da2899SCharles.Forsyth {
44037da2899SCharles.Forsyth 	static int tick;
44137da2899SCharles.Forsyth 
44237da2899SCharles.Forsyth 	/*
44337da2899SCharles.Forsyth 	 * Posix-conforming CLK_TCK implementations tend to call sysconf,
44437da2899SCharles.Forsyth 	 * and we don't need the overhead.
44537da2899SCharles.Forsyth 	 */
44637da2899SCharles.Forsyth 	if(tick == 0)
44737da2899SCharles.Forsyth 		tick = CLK_TCK;
44837da2899SCharles.Forsyth 	sginap((tick*milsec)/1000);
44937da2899SCharles.Forsyth 	return 0;
45037da2899SCharles.Forsyth }
45137da2899SCharles.Forsyth 
45237da2899SCharles.Forsyth int
limbosleep(ulong milsec)45337da2899SCharles.Forsyth limbosleep(ulong milsec)
45437da2899SCharles.Forsyth {
45537da2899SCharles.Forsyth 	return osmillisleep(milsec);
45637da2899SCharles.Forsyth }
45737da2899SCharles.Forsyth 
45837da2899SCharles.Forsyth void
osyield(void)45937da2899SCharles.Forsyth osyield(void)
46037da2899SCharles.Forsyth {
46137da2899SCharles.Forsyth 	sginap(0);
46237da2899SCharles.Forsyth }
46337da2899SCharles.Forsyth 
46437da2899SCharles.Forsyth void
ospause(void)46537da2899SCharles.Forsyth ospause(void)
46637da2899SCharles.Forsyth {
46737da2899SCharles.Forsyth 	for(;;)
46837da2899SCharles.Forsyth 		pause();
46937da2899SCharles.Forsyth }
47037da2899SCharles.Forsyth 
47137da2899SCharles.Forsyth void
oslopri(void)47237da2899SCharles.Forsyth oslopri(void)
47337da2899SCharles.Forsyth {
47437da2899SCharles.Forsyth 	nice(2);
47537da2899SCharles.Forsyth }
476