From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Thu, 8 May 1997 11:32:19 -0700 From: beto@ncube.com beto@ncube.com Subject: calling sleep() while holding lock() Topicbox-Message-UUID: 5aa2909c-eac8-11e9-9e20-41e7f4b1d025 Message-ID: <19970508183219.3i6xJVJOib5aq_LgJRICHqXGTOd-QGYLjjLknWdx7DE@z> In <199705090253.496031.out.bajag@plan9.cs.su.oz.au> David Hogan wrote: > Good coding. So now the question remains: why is this behaviour > occuring? One possibility is that we take a fault while holding > the lock, and we then have to sleep until the memory gets paged in. > Alberto Nava found a place in the kernel where this is happening, and > I'm sure there must be others. > Here is the example that Dave 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 generate a page-fault. This could lead to seg() calling qlock or sleeping waiting for the actual data. There are plenty of places where plan9 does that or similar. 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: if(omode != OREAD) error(Eperm); break; case Qmouse: lock(&bit); if(bit.mouseopen){ unlock(&bit); error(Einuse); } bit.mouseopen = 1; bit.ref++; unlock(&bit); break; case Qbitblt: lock(&bit); if(bit.bitbltopen || bit.mouseopen){ unlock(&bit); error(Einuse); } b = smalloc(sizeof(GBitmap));*************************************** smalloc could make the kernel sleep waiting for memory so again holding spin-lock/sleep. Actually we have code in qlock and sleep to check for a process holding spin-lock before the calls.