mcs locks charles take on mcs locks. the changes should be mostly straightforward and self-explanitory. except the new rule is we must not sched with a lock ever. (no scratch-n-sniff tests.) due to the structure of the mcs lock, we now need a few functions to find the pc of the locker. in theory we could build a has/want table such as the file server provides from this. Reference: /n/atom/patch/applied/mcslocks Date: Thu Mar 27 06:33:18 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/port/tiklock.c Thu Mar 27 06:28:43 2014 +++ /sys/src/nix/port/tiklock.c Thu Mar 27 06:28:44 2014 @@ -166,9 +166,10 @@ p = l->p; if(lockdebug > 1){ - dumpaproc(up); - if(p != nil) + if(up != nil) dumpaproc(up); + if(p != nil) + dumpaproc(p); } showlockloops(); panic("cpu%d: %s lock %#p key %#p pc %#p proc %ud held by pc %#p proc %ud\n", @@ -395,4 +396,24 @@ if(up) up->lastilock = nil; splx(s); +} + +int +ownlock(Lock *l) +{ + return l->m == MACHP(m->machno); +} + +uintptr +lockgetpc(Lock *l) +{ + if(l != nil) + return l->pc; + return 0; +} + +void +locksetpc(Lock *l, uintptr pc) +{ + l->pc = pc; } --- /sys/src/nix/port/sysproc.c Thu Mar 27 06:28:47 2014 +++ /sys/src/nix/port/sysproc.c Thu Mar 27 06:28:48 2014 @@ -950,7 +950,7 @@ * queued processor writes into account so we have to * think hard. The only variables accessed outside locks * are the semaphore value itself and the boolean flag - * Sema.waiting. The value is only accessed with CAS, + * Sema.waiting. The value is only accessed with cas, * whose job description includes doing the right thing as * far as memory coherence across processors. That leaves * Sema.waiting. To handle it, we call coherence() before each @@ -1008,7 +1008,7 @@ do value = *addr; - while(!CASW(addr, value, value+delta)); + while(!cas32(addr, value, value+delta)); semwakeup(s, addr, delta); return value+delta; @@ -1021,7 +1021,7 @@ int value; while((value = *addr) > 0){ - if(CASW(addr, value, value-1)) + if(cas32(addr, value, value-1)) return 1; } --- /sys/src/nix/port/segment.c Thu Mar 27 06:28:49 2014 +++ /sys/src/nix/port/segment.c Thu Mar 27 06:28:50 2014 @@ -374,7 +374,7 @@ Segment *s; s = up->seg[TSEG]; - if(s == 0 || s->profile == 0) + if(s == nil || s->profile == 0) return; s->profile[0] += TK2MS(1); --- /sys/src/nix/port/taslock.c Thu Mar 27 06:28:52 2014 +++ /sys/src/nix/port/taslock.c Thu Mar 27 06:28:52 2014 @@ -43,7 +43,7 @@ lockstats.locks++; if(up) ainc(&up->nlocks); /* prevent being scheded */ - if(TAS(&l->key) == 0){ + if(tas(&l->key) == 0){ if(up) up->lastlock = l; l->pc = pc; @@ -80,7 +80,7 @@ } if(up) ainc(&up->nlocks); - if(TAS(&l->key) == 0){ + if(tas(&l->key) == 0){ if(up) up->lastlock = l; l->pc = pc; @@ -108,7 +108,7 @@ lockstats.locks++; pl = splhi(); - if(TAS(&l->key) != 0){ + if(tas(&l->key) != 0){ cycles(&t0); lockstats.glare++; /* @@ -122,7 +122,7 @@ while(l->key) pause(); pl = splhi(); - if(TAS(&l->key) == 0){ + if(tas(&l->key) == 0){ if(l != &waitstatslk) addwaitstat(pc, t0, WSlock); goto acquire; @@ -147,7 +147,7 @@ { if(up) ainc(&up->nlocks); - if(TAS(&l->key)){ + if(tas(&l->key)){ if(up) adec(&up->nlocks); return 0; @@ -232,4 +232,24 @@ if(up) up->lastilock = nil; splx(pl); +} + +int +ownlock(Lock *l) +{ + return l->m == MACHP(m->machno); +} + +uintptr +lockgetpc(Lock *l) +{ + if(l != nil) + return l->pc; + return 0; +} + +void +locksetpc(Lock *l, uintptr pc) +{ + l->pc = pc; } --- /sys/src/nix/port/portdat.h Thu Mar 27 06:28:55 2014 +++ /sys/src/nix/port/portdat.h Thu Mar 27 06:28:56 2014 @@ -14,10 +14,11 @@ typedef struct Image Image; typedef struct Log Log; typedef struct Logflag Logflag; -typedef struct Lockstats Lockstats; +typedef struct Lockstats Lockstats; +typedef struct LockEntry LockEntry; typedef struct Mhead Mhead; typedef struct Mnt Mnt; -typedef struct Mntcache Mntcache; +typedef struct Mntcache Mntcache; typedef struct Mntrpc Mntrpc; typedef struct Mntwalk Mntwalk; typedef struct Mount Mount; @@ -26,7 +27,7 @@ typedef struct Pallocmem Pallocmem; typedef struct Path Path; typedef struct Perf Perf; -typedef struct Pgalloc Pgalloc; +typedef struct Pgalloc Pgalloc; typedef struct Pgrp Pgrp; typedef struct Pgsza Pgsza; typedef struct Physseg Physseg; @@ -35,7 +36,7 @@ typedef struct Procalloc Procalloc; typedef struct Pte Pte; typedef struct QLock QLock; -typedef struct QLockstats QLockstats; +typedef struct QLockstats QLockstats; typedef struct Queue Queue; typedef struct Ref Ref; typedef struct Rendez Rendez; @@ -100,6 +101,22 @@ int nstats; int nsalloc; Waitstat *stat; +}; + +struct LockEntry +{ + LockEntry* next; + uint locked; + Lock* used; + int isilock; + union { /* GAK */ + Mpl pl; + Mreg sr; + }; + /* for debugging */ + uintptr pc; + Proc* p; + Mach* m; }; struct Lockstats --- /sys/src/nix/port/portfns.h Thu Mar 27 06:28:58 2014 +++ /sys/src/nix/port/portfns.h Thu Mar 27 06:28:59 2014 @@ -153,6 +153,8 @@ void kstrdup(char**, char*); long latin1(Rune*, int); int lock(Lock*); +uintptr lockgetpc(Lock*); +void locksetpc(Lock*, uintptr); void log(Log*, int, char*, ...); int log2ceil(uintmem); void log2init(void); @@ -209,6 +211,7 @@ uvlong ns2fastticks(uvlong); int okaddr(uintptr, long, int); int openmode(int); +int ownlock(Lock*); Block* packblock(Block*); Block* padblock(Block*, int); void pagechainhead(Page*); @@ -350,6 +353,7 @@ uintptr sysexecstack(uintptr, int); void sysrforkchild(Proc*, Proc*); void sysprocsetup(Proc*); +#define tickscmp(a, b) ((long)((a)-(b))) void timeradd(Timer*); void timerdel(Timer*); void timerintr(Ureg*, void*); --- /sys/src/nix/port/edf.c Thu Mar 27 06:29:01 2014 +++ /sys/src/nix/port/edf.c Thu Mar 27 06:29:02 2014 @@ -69,13 +69,13 @@ sign = ""; if (t > Onesecond){ t += OneRound; - sprint(buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), + snprint(buf, sizeof buf, "%s%d.%.3ds", sign, (int)(t / Onesecond), (int)(t % Onesecond)/Onemillisecond); }else if (t > Onemillisecond) - sprint(buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), + snprint(buf, sizeof buf, "%s%d.%.3dms", sign, (int)(t / Onemillisecond), (int)(t % Onemillisecond)); else - sprint(buf, "%s%dµs", sign, (int)t); + snprint(buf, sizeof buf, "%s%dµs", sign, (int)t); return fmtstrcpy(f, buf); } @@ -90,7 +90,7 @@ return nil; ilock(&thelock); if((e = p->edf) && (e->flags & Admitted)){ - thelock.pc = getcallerpc(&p); + locksetpc(&thelock, getcallerpc(&p)); #ifdef EDFCYCLES edfcycles -= lcycles(); #endif --- /sys/src/nix/port/devuart.c Thu Mar 27 06:29:03 2014 +++ /sys/src/nix/port/devuart.c Thu Mar 27 06:29:04 2014 @@ -246,15 +246,15 @@ p = uartlist; for(i = 0; i < uartnuart; i++){ /* 3 directory entries per port */ - sprint(dp->name, "eia%d", i); + snprint(dp->name, sizeof dp->name, "eia%d", i); dp->qid.path = UARTQID(i, Qdata); dp->perm = 0660; dp++; - sprint(dp->name, "eia%dctl", i); + snprint(dp->name, sizeof dp->name, "eia%dctl", i); dp->qid.path = UARTQID(i, Qctl); dp->perm = 0660; dp++; - sprint(dp->name, "eia%dstatus", i); + snprint(dp->name, sizeof dp->name, "eia%dstatus", i); dp->qid.path = UARTQID(i, Qstat); dp->perm = 0444; dp++; --- /sys/src/nix/port/proc.c Thu Mar 27 06:29:07 2014 +++ /sys/src/nix/port/proc.c Thu Mar 27 06:29:09 2014 @@ -60,7 +60,7 @@ "Stopped", "Rendez", "Waitrelease", - "Down", + "Semdown", }; void @@ -70,7 +70,7 @@ color = machcolor(mp); if(color < 0){ -// print("cpu%d: unknown color\n", mp->machno); + iprint("cpu%d: unknown color\n", mp->machno); color = 0; } mp->sch = &run[color%Nsched]; @@ -111,17 +111,13 @@ Edf *e; m->inidle = 1; - if(m->sch == nil){ - print("schedinit: no sch for cpu%d\n", m->machno); - setmachsched(m); - } ainc(&m->sch->nmach); setlabel(&m->sched); if(up) { if((e = up->edf) && (e->flags & Admitted)) edfrecord(up); - m->proc = 0; + m->proc = nil; switch(up->state) { case Running: ready(up); @@ -148,8 +144,10 @@ psrelease(up); up->mach = nil; updatecpu(up); - up = procalloc.p = nil; /* lock knows too much */ + unlock(&procalloc); + up = nil; + break; } } @@ -170,7 +168,8 @@ p = &dummy; if(p < up->kstack + 4*KiB || p > up->kstack + KSTACK) - panic("cpu%d: up->stack out-of-bounds %#p %#p", m->machno, p, up->kstack); + panic("cpu%d: up->stack bounds %s:%s %#p %#p", + m->machno, up->text, statename[up->state], p, up->kstack); } /* @@ -189,7 +188,7 @@ m->machno, m->ilockdepth, up? up->lastilock: nil, - (up && up->lastilock)? up->lastilock->pc: 0, + (up && up->lastilock)? lockgetpc(up->lastilock): m->ilockpc, getcallerpc(&p+2)); if(up){ @@ -207,11 +206,7 @@ * instructions in the middle of taslock when a process * holds a lock but Lock.p has not yet been initialized. */ - if(up->nlocks) - if(up->state != Moribund) - if(up->delaysched < 20 - || pga.Lock.p == up - || procalloc.Lock.p == up){ + if(up->nlocks && up->state != Moribund){ up->delaysched++; sch->delayedscheds++; return; @@ -427,8 +422,8 @@ pri = rq - sch->runq; if(!locked) lock(sch); - else if(canlock(sch)) - panic("queueproc: locked and can lock"); +// else if(canlock(sch)) +// panic("queueproc: locked and can lock"); p->priority = pri; p->rnext = 0; if(rq->tail) @@ -483,7 +478,7 @@ rq->n--; sch->nrdy--; if(p->state != Ready) - print("dequeueproc %s %d %s\n", p->text, p->pid, statename[p->state]); + iprint("dequeueproc %s %d %s\n", p->text, p->pid, statename[p->state]); unlock(sch); return p; @@ -769,6 +764,7 @@ p->procctl = 0; p->syscalltrace = nil; p->notepending = 0; + p->nnote = 0; p->ureg = 0; p->privatemem = 0; p->noswap = 0; @@ -869,11 +865,7 @@ pri = 0; p->basepri = pri; p->priority = pri; - if(fixed){ - p->fixedpri = 1; - } else { - p->fixedpri = 0; - } + p->fixedpri = fixed; } /* @@ -893,7 +885,7 @@ if(up->nlocks) print("process %d sleeps with %d locks held, last lock %#p locked at pc %#p, sleep called from %#p\n", - up->pid, up->nlocks, up->lastlock, up->lastlock->pc, getcallerpc(&r)); + up->pid, up->nlocks, up->lastlock, lockgetpc(up->lastlock), getcallerpc(&r)); lock(r); lock(&up->rlock); if(r->p){ @@ -1202,7 +1194,7 @@ up->syscalltrace = nil; up->alarm = 0; - if (up->tt) + if(up->tt) timerdel(up); if(up->trace) proctrace(up, SDead, 0); @@ -1221,7 +1213,6 @@ up->dot = nil; qunlock(&up->debug); - if(fgrp) closefgrp(fgrp); if(egrp) @@ -1399,7 +1390,7 @@ print("%3d:%10s pc %#p dbgpc %#p %8s (%s) ut %ld st %ld bss %#p qpc %#p nl %d nd %ud lpc %#p pri %ud\n", p->pid, p->text, p->pc, dbgpc(p), s, statename[p->state], p->time[0], p->time[1], bss, p->qpc, p->nlocks, - p->delaysched, p->lastlock ? p->lastlock->pc : 0, p->priority); + p->delaysched, lockgetpc(p->lastlock), p->priority); } void @@ -1494,7 +1485,11 @@ Proc *p; static Pgrp *kpgrp; + while(waserror()) + ; p = newproc(); + poperror(); + p->psstate = 0; p->procmode = 0640; p->kp = 1; @@ -1530,13 +1525,6 @@ memset(p->time, 0, sizeof(p->time)); p->time[TReal] = sys->ticks; ready(p); - /* - * since the bss/data segments are now shareable, - * any mmu info about this process is now stale - * and has to be discarded. - */ - p->newtlb = 1; - mmuflush(); } /* @@ -1607,7 +1595,7 @@ { char buf[ERRMAX]; - sprint(buf, "no free %s", resource); + snprint(buf, sizeof buf, "no free %s", resource); iprint("%s\n", buf); error(buf); } --- /sys/src/nix/port/devcons.c Thu Mar 27 06:29:11 2014 +++ /sys/src/nix/port/devcons.c Thu Mar 27 06:29:13 2014 @@ -45,7 +45,7 @@ static Queue* kbdq; /* unprocessed console input */ static Queue* lineq; /* processed console input */ static Queue* kprintoq; /* console output, for /dev/kprint */ -static ulong kprintinuse; /* test and set whether /dev/kprint is open */ +static int kprintinuse; /* test and set whether /dev/kprint is open */ int panicking; @@ -365,7 +365,7 @@ for(i=0; i<1000; i++){ if(canlock(l)) return 1; - if(l->m == MACHP(m->machno)) + if(ownlock(l)) return 0; microdelay(100); } @@ -775,7 +775,7 @@ break; case Qkprint: - if(TAS(&kprintinuse) != 0){ + if(tas(&kprintinuse) != 0){ c->flag &= ~COPEN; error(Einuse); } --- /sys/src/nix/port/mcslock.c Thu Jan 1 00:00:00 1970 +++ /sys/src/nix/port/mcslock.c Thu Mar 27 06:29:13 2014 @@ -0,0 +1,220 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#include "../port/edf.h" + +#define D(c) if(0)cgapost((c)) + +static void +mcslock(Lock *lk, LockEntry *ql) +{ + LockEntry *pred; + + D('!'); + ql->next = nil; + ql->locked = 0; + pred = fasp(&lk->head, ql); + if(pred != nil){ + ql->locked = 1; + sfence(); /* ensure reader sees updated value */ + pred->next = ql; + while(monmwait32(&ql->locked, 1) == 1) + {} + } +} + +static int +mcscanlock(Lock *lk, LockEntry *ql) +{ + D('?'); + ql->next = nil; + ql->locked = 0; + return casp(&lk->head, nil, ql); +} + +static LockEntry* +mcsunlock(Lock *lk, LockEntry *ql) +{ + D('#'); + if(ql->next != nil || !casp(&lk->head, ql, nil)){ + /* successor, wait for list to catch up */ + while(ql->next == nil) + {} + ql->next->locked = 0; + sfence(); + } + return ql; +} + +static LockEntry* +allocle(Lock *l, uintptr pc) +{ + LockEntry *a; + int i; + + a = &m->locks[0]; + if(a->used != nil){ + i = nelem(m->locks)-1; + while(--i >= 0){ + a++; + if(a->used == nil) + break; + } + if(i < 0) + panic("allocle: need more m->locks"); + } + a->used = l; /* must be first, to claim against interrupts */ + a->pc = pc; + a->p = up; + a->m = m; + a->isilock = 0; + return a; +} + +static LockEntry* +findle(Lock *l) +{ + LockEntry *a; + + a = l->e; + if(a->used != l) + panic("findle"); + return a; +} + +int +lock(Lock *l) +{ + LockEntry *ql; + + if(up != nil) + up->nlocks++; + ql = allocle(l, getcallerpc(&l)); + mcslock(l, ql); + l->e = ql; + return 0; +} + +int +canlock(Lock *l) +{ + LockEntry *ql; + + if(up != nil) + up->nlocks++; + ql = allocle(l, getcallerpc(&l)); + if(mcscanlock(l, ql)){ + l->e = ql; + return 1; + } + ql->used = nil; + if(up != nil) + up->nlocks--; + return 0; +} + +void +unlock(Lock *l) +{ + LockEntry *ql; + + if(l->head == nil){ + print("unlock: not locked: pc %#p\n", getcallerpc(&l)); + return; + } + ql = findle(l); + if(ql->isilock) + panic("unlock of ilock: pc %#p", getcallerpc(&l)); + if(ql->p != up) + panic("unlock: up changed: pc %#p, acquired at pc %#p, lock p %#p, unlock up %#p", + getcallerpc(&l), ql->pc, ql->p, up); + mcsunlock(l, ql); + ql->used = nil; + if(up != nil && --up->nlocks == 0 && up->delaysched && islo()){ + /* + * Call sched if the need arose while locks were held + * But, don't do it from interrupt routines, hence the islo() test + */ + sched(); + } +} + +void +ilock(Lock *l) +{ + uintptr pc; + Mreg s; + LockEntry *ql; + + pc = getcallerpc(&l); + s = splhi(); + ql = allocle(l, pc); + ql->isilock = 1; + ql->sr = s; + /* the old taslock code would splx(s) to allow interrupts while waiting (if not nested) */ + mcslock(l, ql); + l->e = ql; + m->ilockdepth++; + m->ilockpc = pc; + if(up != nil) + up->lastilock = l; +} + +void +iunlock(Lock *l) +{ + Mreg s; + LockEntry *ql; + + if(islo()) + panic("iunlock while lo: pc %#p\n", getcallerpc(&l)); + ql = findle(l); + if(!ql->isilock) + panic("iunlock of lock: pc %#p\n", getcallerpc(&l)); + if(ql->m != m){ + panic("iunlock by cpu%d, locked by cpu%d: pc %#p\n", + m->machno, ql->m->machno, getcallerpc(&l)); + } + mcsunlock(l, ql); + s = ql->sr; + ql->used = nil; + m->ilockdepth--; + if(up != nil) + up->lastilock = nil; + splx(s); +} + +int +ownlock(Lock *l) +{ + int i; + + for(i = 0; i < nelem(m->locks); i++) + if(m->locks[i].used == l) + return 1; + return 0; +} + +uintptr +lockgetpc(Lock *l) +{ + LockEntry *ql; + + ql = l->e; + if(ql != nil && ql->used == l) + return ql->pc; + return 0; +} + +void +locksetpc(Lock *l, uintptr pc) +{ + LockEntry *ql; + + ql = l->e; + if(ql != nil && ql->used == l && ql->m == m) + ql->pc = pc; +} --- /sys/src/nix/k10/l64v.s Thu Mar 27 06:29:15 2014 +++ /sys/src/nix/k10/l64v.s Thu Mar 27 06:29:15 2014 @@ -315,6 +315,11 @@ XCHGL AX, (RARG) /* */ RET +TEXT fas32(SB), 1, $-4 + MOVL p+8(FP), AX + LOCK; XCHGL AX, (RARG) + RET + TEXT fas64(SB), 1, $-4 MOVQ p+8(FP), AX LOCK; XCHGQ AX, (RARG) /* */ @@ -374,9 +379,9 @@ #define MWAIT BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* - * uintptr monmwait(void*, uintptr) + * u64int monmwait(u64int*, u64int) */ -TEXT k10monmwait(SB),1,$16 +TEXT k10monmwait64(SB),1,$16 MOVQ val+8(FP), BX _mmstart: @@ -397,6 +402,29 @@ /* questionable: pop out on irq */ _mmdone: MOVQ (BP), AX + RET + +TEXT k10monmwait32(SB),1,$16 + MOVQ val+8(FP), BX + +_mmstart32: + CMPL (BP), BX /* changed yet? */ + JNE _mmdone32 + + MOVQ BP, AX /* linear address to monitor */ + XORQ CX, CX /* extensions */ + XORQ DX, DX /* hints */ + MONITOR + + CMPL (BP), BX /* changed yet? */ + JNE _mmdone32 + + /*XORQ CX, CX*/ /* extensions (different from monitor) */ + XORQ AX, AX /* hints */ + MWAIT + /* questionable: pop out on irq */ +_mmdone32: + MOVL (BP), AX RET TEXT mul64fract(SB), 1, $-4 --- /sys/src/nix/k10/archk10.c Thu Mar 27 06:29:17 2014 +++ /sys/src/nix/k10/archk10.c Thu Mar 27 06:29:18 2014 @@ -7,12 +7,23 @@ #include "io.h" #include "apic.h" -void (*monmwait)(void*, uintptr) = nopmonmwait; +u64int (*monmwait64)(u64int*, uintptr) = nopmonmwait64; +u32int (*monmwait32)(u32int*, u32int) = nopmonmwait32; -void -nopmonmwait(void*, uintptr) +u64int +nopmonmwait64(u64int *p, u64int v) { -// pause(); + if(*(u64int*)p == v) + pause(); + return *(u64int*)p; +} + +u32int +nopmonmwait32(u32int *p, u32int v) +{ + if(*(u32int*)p == v) + pause(); + return *(u32int*)p; } static void @@ -21,8 +32,10 @@ u32int info[4]; cpuid(1, 0, info); - if(info[2] & 8) - monmwait = k10monmwait; + if(info[2] & 8){ + monmwait64 = k10monmwait64; + monmwait32 = k10monmwait32; + } } static int @@ -205,8 +218,6 @@ { splhi(); lapicpri(0xff); - outb(0x21, 0xff); /* 8259 pic 0: mask irqs */ - outb(0xa1, 0xff); /* 8259 pic 1: mask irqs */ for(;;) hardhalt(); } --- /sys/src/nix/k10/fns.h Thu Mar 27 06:29:19 2014 +++ /sys/src/nix/k10/fns.h Thu Mar 27 06:29:20 2014 @@ -129,15 +129,15 @@ int ainc8(void*); int cas32(void*, u32int, u32int); int cas64(void*, u64int, u64int); -int tas32(void*); +u32int fas32(u32int*, u32int); u64int fas64(u64int*, u64int); +int tas32(void*); -#define CASU(p, e, n) cas64((p), (u64int)(e), (u64int)(n)) -#define CASV(p, e, n) cas64((p), (u64int)(e), (u64int)(n)) -#define CASP(p, e, n) cas64((p), (u64int)(e), (u64int)(n)) -#define CASW(p, e, n) cas32((p), (e), (n)) -#define TAS(addr) tas32((addr)) -#define FASP(p, v) ((void*)fas64((u64int*)(p), (u64int)(v))) +#define cas(p, e, n) cas32((p), (u32int)(e), (u32int)(n)) +#define casp(p, e, n) cas64((p), (u64int)(e), (u64int)(n)) +#define fas(p, v) ((int)fas32((u32int*)(p), (u32int)(v))) +#define fasp(p, v) ((void*)fas64((u64int*)(p), (u64int)(v))) +#define tas(p) tas32(p) void touser(uintptr); void syscallentry(void); @@ -157,9 +157,15 @@ /* * archk10.c; l64v.s */ -void (*monmwait)(void*, uintptr); -void nopmonmwait(void*, uintptr); -void k10monmwait(void*, uintptr); +#define monmwait(v, o) ((int)monmwait32((u32int*)(v), (u32int)(o))) +u32int (*monmwait32)(u32int*, u32int); +u32int nopmonmwait32(u32int*, u32int); +u32int k10monmwait32(u32int*, u32int); + +#define monmwaitp(v, o) monmwait64(v, o); +u64int (*monmwait64)(u64int*, u64int); +u64int nopmonmwait64(u64int*, u64int); +u64int k10monmwait64(u64int*, u64int); /* * i8259.c --- /sys/src/nix/k10/dat.h Thu Mar 27 06:29:21 2014 +++ /sys/src/nix/k10/dat.h Thu Mar 27 06:29:22 2014 @@ -1,10 +1,12 @@ typedef struct Fxsave Fxsave; typedef struct Label Label; typedef struct Lock Lock; +typedef struct LockEntry LockEntry; typedef struct MFPU MFPU; typedef struct MMMU MMMU; typedef struct Mach Mach; typedef u64int Mpl; +typedef u64int Mreg; typedef struct Page Page; typedef struct Pcidev Pcidev; typedef struct PFPU PFPU; @@ -13,7 +15,7 @@ typedef u64int PTE; typedef struct Proc Proc; typedef struct Sys Sys; -typedef u64int uintmem; /* Physical address (hideous) */ +typedef u64int uintmem; typedef struct Ureg Ureg; typedef struct Vctl Vctl; @@ -45,6 +47,13 @@ uvlong lockcycles; }; #else +#ifdef Mcslock +struct Lock +{ + LockEntry* head; + LockEntry* e; +}; +#else struct Lock { u32int key; @@ -56,6 +65,7 @@ uvlong lockcycles; }; #endif +#endif struct Label { @@ -157,6 +167,8 @@ int apicno; int online; + LockEntry locks[8]; + MMMU; uchar* vsvm; @@ -180,6 +192,8 @@ int intr; int mmuflush; /* make current proc flush it's mmu state */ int ilockdepth; + uintptr ilockpc; + Perf perf; /* performance counters */ int inidle; /* profiling */ @@ -211,7 +225,7 @@ struct Sys { uchar machstk[MACHSTKSZ]; - PTE pml4[PTSZ/sizeof(PTE)]; /* */ + PTE pml4[PTSZ/sizeof(PTE)]; /* all this is unused; but size known to asm */ PTE pdp[PTSZ/sizeof(PTE)]; PTE pd[PTSZ/sizeof(PTE)]; PTE pt[PTSZ/sizeof(PTE)]; --- /sys/man/9/monmwait Thu Mar 27 06:29:23 2014 +++ /sys/man/9/monmwait Thu Mar 27 06:29:24 2014 @@ -1,10 +1,19 @@ .TH MONMWAIT 9 .SH NAME -monmwait \- wait for memory write +monmwait, monmwait32, monmwait64, monmwaitp \- wait for memory write .SH SYNOPSIS -.ta \w'\fLvoid 'u +.ta \w'\fLuintptr 'u .B -void monmwait(void *adr, uintptr oldval) +uint monmwait(int *adr, int oldval) +.PP +.B +uintptr monmwaitp(uintptr *adr, uintptr oldval) +.PP +.B +u64int monmwait64(u64int *adr, u64int oldval) +.PP +.B +u32int monmwait32(u32int *adr, u32int oldval) .SH DESCRIPTION Wait for the value pointed to by .B adr