Some changes in the kernel side of the semaphores. Mwait is used to reduce the pressure of the spinlock on the memory. Semwakeup changed to avoid retries. Reference: /n/patches.lsub.org/patch/syssemmwait Date: Wed Jul 4 12:19:34 CES 2012 Signed-off-by: esoriano@lsub.org --- /sys/src/nix/port/syssem.c Fri Jun 8 11:35:47 2012 +++ /sys/src/nix/port/syssem.c Wed Jul 4 12:06:00 2012 @@ -6,7 +6,7 @@ #include "../port/error.h" /* - * Sems are represented by two structures, Sem (user space) and + * Sems are characterized by two structures, Sem (user space) and * Ksem (kernel space). A Sem includes a spin lock (userlock) to * protect its three counters: * @@ -22,6 +22,7 @@ Semtrytimes = 100, Locktrytimes = 10, Maxaltsems = 300, + Lockmagic = 0xdeaddead, /* libc and kernel*/ }; /* @@ -34,19 +35,19 @@ int try; n = 0; - try = Locktrytimes; - while(tas32(&s->sem->userlock.val)){ + while(TAS(&s->sem->userlock.val)){ if(s->state == Semdead) error(Esemdead); - if(++n % 100000 == 0){ - iprint("syssem: warning, userlock busy\n"); + if(++n % 10000 == 0){ + iprint("syssem: warning userlock busy\n"); if(--try == 0){ iprint("syssem: the userlock of ksem %p is dead\n", s); s->state = Semdead; error(Esemtimeout); } } + waitwhile(&s->sem->userlock.val, Lockmagic); } return; } @@ -123,12 +124,8 @@ semwakeup(Ksem *s) { Proc* p; - int retries = 0; DBG("semwakeup up %#p sem %#p\n", up, s->sem); -retry: - if(retries != 0 && retries % 10 == 0) - print("semwakeup: %d retries\n", retries); rlock(s->semaltlock); lock(s); @@ -154,7 +151,7 @@ _userlock(s); s->sem->waiting--; _userunlock(s); - if(tas32(&p->semawaken) == 0){ + if(TAS(&p->semawaken) == 0){ poperror(); p->waitsem = s; unlock(s); @@ -173,15 +170,10 @@ if(s->sem->going > 0){ _userunlock(s); poperror(); + s->nowait++; unlock(s); runlock(s->semaltlock); - retries++; - /* - * take a break? - */ - if(retries % 3 == 0) - sched(); - goto retry; + return; } /* @@ -214,6 +206,12 @@ s->sem->going--; _userunlock(s); poperror(); + if(s->nowait > 0){ + s->nowait--; + unlock(s); + runlock(s->semaltlock); + return; + } up->semawaken = 0; up->waitsem = nil; semqueue(s, up); --- /sys/src/nix/port/portdat.h Tue Jul 3 10:40:24 2012 +++ /sys/src/nix/port/portdat.h Wed Jul 4 11:52:54 2012 @@ -474,6 +474,7 @@ int state; Proc **q; int nq; + int nowait; RWlock *semaltlock; /* located in the Segment */ Ksem *next; /* in list of semaphores for this Segment */ };