xref: /xv6-public/spinlock.c (revision 0dd42537)
121a88fd4Skaashoek #include "types.h"
221a88fd4Skaashoek #include "defs.h"
321a88fd4Skaashoek #include "x86.h"
47837c71bSkaashoek #include "mmu.h"
54e8f237bSrtm #include "param.h"
64e8f237bSrtm #include "proc.h"
74e8f237bSrtm #include "spinlock.h"
821a88fd4Skaashoek 
965bd8e13Srsc // Can't call cprintf from inside these routines,
1065bd8e13Srsc // because cprintf uses them itself.
1165bd8e13Srsc #define cprintf dont_use_cprintf
1221a88fd4Skaashoek 
13b74f4b57Srsc extern int use_console_lock;
148148b6eeSrtm 
1565bd8e13Srsc int
1665bd8e13Srsc getcallerpc(void *v)
1765bd8e13Srsc {
185ce9751cSrsc 	return ((int*)v)[-1];
195ce9751cSrsc }
205ce9751cSrsc 
2121a88fd4Skaashoek void
22679a977cSrsc acquire(struct spinlock * lock)
2321a88fd4Skaashoek {
24*0dd42537Srsc 	if(holding(lock))
25*0dd42537Srsc 		panic("acquire");
26*0dd42537Srsc 
2765bd8e13Srsc 	if(cpus[cpu()].nlock++ == 0)
28b548df15Srtm 		cli();
2965bd8e13Srsc 	while(cmpxchg(0, 1, &lock->locked) == 1)
3065bd8e13Srsc 		;
3165bd8e13Srsc 	cpuid(0, 0, 0, 0, 0);	// memory barrier
32*0dd42537Srsc 	lock->pc = getcallerpc(&lock);
33*0dd42537Srsc 	lock->cpu = cpu();
3421a88fd4Skaashoek }
3521a88fd4Skaashoek 
3621a88fd4Skaashoek void
37679a977cSrsc release(struct spinlock * lock)
3821a88fd4Skaashoek {
39*0dd42537Srsc 	if(!holding(lock))
40*0dd42537Srsc 		panic("release");
41*0dd42537Srsc 
4265bd8e13Srsc 	cpuid(0, 0, 0, 0, 0);	// memory barrier
4365bd8e13Srsc 	lock->locked = 0;
44b74f4b57Srsc 	if(--cpus[cpu()].nlock == 0)
45b548df15Srtm 		sti();
4621a88fd4Skaashoek }
4746bbd72fSrtm 
48*0dd42537Srsc int
49*0dd42537Srsc holding(struct spinlock *lock)
50*0dd42537Srsc {
51*0dd42537Srsc 	return lock->locked && lock->cpu == cpu();
52*0dd42537Srsc }
53