M alphapc/dat.h => alphapc/dat.h +1 -0
@@ 156,6 156,7 @@ struct Mach
int load;
int intr;
int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
ulong spuriousintr;
int lastintr;
M bitsy/dat.h => bitsy/dat.h +1 -0
@@ 136,6 136,7 @@ struct Mach
vlong intrts; /* time stamp of last interrupt */
ulong spuriousintr;
int lastintr;
+ int ilockdepth;
int flushmmu; /* make current proc flush it's mmu state */
Proc *pid2proc[31]; /* what proc holds what pid */
M mtx/dat.h => mtx/dat.h +1 -0
@@ 151,6 151,7 @@ struct Mach
int load;
int intr;
int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
ulong ptabbase; /* start of page table in kernel virtual space */
int slotgen; /* next pte (byte offset) when pteg is full */
M pc/dat.h => pc/dat.h +1 -0
@@ 177,6 177,7 @@ struct Mach
int intr;
vlong intrts; /* time stamp of last interrupt */
int flushmmu; /* make current proc flush it's mmu state */
+ int ilockdepth;
ulong spuriousintr;
int lastintr;
M pc/pci.c => pc/pci.c +8 -8
@@ 57,7 57,7 @@ enum
};
static Lock pcicfglock;
-static QLock pcicfginitlock;
+static Lock pcicfginitlock;
static int pcicfgmode = -1;
static int pcimaxbno = 7;
static int pcimaxdno;
@@ 498,9 498,9 @@ pciscan(int bno, Pcidev **list)
{
int ubn;
- qlock(&pcicfginitlock);
+ lock(&pcicfginitlock);
ubn = pcilscan(bno, list);
- qunlock(&pcicfginitlock);
+ unlock(&pcicfginitlock);
return ubn;
}
@@ 747,7 747,7 @@ pcicfginit(void)
Pcidev **list;
ulong mema, ioa;
- qlock(&pcicfginitlock);
+ lock(&pcicfginitlock);
if(pcicfgmode != -1)
goto out;
@@ 839,14 839,14 @@ pcicfginit(void)
pcibusmap(pciroot, &mema, &ioa, 1);
DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
- qunlock(&pcicfginitlock);
+ unlock(&pcicfginitlock);
return;
}
pcirouting();
out:
- qunlock(&pcicfginitlock);
+ unlock(&pcicfginitlock);
}
@@ 1117,9 1117,9 @@ pcihinv(Pcidev* p)
{
if(pcicfgmode == -1)
pcicfginit();
- qlock(&pcicfginitlock);
+ lock(&pcicfginitlock);
pcilhinv(p);
- qunlock(&pcicfginitlock);
+ unlock(&pcicfginitlock);
}
void
M pc/trap.c => pc/trap.c +1 -0
@@ 287,6 287,7 @@ trap(Ureg* ureg)
*/
if(ctl->isintr && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK)
if(up && up->state == Running)
+ if(up->nlocks == 0)
if(anyhigher())
if(up->preempted == 0)
if(!active.exiting){
A pc/vgai81x.c => pc/vgai81x.c +281 -0
@@ 0,0 1,281 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <cursor.h>
+#include "screen.h"
+
+typedef struct
+{
+ ushort ctl;
+ ushort pad;
+ ulong base;
+ ulong pos;
+} CursorI81x;
+
+enum {
+ Fbsize = 8*MB,
+
+ hwCur = 0x70080,
+};
+
+static Pcidev *
+i81xpcimatch(void)
+{
+ Pcidev *p;
+
+ p = nil;
+ while((p = pcimatch(p, 0x8086, 0)) != nil){
+ switch(p->did){
+ default:
+ continue;
+ case 0x7121:
+ case 0x7123:
+ case 0x7125:
+ case 0x1102:
+ case 0x1112:
+ case 0x1132:
+ return p;
+ }
+ }
+ return nil;
+}
+
+static ulong
+i81xlinear(VGAscr* scr, int* size, int* align)
+{
+ Pcidev *p;
+ int oapsize, wasupamem;
+ ulong aperture, oaperture, fbuf, fbend, *rp;
+
+ oaperture = scr->aperture;
+ oapsize = scr->apsize;
+ wasupamem = scr->isupamem;
+
+ aperture = 0;
+ p = i81xpcimatch();
+ if(p != nil) {
+ aperture = p->mem[0].bar & ~0x0F;
+ *size = p->mem[0].size;
+ if(*size > Fbsize)
+ *size = Fbsize;
+ }
+
+ if(wasupamem){
+ if(oaperture == aperture)
+ return oaperture;
+ upafree(oaperture, oapsize);
+ }
+ scr->isupamem = 0;
+
+ aperture = upamalloc(aperture, *size, *align);
+ if(aperture == 0){
+ if(wasupamem && upamalloc(oaperture, oapsize, 0)){
+ aperture = oaperture;
+ scr->isupamem = 1;
+ }
+ else
+ scr->isupamem = 0;
+ }
+ else
+ scr->isupamem = 1;
+
+ /* allocate space for frame buffer, populate page table */
+ if(oapsize == 0) {
+ fbuf = PADDR(xspanalloc(*size, BY2PG, 0));
+ fbend = PGROUND(fbuf+*size);
+ rp = KADDR(scr->io+0x10000);
+ while(fbuf < fbend) {
+ *rp++ = fbuf | (1<<0);
+ fbuf += BY2PG;
+ }
+ }
+ return aperture;
+}
+
+static void
+i81xenable(VGAscr* scr)
+{
+ Pcidev *p;
+ int align, size;
+ Mach *mach0;
+ ulong aperture, pgtbl, *rp, cursor, *pte;
+
+ /*
+ * Only once, can't be disabled for now.
+ * scr->io holds the physical address of
+ * the MMIO registers.
+ */
+ if(scr->io)
+ return;
+ p = i81xpcimatch();
+ if(p == nil)
+ return;
+ scr->io = upamalloc(p->mem[1].bar & ~0x0F, p->mem[1].size, 0);
+ if(scr->io == 0)
+ return;
+
+ /* allocate page table */
+ pgtbl = PADDR(xspanalloc(64*1024, BY2PG, 0));
+ rp = KADDR(scr->io+0x2020);
+ *rp = pgtbl | 1;
+
+ addvgaseg("i81xmmio", (ulong)scr->io, p->mem[0].size);
+
+ size = p->mem[0].size;
+ align = 0;
+ aperture = i81xlinear(scr, &size, &align);
+ if(aperture){
+ scr->aperture = aperture;
+ scr->apsize = size;
+ addvgaseg("i81xscreen", aperture, size);
+ }
+
+ /*
+ * allocate space for the cursor data in system memory.
+ * must be uncached.
+ */
+ cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
+ mach0 = MACHP(0);
+ pte = mmuwalk(mach0->pdb, cursor, 2, 0);
+ if(pte == nil)
+ panic("i81x cursor");
+ *pte |= PTEUNCACHED;
+ scr->storage = PADDR(cursor);
+}
+
+static void
+i81xcurdisable(VGAscr* scr)
+{
+ CursorI81x *hwcurs;
+
+ if(scr->io == 0)
+ return;
+ hwcurs = KADDR(scr->io+hwCur);
+ hwcurs->ctl = (1<<4);
+}
+
+static void
+i81xcurload(VGAscr* scr, Cursor* curs)
+{
+ int y;
+ uchar *p;
+ CursorI81x *hwcurs;
+
+ if(scr->io == 0)
+ return;
+ hwcurs = KADDR(scr->io+hwCur);
+
+ /*
+ * Disable the cursor then load the new image in
+ * the top-left of the 32x32 array.
+ * Unused portions of the image have been initialised to be
+ * transparent.
+ */
+ hwcurs->ctl = (1<<4);
+ p = KADDR(scr->storage);
+ for(y = 0; y < 16; y += 2) {
+ *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
+ *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
+ p += 2;
+ *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
+ *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
+ p += 2;
+ *p++ = curs->set[2*y];
+ *p++ = curs->set[2*y+1];
+ p += 2;
+ *p++ = curs->set[2*y+2];
+ *p++ = curs->set[2*y+3];
+ p += 2;
+ }
+
+ /*
+ * Save the cursor hotpoint and enable the cursor.
+ * The 0,0 cursor point is top-left.
+ */
+ scr->offset.x = curs->offset.x;
+ scr->offset.y = curs->offset.y;
+ hwcurs->ctl = (1<<4)|1;
+}
+
+static int
+i81xcurmove(VGAscr* scr, Point p)
+{
+ int x, y;
+ ulong pos;
+ CursorI81x *hwcurs;
+
+ if(scr->io == 0)
+ return 1;
+ hwcurs = KADDR(scr->io+hwCur);
+
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
+ pos = 0;
+ if(x < 0) {
+ pos |= (1<<15);
+ x = -x;
+ }
+ if(y < 0) {
+ pos |= (1<<31);
+ y = -y;
+ }
+ pos |= ((y&0x7ff)<<16)|(x&0x7ff);
+ hwcurs->pos = pos;
+
+ return 0;
+}
+
+static void
+i81xcurenable(VGAscr* scr)
+{
+ int i;
+ uchar *p;
+ CursorI81x *hwcurs;
+
+ i81xenable(scr);
+ if(scr->io == 0)
+ return;
+ hwcurs = KADDR(scr->io+hwCur);
+
+ /*
+ * Initialise the 32x32 cursor to be transparent in 2bpp mode.
+ */
+ hwcurs->base = scr->storage;
+ p = KADDR(scr->storage);
+ for(i = 0; i < 32/2; i++) {
+ memset(p, 0xff, 8);
+ memset(p+8, 0, 8);
+ p += 16;
+ }
+ /*
+ * Load, locate and enable the 32x32 cursor in 2bpp mode.
+ */
+ i81xcurload(scr, &arrow);
+ i81xcurmove(scr, ZP);
+}
+
+VGAdev vgai81xdev = {
+ "i81x",
+
+ i81xenable,
+ nil,
+ nil,
+ i81xlinear,
+};
+
+VGAcur vgai81xcur = {
+ "i81xhwgc",
+
+ i81xcurenable,
+ i81xcurdisable,
+ i81xcurload,
+ i81xcurmove,
+};
M port/edf.c => port/edf.c +3 -0
@@ 40,6 40,7 @@ int ntasks;
Resource resources[Maxresources];
int nresources;
int edfstateupdate;
+int misseddeadlines;
enum{
Deadline, /* Invariant for schedulability test: Deadline < Release */
@@ 465,6 466,8 @@ edfdeadlineintr(Ureg*, Timer*)
if (t->d <= now || t->S == 0LL){
/* Task has reached its deadline/slice, remove from queue */
+ if (t->S > 0LL)
+ misseddeadlines++;
deadline(up, SSlice);
while (t = edfstack[m->machno].head){
if (now < t->d)
M port/proc.c => port/proc.c +5 -3
@@ 87,10 87,12 @@ schedinit(void) /* never returns */
void
sched(void)
{
+ if(m->ilockdepth)
+ panic("ilockdepth %d", m->ilockdepth);
+
if(up){
- if(up->state == Running && up->nlocks){
- up->delaysched = 1;
- delayedscheds++;
+ if(up->nlocks && up->state != Moribund){
+ delayedscheds++;
return;
}
M port/qlock.c => port/qlock.c +20 -11
@@ 13,10 13,22 @@ struct {
ulong qlockq;
} rwstats;
+int shutup=1; /* RSC: you can take this out, it's just to silence a print in a loop on the dist floppy */
void
qlock(QLock *q)
{
- Proc *p, *mp;
+ Proc *p;
+
+ if(up == 0)
+ panic("qlock");
+ if(m->ilockdepth != 0 && !shutup){
+ print("qlock: %lux: ilockdepth %d", getcallerpc(&q), m->ilockdepth);
+ shutup = 1;
+ }
+ if(up->nlocks && !shutup){
+ print("qlock: %lux: nlocks %d", getcallerpc(&q), up->nlocks);
+ shutup = 1;
+ }
lock(&q->use);
rwstats.qlock++;
@@ 27,20 39,17 @@ qlock(QLock *q)
}
rwstats.qlockq++;
p = q->tail;
- mp = up;
- if(mp == nil)
- panic("qlock");
if(p == 0)
- q->head = mp;
+ q->head = up;
else
- p->qnext = mp;
- q->tail = mp;
- mp->qnext = 0;
- mp->state = Queueing;
+ p->qnext = up;
+ q->tail = up;
+ up->qnext = 0;
+ up->state = Queueing;
up->qpc = getcallerpc(&q);
unlock(&q->use);
- if (isedf(mp))
- edfblock(mp);
+ if (isedf(up))
+ edfblock(up);
sched();
}
M port/segment.c => port/segment.c +1 -1
@@ 112,6 112,7 @@ putseg(Segment *s)
unlock(s);
return;
}
+ unlock(s);
qlock(&s->lk);
if(i)
@@ 127,7 128,6 @@ putseg(Segment *s)
free(s->map);
if(s->profile != 0)
free(s->profile);
- unlock(s); /* keep lock/unlocks balanced */
free(s);
}
M port/taslock.c => port/taslock.c +4 -10
@@ 36,9 36,6 @@ lockloop(Lock *l, ulong pc)
dumpaproc(up);
if(p != nil)
dumpaproc(p);
-
- if(up && up->state == Running && islo())
- sched();
}
int
@@ 99,6 96,7 @@ ilock(Lock *l)
lockstats.locks++;
x = splhi();
+ m->ilockdepth++;
if(tas(&l->key) == 0){
if(up)
up->lastlock = l;
@@ 164,13 162,8 @@ unlock(Lock *l)
l->key = 0;
coherence();
- /* give up the processor if ... */
- if(up && --up->nlocks == 0 /* we've closed the last nexted lock */
- && up->delaysched /* we delayed scheduling because of the lock */
- && up->state == Running){ /* we're in running state */
- up->delaysched = 0;
- sched();
- }
+ if(up)
+ --up->nlocks;
}
void
@@ 190,5 183,6 @@ iunlock(Lock *l)
coherence();
m->splpc = getcallerpc(&l);
+ m->ilockdepth--;
splxpc(sr);
}