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