lockstats.glare++;
for(;;){
lockstats.inglare++;
i = 0;
while(l->key){
if(conf.nmach < 2 && up && up->edf && (up->edf->flags & Admitted)){
/*
* Priority inversion, yield on a uniprocessor; on a
* multiprocessor, the other processor will unlock
*/
print("inversion %#p pc %#p proc %lud held by pc %#p proc %lud\n",
l, pc, up ? up->pid : 0, l->pc, l->p ? l->p->pid : 0);
up->edf->d = todget(nil); /* yield to process with lock */
}
if(i++ > 100000000){
i = 0;
lockloop(l, pc);
}
}
if(up)
up->nlocks++;
if(tas(&l->key) == 0){
if(up)
up->lastlock = l;
l->pc = pc;
l->p = up;
l->m = MACHP(m->machno);
l->isilock = 0;
#ifdef LOCKCYCLES
l->lockcycles = -lcycles();
#endif
return 1;
}
if(up)
up->nlocks--;
}
}
void
ilock(Lock *l)
{
ulong x;
uintptr pc;
pc = getcallerpc(&l);
lockstats.locks++;
x = splhi();
if(tas(&l->key) != 0){
lockstats.glare++;
/*
* Cannot also check l->pc, l->m, or l->isilock here
* because they might just not be set yet, or
* (for pc and m) the lock might have just been unlocked.
*/
for(;;){
lockstats.inglare++;
splx(x);
while(l->key)
;
x = splhi();
if(tas(&l->key) == 0)
goto acquire;
}
}
acquire:
m->ilockdepth++;
if(up)
up->lastilock = l;
l->sr = x;
l->pc = pc;
l->p = up;
l->m = MACHP(m->machno);
l->isilock = 1;
#ifdef LOCKCYCLES
l->lockcycles = -lcycles();
#endif
}
void
unlock(Lock *l)
{
#ifdef LOCKCYCLES
l->lockcycles += lcycles();
cumlockcycles += l->lockcycles;
if(l->lockcycles > maxlockcycles){
maxlockcycles = l->lockcycles;
maxlockpc = l->pc;
}
#endif
if(l->key == 0)
print("unlock(%#p): not locked: pc %#p\n",
l, getcallerpc(&l));
if(l->isilock)
print("unlock(%#p) of ilock: pc %#p, held by %#p\n",
l, getcallerpc(&l), l->pc);
if(l->p != up){
print("unlock(%#p): up changed: pc %#p, acquired at pc %#p, lock p %#p, unlock up %#p\n",
l, getcallerpc(&l), l->pc, l->p, up);
dumpaproc(l->p);
dumpaproc(up);
}
l->m = nil;
coherence();
l->key = 0;
if(up && --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();
}
}