From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Fri, 9 May 1997 18:30:28 -0700 From: beto@ncube.com beto@ncube.com Subject: spin-locks problem Topicbox-Message-UUID: 5ae3c526-eac8-11e9-9e20-41e7f4b1d025 Message-ID: <19970510013028.-QZTMy2Rm4tPJWAl6vS8khzatHb-G68d1bO4TiIid-w@z> Here is the problem which dhog mentioned: long bitread(Chan *c, void *va, long n, ulong offset) { uchar *p, *q; long miny, maxy, t, x, y; ulong l, nw, ws, rv, gv, bv; int off, j; Fontchar *i; GBitmap *src; BSubfont *s; static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; if(!conf.monitor) error(Egreg); if(c->qid.path & CHDIR) return devdirread(c, va, n, bitdir, NBIT, devgen); if(c->qid.path == Qmouse){ /* * mouse: * 'm' 1 * buttons 1 * point 8 * msec 4 */ if(n < 14) error(Ebadblt); while(mousechanged(0) == 0) sleep(&mouse.r, mousechanged, 0); lock(&cursor); p = va; ************************ accessing va could cause a page fault which could sleep in a qlock in seg() or reading the page. A simple solution is to add uchar buf[14]; and then replace lock(&cursor); p = buf; p[0] = 'm'; ...... unlock(&cursor); memmove(va,buf,14); There are plenty of places in plan9 where we could sleep holding a spin-lock. For example in the same driver Chan* bitopen(Chan *c, int omode) { GBitmap *b; if(!conf.monitor) error(Egreg); switch(c->qid.path){ case CHDIR: ... case Qmouse: ... case Qbitblt: lock(&bit); if(bit.bitbltopen || bit.mouseopen){ unlock(&bit); error(Einuse); } b = smalloc(sizeof(GBitmap));*************** smalloc could sleep while holding bit. We actually added some code to qlock and sleep so we capture calls while holding spin-locks.