shithub: riscv

Download patch

ref: 440202d029af36e5e52545a3badd1ea459961f84
parent: e7b94ba052b3ee175f17f7ebc85f7c21d22431ca
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue May 20 03:05:53 EDT 2014

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.

--- 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 @@
 		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;
 
-	t = 0;
-	fd = open("/dev/bintime", OREAD);
-	if(fd >= 0){
-		if(pread(fd, b, sizeof b, 0) == sizeof b)
+	/*
+	 * 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 */
+	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;
 }
--- a/sys/src/libc/9sys/time.c
+++ b/sys/src/libc/9sys/time.c
@@ -1,6 +1,42 @@
 #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)
 {
@@ -7,6 +43,8 @@
 	vlong t;
 
 	t = nsec()/1000000000LL;
+	if(t == 0)
+		t = oldtime(0);
 	if(tp != nil)
 		*tp = t;
 	return t;