Implement the nanotime system call. This is notably useful for the port of the Go Programming Language on Plan 9. In the Go environment, we are currently relying on the /dev/bintime file to get time. However it has the disadvantage of introducing latency (in order of ten microseconds) and require the /dev/bintime file to be opened for every child process and call to the nanotime() function. The nanotime syscall should also be implemented in /sys/src/9k/port/sysfile.c: void sysnanotime(Ar0* ar0, va_list) { /* * vlong nanotime(void); */ ar0->vl = todget(nil); } This is an idea from Ron Minnich, which was originaly implemented as part of NxM. I think Jim already reviewed this change last year. Reference: /n/sources/patch/maybe/sys-nanotime Date: Wed Jan 15 20:25:36 CET 2014 Signed-off-by: djc@9grid.fr --- /sys/src/libc/9syscall/sys.h Wed Jan 15 20:24:35 2014 +++ /sys/src/libc/9syscall/sys.h Wed Jan 15 20:24:32 2014 @@ -49,3 +49,4 @@ #define PREAD 50 #define PWRITE 51 #define TSEMACQUIRE 52 +#define NANOTIME 53 --- /sys/src/9/port/sysfile.c Wed Jan 15 20:24:50 2014 +++ /sys/src/9/port/sysfile.c Wed Jan 15 20:24:42 2014 @@ -281,6 +281,14 @@ return fd; } +long +sysnanotime(ulong *arg) +{ + validaddr(arg[0], BY2V, 1); + *(vlong*)arg[0] = todget(nil); + return 0; +} + void fdclose(int fd, int flag) { --- /sys/include/libc.h Wed Jan 15 20:25:04 2014 +++ /sys/include/libc.h Wed Jan 15 20:24:55 2014 @@ -668,6 +668,7 @@ extern int mount(int, int, char*, int, char*); extern int unmount(char*, char*); extern int noted(int); +extern vlong nanotime(void); extern int notify(void(*)(void*, char*)); extern int open(char*, int); extern int fd2path(int, char*, int); --- /sys/src/libc/9sys/nsec.c Wed Jan 15 20:25:09 2014 +++ /sys/src/libc/9sys/nsec.c Wed Jan 15 20:25:06 2014 @@ -1,76 +1,8 @@ #include #include -#include - -static uvlong order = 0x0001020304050607ULL; - -static void -be2vlong(vlong *to, uchar *f) -{ - uchar *t, *o; - int i; - - t = (uchar*)to; - o = (uchar*)ℴ - for(i = 0; i < sizeof order; i++) - t[o[i]] = f[i]; -} - -static int fd = -1; -static struct { - int pid; - int fd; -} fds[64]; vlong nsec(void) { - uchar b[8]; - vlong t; - int pid, i, f, tries; - - /* - * Threaded programs may have multiple procs - * with different fd tables, so we may need to open - * /dev/bintime on a per-pid basis - */ - - /* First, look if we've opened it for this particular pid */ - if((pid = _tos->pid) == 0) /* 9vx bug, perhaps? */ - _tos->pid = pid = getpid(); - do{ - f = -1; - for(i = 0; i < nelem(fds); i++) - if(fds[i].pid == pid){ - f = fds[i].fd; - break; - } - tries = 0; - if(f < 0){ - /* If it's not open for this pid, try the global pid */ - if(fd >= 0) - f = fd; - else{ - /* must open */ - if((f = open("/dev/bintime", OREAD|OCEXEC)) < 0) - return 0; - fd = f; - for(i = 0; i < nelem(fds); i++) - if(fds[i].pid == pid || fds[i].pid == 0){ - fds[i].pid = pid; - fds[i].fd = f; - break; - } - } - } - if(pread(f, b, sizeof b, 0) == sizeof b){ - be2vlong(&t, b); - return t; - } - close(f); - if(i < nelem(fds)) - fds[i].fd = -1; - }while(tries++ == 0); /* retry once */ - USED(tries); - return 0; + return nanotime(); }