xref: /plan9/sys/src/libc/9sys/nsec.c (revision 3128c8a0f7b81b6e6e0831d669ef15a24852fbd8)
1 #include <u.h>
2 #include <libc.h>
3 #include <tos.h>
4 
5 static uvlong order = 0x0001020304050607ULL;
6 
7 static void
be2vlong(vlong * to,uchar * f)8 be2vlong(vlong *to, uchar *f)
9 {
10 	uchar *t, *o;
11 	int i;
12 
13 	t = (uchar*)to;
14 	o = (uchar*)&order;
15 	for(i = 0; i < sizeof order; i++)
16 		t[o[i]] = f[i];
17 }
18 
19 static int fd = -1;
20 static struct {
21 	int	pid;
22 	int	fd;
23 } fds[64];
24 
25 vlong
nsec(void)26 nsec(void)
27 {
28 	uchar b[8];
29 	vlong t;
30 	int pid, i, f, tries;
31 
32 	/*
33 	 * Threaded programs may have multiple procs
34 	 * with different fd tables, so we may need to open
35 	 * /dev/bintime on a per-pid basis
36 	 */
37 
38 	/* First, look if we've opened it for this particular pid */
39 	if((pid = _tos->pid) == 0)		/* 9vx bug, perhaps? */
40 		_tos->pid = pid = getpid();
41 	do{
42 		f = -1;
43 		for(i = 0; i < nelem(fds); i++)
44 			if(fds[i].pid == pid){
45 				f = fds[i].fd;
46 				break;
47 			}
48 		tries = 0;
49 		if(f < 0){
50 			/* If it's not open for this pid, try the global pid */
51 			if(fd >= 0)
52 				f = fd;
53 			else{
54 				/* must open */
55 				if((f = open("/dev/bintime", OREAD|OCEXEC)) < 0)
56 					return 0;
57 				fd = f;
58 				for(i = 0; i < nelem(fds); i++)
59 					if(fds[i].pid == pid || fds[i].pid == 0){
60 						fds[i].pid = pid;
61 						fds[i].fd = f;
62 						break;
63 					}
64 			}
65 		}
66 		if(pread(f, b, sizeof b, 0) == sizeof b){
67 			be2vlong(&t, b);
68 			return t;
69 		}
70 		close(f);
71 		if(i < nelem(fds))
72 			fds[i].fd = -1;
73 	}while(tries++ == 0);	/* retry once */
74 	USED(tries);
75 	return 0;
76 }
77