shithub: ridefs

Download patch

ref: dba0c3fbd5463e44d57c5c75f6fa285b91770474
parent: 4401e746299f6c7c0665cefb557c455d4edb7d9f
author: B. Wilson <x@wilsonb.com>
date: Mon Jun 23 11:57:36 EDT 2025

Allow simultaneous reading and writing

--- a/ridefs.c
+++ b/ridefs.c
@@ -12,20 +12,19 @@
 
 struct Client {
 	Ref;
-	QLock;
 
 	char *addr;
 
-	/* internal use */
-	Req *req;       /* i/o req */
-	int pid;        /*     pid */
-	char *r;        /* response buffer */
-	int rn;         /*          length */
-	int roff;       /*          offset */
-	char *qinfo;
-	char *qctl;
-	int fd;         /* data */
-	int cfd;        /* ctl */
+	/* tcp i/o */
+	QLock rl, wl;
+	Req *rreq, *wreq;
+	int rpid, wpid;
+	int fd, cfd;
+
+	/* buffers */
+	char *qinfo, *qctl;
+	char *r;      /* response */
+	int rn, roff;
 };
 
 enum {
@@ -457,25 +456,25 @@
 			return;
 		}
 
-		qlock(c);
+		qlock(&c->wl);
 		incref(&r->ref);
-		c->req = r;
-		switch(c->pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
+		c->wreq = r;
+		switch(c->wpid = rfork(RFPROC|RFNOWAIT|RFMEM)){
 		case 0:
 			if(!c->fd)
 				err = rideinit(c->addr, &c->fd, &c->cfd, &c->qinfo);
-			c->pid = 0;
-			c->req = nil;
+			c->wpid = 0;
+			c->wreq = nil;
 			decref(&r->ref);
 			respond(r, err);
-			qunlock(c);
+			qunlock(&c->wl);
 			exits(nil);
 		case -1:
 			respond(r, "failed to init ride");
-			c->pid = 0;
-			c->req = nil;
+			c->wpid = 0;
+			c->wreq = nil;
 			decref(&r->ref);
-			qunlock(c);
+			qunlock(&c->wl);
 			break;
 		default:
 			return;
@@ -504,14 +503,15 @@
 	case Qctl: buf = estrdup(c->qctl); break;
 	case Qinfo: buf = estrdup(c->qinfo); break;
 	case Qdata:
-		qlock(c);
+		qlock(&c->rl);
 		incref(&r->ref);
-		c->req = r;
-		switch(c->pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
+		c->rreq = r;
+		switch(c->rpid = rfork(RFPROC|RFNOWAIT|RFMEM)){
 		case 0:
 			off = r->ifcall.offset - c->roff;
 			if(c->rn < 0){
 				free(c->r);
+				c->r = nil;
 				c->rn = readmsg(c->fd, &c->r);
 				c->roff = r->ifcall.offset;
 				off = 0;
@@ -527,18 +527,18 @@
 				r->ofcall.count = n;
 			}
 
-			c->pid = 0;
-			c->req = nil;
+			c->rpid = 0;
+			c->rreq = nil;
 			decref(&r->ref);
 			respond(r, err);
-			qunlock(c);
+			qunlock(&c->rl);
 			exits(nil);
 		case -1:
 			err = "failed to fork read";
-			c->pid = 0;
-			c->req = nil;
+			c->rpid = 0;
+			c->rreq = nil;
 			decref(&r->ref);
-			qunlock(c);
+			qunlock(&c->rl);
 			break;
 		default:
 			return;
@@ -575,26 +575,25 @@
 		r->ofcall.count = writeqctl(d, n, f->client);
 		break;
 	case Qdata:
-		qlock(c);
+		qlock(&c->wl);
 		incref(&r->ref);
-		c->req = r;
-		switch(c->pid = rfork(RFPROC|RFNOWAIT|RFMEM)){
+		c->wreq = r;
+		switch(c->wpid = rfork(RFPROC|RFNOWAIT|RFMEM)){
 		case 0:
 			r->ofcall.count = writemsg(c->fd, d, n);
 
-			c->pid = 0;
-			c->req = nil;
+			c->wpid = 0;
+			c->wreq = nil;
 			decref(&r->ref);
 			respond(r, nil);
-
-			qunlock(c);
+			qunlock(&c->wl);
 			exits(nil);
 		case -1:
 			err = "failed to fork write";
-			c->pid = 0;
-			c->req = nil;
+			c->wpid = 0;
+			c->wreq = nil;
 			decref(&r->ref);
-			qunlock(c);
+			qunlock(&c->wl);
 			break;
 		default:
 			return;
@@ -616,13 +615,19 @@
 	if(o = r->oldreq)
 	if(f = o->fid->aux)
 	if(c = clientref(f->client))
-	if(c->req){
-		postnote(PNPROC, c->pid, "interrupt");
-		respond(c->req, "interrupted");
-		c->pid = 0;
-		c->req = nil;
-		decref(&c->req->ref);
-		qunlock(c);
+	if(o == c->rreq){
+		postnote(PNPROC, c->rpid, "interrupt");
+		respond(c->rreq, "interrupted");
+		c->rpid = 0;
+		decref(&c->rreq->ref);
+		qunlock(&c->rl);
+	} else if (o == c->wreq){
+		postnote(PNPROC, c->wpid, "interrupt");
+		respond(c->wreq, "interrupted");
+		c->wpid = 0;
+		c->wreq = nil;
+		decref(&c->wreq->ref);
+		qunlock(&c->wl);
 	}
 
 	respond(r, nil);
--