summaryrefslogtreecommitdiff
path: root/sys/src/libc
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-05-23 18:56:20 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2014-05-23 18:56:20 +0200
commiteef4565003def0a1e72bf381665027ebe0420c6f (patch)
treebd62103648d827103746706f99eb7339cf28c030 /sys/src/libc
parent440202d029af36e5e52545a3badd1ea459961f84 (diff)
libc: avoid static table and supurious reads in nsec()
use two per process memory slots, one for the pid and one for the fd instead of a global table avoiding the case when the table gets full. instead of calling pread() on the cached fd (dangerous as it has side effects when the fd was not closed), we check if the cached fd is still good using fd2path() when called the first time in this process.
Diffstat (limited to 'sys/src/libc')
-rw-r--r--sys/src/libc/9sys/nsec.c80
-rw-r--r--sys/src/libc/9sys/time.c38
2 files changed, 34 insertions, 84 deletions
diff --git a/sys/src/libc/9sys/nsec.c b/sys/src/libc/9sys/nsec.c
index f0e981d04..3519fae33 100644
--- a/sys/src/libc/9sys/nsec.c
+++ b/sys/src/libc/9sys/nsec.c
@@ -16,60 +16,48 @@ be2vlong(vlong *to, uchar *f)
t[o[i]] = f[i];
}
-static int fd = -1;
-static struct {
- int pid;
- int fd;
-} fds[64];
+static int
+stillopen(int fd, char *name)
+{
+ char buf[64];
+
+ return fd >= 0 && fd2path(fd, buf, sizeof(buf)) == 0 && strcmp(buf, name) == 0;
+}
vlong
nsec(void)
{
+ static char name[] = "/dev/bintime";
+ static int *pidp = nil, *fdp = nil, fd = -1;
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
- */
+ int f;
- /* 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(pidp != nil && *pidp == _tos->pid)
+ f = *fdp;
+ else{
+Reopen:
+ f = fd;
+ if(fdp != nil && *fdp != f && stillopen(*fdp, name))
+ f = *fdp;
+ else if(!stillopen(f, name)){
+ if((f = open(name, OREAD|OCEXEC)) < 0)
+ return 0;
}
- if(pread(f, b, sizeof b, 0) == sizeof b){
- be2vlong(&t, b);
- return t;
+ fd = f;
+ if(fdp == nil){
+ fdp = (int*)privalloc();
+ pidp = (int*)privalloc();
}
+ *fdp = f;
+ *pidp = _tos->pid;
+ }
+ if(pread(f, b, sizeof b, 0) != sizeof b){
+ if(!stillopen(f, name))
+ goto Reopen;
close(f);
- if(i < nelem(fds))
- fds[i].fd = -1;
- }while(tries++ == 0); /* retry once */
- USED(tries);
- return 0;
+ return 0;
+ }
+ be2vlong(&t, b);
+ return t;
}
diff --git a/sys/src/libc/9sys/time.c b/sys/src/libc/9sys/time.c
index 3e5f83b04..23ef3d1ba 100644
--- a/sys/src/libc/9sys/time.c
+++ b/sys/src/libc/9sys/time.c
@@ -1,50 +1,12 @@
#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;