diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-05-20 07:05:53 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-05-20 07:05:53 +0200 |
commit | 440202d029af36e5e52545a3badd1ea459961f84 (patch) | |
tree | 9891d80bd2374f0313572be437d669aa54ed7437 /sys/src/libc | |
parent | e7b94ba052b3ee175f17f7ebc85f7c21d22431ca (diff) |
libc: revert nsec() change, bring back filedescriptor caching
theres big performance regression with this using
cwfs. cwfs calls time() to update atime on every
read/write which now causes walks on /dev.
reverting to the previous version for now. in the
long run, we'll use new _nsec() syscall but this
has to wait for a later release once new kernels
are established.
Diffstat (limited to 'sys/src/libc')
-rw-r--r-- | sys/src/libc/9sys/nsec.c | 58 | ||||
-rw-r--r-- | sys/src/libc/9sys/time.c | 38 |
2 files changed, 88 insertions, 8 deletions
diff --git a/sys/src/libc/9sys/nsec.c b/sys/src/libc/9sys/nsec.c index 13fc44d5b..f0e981d04 100644 --- a/sys/src/libc/9sys/nsec.c +++ b/sys/src/libc/9sys/nsec.c @@ -1,5 +1,6 @@ #include <u.h> #include <libc.h> +#include <tos.h> static uvlong order = 0x0001020304050607ULL; @@ -15,19 +16,60 @@ be2vlong(vlong *to, uchar *f) 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 fd; + 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 + */ - t = 0; - fd = open("/dev/bintime", OREAD); - if(fd >= 0){ - if(pread(fd, b, sizeof b, 0) == sizeof b) + /* First, look if we've opened it for this particular pid */ + pid = _tos->pid; + 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); - close(fd); - } - return t; + return t; + } + close(f); + if(i < nelem(fds)) + fds[i].fd = -1; + }while(tries++ == 0); /* retry once */ + USED(tries); + return 0; } diff --git a/sys/src/libc/9sys/time.c b/sys/src/libc/9sys/time.c index 23ef3d1ba..3e5f83b04 100644 --- a/sys/src/libc/9sys/time.c +++ b/sys/src/libc/9sys/time.c @@ -1,12 +1,50 @@ #include <u.h> #include <libc.h> + +/* + * After a fork with fd's copied, both fd's are pointing to + * the same Chan structure. Since the offset is kept in the Chan + * structure, the seek's and read's in the two processes can + * compete at moving the offset around. Hence the unusual loop + * in the middle of this routine. + */ +static long +oldtime(long *tp) +{ + char b[20]; + static int f = -1; + int i, retries; + long t; + + memset(b, 0, sizeof(b)); + for(retries = 0; retries < 100; retries++){ + if(f < 0) + f = open("/dev/time", OREAD|OCEXEC); + if(f < 0) + break; + if(seek(f, 0, 0) < 0 || (i = read(f, b, sizeof(b))) < 0){ + close(f); + f = -1; + } else { + if(i != 0) + break; + } + } + t = atol(b); + if(tp) + *tp = t; + return t; +} + long time(long *tp) { vlong t; t = nsec()/1000000000LL; + if(t == 0) + t = oldtime(0); if(tp != nil) *tp = t; return t; |