xref: /plan9/sys/src/libc/9sys/nsec.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include <u.h>
2 #include <libc.h>
3 
4 
5 static uvlong order = 0x0001020304050607ULL;
6 
7 static void
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 < 8; i++)
16 		t[o[i]] = f[i];
17 }
18 
19 /*
20  *  After a fork with fd's copied, both fd's are pointing to
21  *  the same Chan structure.  Since the offset is kept in the Chan
22  *  structure, the seek's and read's in the two processes can
23  *  compete at moving the offset around.  Hence the retry loop.
24  *
25  *  Since the bintime version doesn't need a seek, it doesn't
26  *  have the loop.
27  */
28 vlong
29 nsec(void)
30 {
31 	char b[12+1];
32 	static int f = -1;
33 	static int usebintime;
34 	int retries;
35 	vlong t;
36 
37 	if(f < 0){
38 		usebintime = 1;
39 		f = open("/dev/bintime", OREAD|OCEXEC);
40 		if(f < 0){
41 			usebintime = 0;
42 			f = open("/dev/nsec", OREAD|OCEXEC);
43 			if(f < 0)
44 				return 0;
45 		}
46 	}
47 
48 	if(usebintime){
49 		if(read(f, b, sizeof(uvlong)) < 0)
50 			goto error;
51 		be2vlong(&t, (uchar*)b);
52 		return t;
53 	} else {
54 		for(retries = 0; retries < 100; retries++){
55 			if(seek(f, 0, 0) >= 0 && read(f, b, sizeof(b)-1) >= 0){
56 				b[sizeof(b)-1] = 0;
57 				return strtoll(b, 0, 0);
58 			}
59 		}
60 	}
61 
62 error:
63 	close(f);
64 	f = -1;
65 	return 0;
66 }
67