8148b6ee53
nesting cli/sti: release shouldn't always enable interrupts separate setup of lapic from starting of other cpus, so cpu() works earlier flag to disable locking in console output make locks work even when curproc==0 (still crashes in clock interrupt)
65 lines
1.2 KiB
C
65 lines
1.2 KiB
C
#include "types.h"
|
|
#include "defs.h"
|
|
#include "x86.h"
|
|
#include "mmu.h"
|
|
#include "param.h"
|
|
#include "proc.h"
|
|
#include "spinlock.h"
|
|
|
|
#define DEBUG 0
|
|
|
|
extern use_printf_lock;
|
|
|
|
int getcallerpc(void *v) {
|
|
return ((int*)v)[-1];
|
|
}
|
|
|
|
void
|
|
acquire(struct spinlock * lock)
|
|
{
|
|
unsigned who;
|
|
|
|
if(curproc[cpu()])
|
|
who = (unsigned) curproc[cpu()];
|
|
else
|
|
who = cpu() + 1;
|
|
|
|
if(DEBUG) cprintf("cpu%d: acquiring at %x\n", cpu(), getcallerpc(&lock));
|
|
|
|
if (lock->who == who && lock->locked){
|
|
lock->count += 1;
|
|
} else {
|
|
cli();
|
|
// if we get the lock, eax will be zero
|
|
// if we don't get the lock, eax will be one
|
|
while ( cmpxchg(0, 1, &lock->locked) == 1 ) { ; }
|
|
lock->locker_pc = getcallerpc(&lock);
|
|
lock->count = 1;
|
|
lock->who = who;
|
|
}
|
|
|
|
if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
|
|
}
|
|
|
|
void
|
|
release(struct spinlock * lock)
|
|
{
|
|
unsigned who;
|
|
|
|
if(curproc[cpu()])
|
|
who = (unsigned) curproc[cpu()];
|
|
else
|
|
who = cpu() + 1;
|
|
|
|
if(DEBUG) cprintf ("cpu%d: releasing at %x\n", cpu(), getcallerpc(&lock));
|
|
|
|
if(lock->who != who || lock->count < 1 || lock->locked != 1)
|
|
panic("release");
|
|
|
|
lock->count -= 1;
|
|
if(lock->count < 1){
|
|
lock->who = 0;
|
|
cmpxchg(1, 0, &lock->locked);
|
|
sti();
|
|
}
|
|
}
|