xref: /xv6-public/spinlock.c (revision 5be0039c)
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.
1132630628Srtm //#define cprintf dont_use_cprintf
1221a88fd4Skaashoek 
13*5be0039cSrtm #define LOCKMAGIC 0x6673ffea
14*5be0039cSrtm 
15b74f4b57Srsc extern int use_console_lock;
168148b6eeSrtm 
170e84a0ecSrtm void
18*5be0039cSrtm initlock(struct spinlock *lock, char *name)
19*5be0039cSrtm {
20*5be0039cSrtm   lock->magic = LOCKMAGIC;
21*5be0039cSrtm   lock->name = name;
22*5be0039cSrtm   lock->locked = 0;
23*5be0039cSrtm   lock->cpu = 0xffffffff;
24*5be0039cSrtm }
25*5be0039cSrtm 
26*5be0039cSrtm void
270e84a0ecSrtm getcallerpcs(void *v, uint pcs[])
2865bd8e13Srsc {
290e84a0ecSrtm   uint *ebp = (uint*)v - 2;
300e84a0ecSrtm   int i;
310e84a0ecSrtm   for(i = 0; i < 10 && ebp && ebp != (uint*)0xffffffff; ebp = (uint*)*ebp, i++){
320e84a0ecSrtm     pcs[i] = *(ebp + 1);
330e84a0ecSrtm   }
340e84a0ecSrtm   for( ; i < 10; i++)
350e84a0ecSrtm     pcs[i] = 0;
365ce9751cSrsc }
375ce9751cSrsc 
3821a88fd4Skaashoek void
39679a977cSrsc acquire(struct spinlock * lock)
4021a88fd4Skaashoek {
41*5be0039cSrtm   if(lock->magic != LOCKMAGIC)
42*5be0039cSrtm     panic("weird lock magic");
430e84a0ecSrtm   if(holding(lock))
440dd42537Srsc     panic("acquire");
450dd42537Srsc 
468a8be1b8Srtm   if(cpus[cpu()].nlock == 0)
47b548df15Srtm     cli();
488a8be1b8Srtm   cpus[cpu()].nlock++;
498a8be1b8Srtm 
5065bd8e13Srsc 	while(cmpxchg(0, 1, &lock->locked) == 1)
5165bd8e13Srsc 		;
5265bd8e13Srsc 	cpuid(0, 0, 0, 0, 0);	// memory barrier
530e84a0ecSrtm 	getcallerpcs(&lock, lock->pcs);
540e84a0ecSrtm 	lock->cpu = cpu() + 10;
5532630628Srtm         cpus[cpu()].lastacquire = lock;
5621a88fd4Skaashoek }
5721a88fd4Skaashoek 
5821a88fd4Skaashoek void
59679a977cSrsc release(struct spinlock * lock)
6021a88fd4Skaashoek {
61*5be0039cSrtm   if(lock->magic != LOCKMAGIC)
62*5be0039cSrtm     panic("weird lock magic");
63*5be0039cSrtm 
640dd42537Srsc 	if(!holding(lock))
650dd42537Srsc 		panic("release");
660dd42537Srsc 
6732630628Srtm         cpus[cpu()].lastrelease = lock;
680e84a0ecSrtm         lock->pcs[0] = 0;
690e84a0ecSrtm         lock->cpu = 0xffffffff;
7065bd8e13Srsc 	cpuid(0, 0, 0, 0, 0);	// memory barrier
7165bd8e13Srsc 	lock->locked = 0;
72b74f4b57Srsc 	if(--cpus[cpu()].nlock == 0)
73b548df15Srtm 		sti();
7421a88fd4Skaashoek }
7546bbd72fSrtm 
760dd42537Srsc int
770dd42537Srsc holding(struct spinlock *lock)
780dd42537Srsc {
790e84a0ecSrtm 	return lock->locked && lock->cpu == cpu() + 10;
800dd42537Srsc }
81