git: 9front

Download patch

ref: d1babe27dc7f74c9b4e8ce464a837960122f7637
parent: 0ffa574bd8e98e9494ac465b9510dc6d3d2db6d5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Sep 14 13:27:14 EDT 2025

nusb/usbd: process read requests on /dev/usbevent in (descending) open order

For handling custom HID devices, we want to give
/rc/bin/nusbrc a first chance attaching a driver
before /sys/src/9/boot/nusbrc.

For that, usbd now maintains a open order and
processes read requests on /dev/usbevent file
in descending open order.

--- a/sys/src/cmd/nusb/usbd/usbd.c
+++ b/sys/src/cmd/nusb/usbd/usbd.c
@@ -24,10 +24,9 @@
 static char Eperm[] = "permission denied";
 
 typedef struct Event Event;
-
 struct Event {
 	Dev *dev;	/* the device producing the event,
-			   dev->aux points to Fid processing the event */
+			   dev->aux points to Reader processing the event */
 	char *data;
 	int len;
 	Event *link;
@@ -37,19 +36,36 @@
 			   their link pointers */
 };
 
+typedef struct Reader Reader;
+struct Reader {
+	Event	*event;	/* next event this reader can read */
+	uint	order;	/* open order */
+};
+
 static Event *evlast;
-static Req *reqfirst, *reqlast;
+static Req *reqlist;	/* sorted by open order */
 static QLock evlock;
 
 static void
 addreader(Req *req)
 {
-	req->aux = nil;
-	if(reqfirst == nil)
-		reqfirst = req;
-	else
-		reqlast->aux = req;
-	reqlast = req;
+	Req **l, *r;
+	Reader *rr;
+	uint order;
+
+	rr = req->fid->aux;
+	order = rr->order;
+
+	l = &reqlist;
+	while((r = *l) != nil) {
+		rr = r->fid->aux;
+		if(order > rr->order)
+			break;
+		l = (Req**)&r->aux;
+	}
+
+	req->aux = r;
+	*l = req;
 }
 
 static void
@@ -88,38 +104,35 @@
 static void
 procreqs(void)
 {
-	Req *r, *p, *x;
+	Req **l, *r;
+	Reader *rr;
 	Event *e;
-	Fid *f;
 
-Loop:
-	for(p = nil, r = reqfirst; r != nil; p = r, r = x){
-		x = r->aux;
-		f = r->fid;
-		e = f->aux;
-		if(e == evlast)
-			continue;
-		if(e->dev->aux == f){
+	for(r = reqlist; r != nil; r = r->aux){
+		rr = r->fid->aux;
+		e = rr->event;
+		if(e != evlast && e->dev->aux == rr){
 			e->dev->aux = nil;	/* release device */
 			e->ref--;
 			e = putevent(e);
 			e->ref++;
-			f->aux = e;
-			goto Loop;
+			rr->event = e;
 		}
-		if(e->dev->aux == nil){
-			e->dev->aux = f;	/* claim device */
-			if(x == nil)
-				reqlast = p;
-			if(p == nil)
-				reqfirst = x;
-			else
-				p->aux = x;
+	}
+
+	l = &reqlist;
+	while((r = *l) != nil){
+		rr = r->fid->aux;
+		e = rr->event;
+		if(e != evlast && e->dev->aux == nil){
+			e->dev->aux = rr;	/* claim device */
+			*l = r->aux;
 			r->aux = nil;
 			fulfill(r, e);
 			respond(r, nil);
-			goto Loop;
+			continue;
 		}
+		l = (Req**)&r->aux;
 	}
 }
 
@@ -342,6 +355,8 @@
 usbdopen(Req *req)
 {
 	extern QLock hublock;
+	static uint order;
+	Reader *rr;
 	Event *e;
 
 	switch((ulong)req->fid->qid.path){
@@ -356,8 +371,12 @@
 		enumerate(&e);
 		e->prev--;
 		e->ref++;
-		req->fid->aux = e;
 
+		rr = emallocz(sizeof(Reader), 1);
+		rr->event = e;
+		rr->order = ++order;
+		req->fid->aux = rr;
+
 		qunlock(&evlock);
 		qunlock(&hublock);
 		break;
@@ -375,19 +394,22 @@
 usbddestroyfid(Fid *fid)
 {
 	if(fid->qid.path == Qusbevent){
+		Reader *rr;
 		Event *e;
 
 		qlock(&evlock);
-		e = fid->aux;
-		if(e != nil){
+		if((rr = fid->aux) != nil){
 			fid->aux = nil;
-			if(e->dev != nil && e->dev->aux == fid){
-				e->dev->aux = nil;	/* release device */
-				procreqs();
+			if((e = rr->event) != nil){
+				if(e->dev != nil && e->dev->aux == rr){
+					e->dev->aux = nil;	/* release device */
+					procreqs();
+				}
+				e->ref--;
+				while(e->ref == 0 && e->prev == 0 && e != evlast)
+					e = putevent(e);
 			}
-			e->ref--;
-			while(e->ref == 0 && e->prev == 0 && e != evlast)
-				e = putevent(e);
+			free(rr);
 		}
 		qunlock(&evlock);
 	}
@@ -396,22 +418,18 @@
 static void
 usbdflush(Req *req)
 {
-	Req *r, *p, *x;
+	Req **l, *r;
 
 	qlock(&evlock);
-	for(p = nil, r = reqfirst; r != nil; p = r, r = x){
-		x = r->aux;
+	l = &reqlist;
+	while((r = *l) != nil){
 		if(r == req->oldreq){
-			if(x == nil)
-				reqlast = p;
-			if(p == nil)
-				reqfirst = x;
-			else
-				p->aux = x;
+			*l = r->aux;
 			r->aux = nil;
 			respond(r, "interrupted");
 			break;
 		}
+		l = (Req**)&r->aux;
 	}
 	qunlock(&evlock);
 	respond(req, nil);
@@ -535,7 +553,7 @@
 void
 checkidle(void)
 {
-	if(busyfd < 0 || reqlast == nil || evlast == nil || evlast->prev > 0)
+	if(busyfd < 0 || reqlist == nil || evlast == nil || evlast->prev > 0)
 		return;
 
 	close(busyfd);
--