code: 9ferno

Download patch

ref: 064b0e15d602a0f773099156ccf09a8aa7db5c3e
parent: 2745a626390bd5df5a01a7ef18c1a18a93f8c54d
author: 9ferno <gophone2015@gmail.com>
date: Sun Jan 16 11:23:19 EST 2022

first cut at devready a device to monitor pipe readers

--- a/os/port/devready.c
+++ b/os/port/devready.c
@@ -16,6 +16,8 @@
 		It belongs there..
 		instead of 2 files (watch and ready). Use 1 file (canread).
 
+	#r/canread
+
 up->shm = Ready*
 c->aux = 
  */
@@ -23,7 +25,7 @@
 {
 	NFD = 16,
 
-	Qwatch		= 0,
+	Qcanread = 0,
 	Qready
 };
 
@@ -45,6 +47,8 @@
 	s32 fd;
 	Queue *q;
 	s32 ready;
+	u8 stop;
+	Proc *kproc;
 };
 
 typedef struct Ready;
@@ -53,6 +57,7 @@
 	Qlock;
 	Readyfd *rfd[[NFD];
 	s32 nrfd;
+	Queue *commq;	/* queue for the different watcher kproc's to communicate */
 };
 
 static int
@@ -68,14 +73,10 @@
 		return 1;
 	}
 
-	if(c->qid == Qwatch){
-		mkqid(&q, Qwatch, 0, QTFILE);
-		devdir(c, q, "watch", 0, eve, 0664, dp);
+	if(c->qid == Qcanread){
+		mkqid(&q, Qcanread, 0, QTFILE);
+		devdir(c, q, "canread", 0, eve, 0664, dp);
 		return 1;
-	}else if(c->qid == Qready){
-		mkqid(&q, Qready, 0, QTFILE);
-		devdir(c, q, "ready", 0, eve, 0664, dp);
-		return 1;
 	}
 	return -1;
 }
@@ -142,11 +143,11 @@
 			error(Eperm);
 
 		qlock(r);
+		r->commq = qopen(1024, 0, 0, 0);
 		if(trunc) { /* shoud be Qwatch */
 			for(i = 0; i < r->nrfd; i++){
-				TODO shutdown kproc's
-				if(r->rfd[i] != nil)
-					free(r->rfd[i]);
+				r->rfd[i].stop = 1;
+				/* TODO shutdown kproc's send a note to any running kprocs */
 			}
 			r->nrfd = 0;
 		}
@@ -183,25 +184,10 @@
 	if((r = up->readyfds) == nil)
 		error(Enonexist);
 
-	return qread(r->q, a, n);
-
-	qlock(r);
-	should this be qbread?
-	for(i = 0; i<r->nrfd; i++){
-		if(r->rfd.ready > 0){
-			rv = snprint(a, n, "%d\n", r->rfd.fd);
-			r->rfd.ready = 0;
-			qunlock(r);
-			return rv;
-		}
-	}
-	if none of the fd's are ready, let the kproc's run and loop here until there is a ready fd
-		let the dogs go and wait for them to bring back the kill
-	this should be interruptible too. So, there can be an alarm() before.
-
-	return 0;
+	return qread(r->commq, a, n);
 }
 
+/* TODO close kproc by sending a note */
 static void
 stopwatchers(void)
 {
@@ -210,28 +196,29 @@
 	if((r = up->readyfds) == nil)
 		error(Enonexist);
 
-	if(r->q != nil)
-		qhangup(r->q, nil);
+	if(r->commq != nil)
+		qhangup(r->commq, nil);
 	for(i = 0; i < r->rnfd; i++){
-		TODO close kproc by sending a note
-		r->rfd[i].ready = 0;
+		r->rfd[i].stop = 1;
 		r->rfd[i].fd = -1;
 	}
 }
 
+/*
+	wrap this in an alarm() so it does not block forever?
+	should be using qread() instead? qcanread does not block(?)
+	TODO double check wv values
+ */
 static void
-startwatcher(Queue *q, Readyfd *rfd)
+startwatcher(Readyfd *rfd)
 {
 	char s[16];
 
 	rfd->kproc = up;
-	while(){
-		qread(rfd->readq);
-wrap this in an alarm() so it does not block forever?
-should be using qread() instead? qcanread does not block(?)
-		qcanread(rfd->q);
+	while(rfd->stop == 0 && wv != 0 && wv != -1){
+		qhasdata(rfd->q);
 		n = snprint(s, 16, "%d\n", rfd->fd);
-		qwrite(q, s, n);
+		wv = qwrite(rfd->commq, s, n);
 	}
 }
 
@@ -267,8 +254,9 @@
 		i = r->nrfd;
 		r->rfd[i].fd = fd;
 		r->rfd[i].ready = 0;
+		r->rfd[i].commq = r->commq;
 		snprint(name, KNAMELEN, "watch %d for %d", fd, up->pid);
-		kproc(name, startwatcher, r->q, &r->rfd[i]);
+		kproc(name, startwatcher, &r->rfd[i], 0);
 		r->nrfd++;
 	}
 	qunlock(r);
--- a/os/port/portfns.h
+++ b/os/port/portfns.h
@@ -249,6 +249,7 @@
 int		qfull(Queue*);
 Block*		qget(Queue*);
 void		qhangup(Queue*, char*);
+s32		qhasdata(Queue*);
 int		qisclosed(Queue*);
 int		qiwrite(Queue*, void*, int);
 int		qlen(Queue*);
--- a/os/port/qio.c
+++ b/os/port/qio.c
@@ -979,6 +979,20 @@
 }
 
 /*
+ *  same as qcanread() but blocks if there is no data, used by devready
+ */
+s32
+qhasdata(Queue *q)
+{
+	s32 rv;
+
+	ilock(q);
+	rv = qwait(q);
+	iunlock(q);
+	return rv;
+}
+
+/*
  *  read a queue.  if no data is queued, post a Block
  *  and wait on its Rendez.
  */