shithub: ridefs

Download patch

ref: 51489f979a4b1a0df534f9b8d461314c8ad86483
parent: ee71fd2728c3201348fdc0ffbd8720d3597f2ac5
author: B. Wilson <x@wilsonb.com>
date: Thu Jun 19 10:45:49 EDT 2025

Allow async io

--- a/ridefs.c
+++ b/ridefs.c
@@ -12,14 +12,15 @@
 
 struct Client {
 	Ref;
+	QLock;
 
 	char *addr;
 	ulong umask;
 
 	/* internal use */
+	int ridone;     /* ride initialized */
 	Req *req;       /* i/o req */
 	int pid;        /*     pid */
-	int oio;        /* io opened */
 	char *r;        /* response buffer */
 	int rn;         /*          length */
 	int roff;       /*          offset */
@@ -465,7 +466,7 @@
 
 static void
 fsopen(Req *r){
-	int e, pid;
+	int pid;
 	char *err;
 	Rfid *f;
 	Client *c;
@@ -472,6 +473,7 @@
 
 	f = r->fid->aux;
 	c = clientref(f->client);
+	err = nil;
 	switch(f->kind){
 	case Qclone:
 		if((f->client = mkclient()) == -1){
@@ -487,21 +489,25 @@
 		respond(r, nil);
 		break;
 	case Qio:
-		if(e = c->oio)
-			respond(r, "client in use");
-		else if(e = (nil == c->addr))
+		if(nil == c->addr){
 			respond(r, "no server set");
-		if(e)
 			return;
+		}
 
 		switch(pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
 		case 0:
+			qlock(c);
+			if(c->ridone)
+				goto end;
+
 			err = rideinit(f->client);
-			if(err == nil)
-				c->oio = 1;
-			respond(r, err);
 			c->pid = 0;
 			c->req = nil;
+			c->ridone = 1;
+
+			end:
+			respond(r, err);
+			qunlock(c);
 			exits(nil);
 		case -1:
 			respond(r, "failed to init ride");
@@ -537,8 +543,9 @@
 	case Qio:
 		switch(pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
 		case 0:
-			off = r->ifcall.offset - c->roff;
+			qlock(c);
 
+			off = r->ifcall.offset - c->roff;
 			if(c->rn < 0){
 				c->rn = readmsg(c->fd, c->r, bufsz);
 				c->roff = r->ifcall.offset;
@@ -558,6 +565,8 @@
 			respond(r, err);
 			c->pid = 0;
 			c->req = nil;
+
+			qunlock(c);
 			exits(nil);
 		case -1:
 			err = "failed to fork read";
@@ -602,11 +611,14 @@
 	case Qio:
 		switch(pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
 		case 0:
+			qlock(c);
 			r->ofcall.count = writemsg(c->fd, d, n);
 
 			respond(r, nil);
 			c->pid = 0;
 			c->req = nil;
+
+			qunlock(c);
 			exits(nil);
 		case -1:
 			err = "failed to fork write";
@@ -638,6 +650,7 @@
 		respond(c->req, "interrupted");
 		c->pid = 0;
 		c->req = nil;
+		qunlock(c);
 	}
 
 	respond(r, nil);
--- a/test
+++ b/test
@@ -50,6 +50,7 @@
 ls -d $n >[2]/dev/null &&
 	fail 'Did not clean up closed client'
 
+
 <clone {
 	cd `{read}
 
@@ -71,4 +72,21 @@
 			fail 'Did not receive response'
 	}
 	cd ..
+}
+
+<clone {
+	cd `{read}
+	echo 'connect 192.168.11.17' >ctl
+
+	<>io >[1=0] {
+		msg='["Execute",{"text":"⍳5\n","trace":0}]'
+		echo -n $msg || fail 'Could not send message'
+	} & spid=$apid
+
+	<>io >[1=0] {
+		cat >/dev/null || fail 'Could not receive message'
+	} & rpid=$apid
+
+	wait $spid || fail $status
+	wait $rpid || fail $status
 }
--