9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] usb/kb fault ... and fix
@ 2013-09-22  1:39 erik quanstrom
  0 siblings, 0 replies; only message in thread
From: erik quanstrom @ 2013-09-22  1:39 UTC (permalink / raw)
  To: 9fans

i had a fault in usb/kb this evening, and have a proposed fix.
it also seemed like a good time to address the goto soup in repeatproc.
by moving the timer into its own proc, it was possible to turn
repeatproc into a case statement.  the downside is there's
a tiny bit of busy work going on between the timer and repeat proc.

minooka; apatch/diffemail
email
	quanstro@quanstro.net
readme
	as there was no interlock for the repeat process shutdown, it was possible
	to free the channel before the repeat process had a chance to shut down,
	so if a repeating keyboard were unplugged, a crash could result.  this was
	seen as in this
	bootes          152    0:00   0:00     4096K Broken   usbd [kbd repeat]
	with this console output:
	
	chula# ````````````````````````````kb: /dev/usb/ep8.1: read: crc/timeout error
	kb: exiting
	`152: usbd: bootes: fault addr=0xcafebac2 kpc=0x20854e
	usbd 152: suicide: sys: trap: fault read addr=0xcafebac2 pc=0x20854e
	
removed
	
files
	/sys/src/cmd/usb/kb/kb.c	kb.c

/sys/src/cmd/usb/kb/kb.c	kb.c
kb.c.orig:19,32 - kb.c:19,50
  
  enum
  {
- 	Awakemsg= 0xdeaddead,
- 	Diemsg	= 0xbeefbeef,
+ 	Stoprpt	= -2,
+ 	Tick	= -3,
+ 	Exiting	= -4,
+ 
+ 	Msec	= 1000*1000,		/* msec per ns */
+ 
  	Dwcidle	= 8,
  };
  
  typedef struct KDev KDev;
+ typedef struct Kbd Kbd;
+ typedef struct Mouse Mouse;
  typedef struct Kin Kin;
  
+ struct Kbd
+ {
+ 	Channel*	repeatc;
+ 	Channel*	exitc;
+ 	long		nproc;
+ };
+ 
+ struct Mouse
+ {
+ 	int	accel;		/* only for mouse */
+ };
+ 
  struct KDev
  {
  	Dev*	dev;		/* usb device*/
kb.c.orig:33,42 - kb.c:51,60
  	Dev*	ep;		/* endpoint to get events */
  	Kin*	in;		/* used to send events to kernel */
  	int	idle;		/* min time between reports (× 4ms) */
- 	Channel*repeatc;	/* only for keyboard */
- 	int	accel;		/* only for mouse */
  	int	bootp;		/* has associated keyboard */
  	int	debug;
+ 	Kbd;
+ 	Mouse;
  	HidRepTempl templ;
  	int	(*ptrvals)(KDev *kd, Chain *ch, int *px, int *py, int *pb);
  };
kb.c.orig:212,219 - kb.c:230,244
  		fprint(2, "kb: fatal: %s\n", sts);
  	else
  		fprint(2, "kb: exiting\n");
- 	if(kd->repeatc != nil)
- 		nbsendul(kd->repeatc, Diemsg);
+ 	if(kd->repeatc != nil){
+ 		chanclose(kd->repeatc);
+ 		for(; kd->nproc != 0; kd->nproc--)
+ 			recvul(kd->exitc);
+ 		chanfree(kd->repeatc);
+ 		chanfree(kd->exitc);
+ 		kd->repeatc = nil;
+ 		kd->exitc = nil;
+ 	}
  	dev = kd->dev;
  	kd->dev = nil;
  	if(kd->ep != nil)
kb.c.orig:392,398 - kb.c:417,423
  static void
  stoprepeat(KDev *f)
  {
- 	sendul(f->repeatc, Awakemsg);
+ 	sendul(f->repeatc, Stoprpt);
  }
  
  static void
kb.c.orig:432,478 - kb.c:457,518
  }
  
  static void
+ repeattimerproc(void *a)
+ {
+ 	Channel *c;
+ 	KDev *f;
+ 
+ 	threadsetname("kbd reptimer");
+ 	f = a;
+ 	c = f->repeatc;
+ 
+ 	for(;;){
+ 		sleep(30);
+ 		if(sendul(c, Tick) == -1)
+ 			break;
+ 	}
+ 	sendul(f->exitc, Exiting);
+ 	threadexits("aborted");
+ }
+ 
+ static void
  repeatproc(void* a)
  {
  	KDev *f;
- 	Channel *repeatc;
- 	ulong l, t, i;
- 	uchar esc1, sc;
+ 	Channel *c;
+ 	int code;
+ 	uint l;
+ 	uvlong timeout;
  
  	threadsetname("kbd repeat");
- 	/*
- 	 * too many jumps here.
- 	 * Rewrite instead of debug, if needed.
- 	 */
  	f = a;
- 	repeatc = f->repeatc;
- 	l = Awakemsg;
- Repeat:
- 	if(l == Diemsg)
- 		goto Abort;
- 	while(l == Awakemsg)
- 		l = recvul(repeatc);
- 	if(l == Diemsg)
- 		goto Abort;
- 	esc1 = l >> 8;
- 	sc = l;
- 	t = 500;
+ 	c = f->repeatc;
+ 
+ 	timeout = 0;
+ 	code = -1;
  	for(;;){
- 		for(i = 0; i < t; i += 5){
- 			if(l = nbrecvul(repeatc))
- 				goto Repeat;
- 			sleep(5);
+ 		switch(l = recvul(c)){
+ 		default:
+ 			code = l;
+ 			timeout = nsec() + 500*Msec;
+ 			break;
+ 		case ~0ul:
+ 			sendul(f->exitc, Exiting);
+ 			threadexits("aborted");
+ 			break;
+ 		case Stoprpt:
+ 			code = -1;
+ 			break;
+ 		case Tick:
+ 			if(code == -1 || nsec() < timeout)
+ 				continue;
+ 			putscan(f, (uchar)(code>>8), (uchar)code);
+ 			timeout = nsec() + 30*Msec;
+ 			break;
  		}
- 		putscan(f, esc1, sc);
- 		t = 30;
  	}
- Abort:
- 	chanfree(repeatc);
- 	threadexits("aborted");
- 
  }
  
- 
  #define hasesc1(sc)	(((sc) >= 0x47) || ((sc) == 0x38))
  
  static void
kb.c.orig:560,570 - kb.c:600,617
  	if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf)
  		kbfatal(f, "weird maxpkt");
  
+ 	f->exitc = chancreate(sizeof(ulong), 0);
+ 	if(f->exitc == nil)
+ 		kbfatal(f, "chancreate failed");
  	f->repeatc = chancreate(sizeof(ulong), 0);
- 	if(f->repeatc == nil)
+ 	if(f->repeatc == nil){
+ 		chanfree(f->exitc);
  		kbfatal(f, "chancreate failed");
+ 	}
  
+ 	f->nproc = 2;
  	proccreate(repeatproc, f, Stack);
+ 	proccreate(repeattimerproc, f, Stack);
  	memset(lbuf, 0, sizeof lbuf);
  	dk = nerrs = 0;
  	for(;;){



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2013-09-22  1:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-22  1:39 [9fans] usb/kb fault ... and fix erik quanstrom

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).