xref: /xv6-public/spinlock.c (revision 4e8f237b)
121a88fd4Skaashoek #include "types.h"
221a88fd4Skaashoek #include "defs.h"
321a88fd4Skaashoek #include "x86.h"
47837c71bSkaashoek #include "mmu.h"
5*4e8f237bSrtm #include "param.h"
6*4e8f237bSrtm #include "proc.h"
7*4e8f237bSrtm #include "spinlock.h"
821a88fd4Skaashoek 
95ce9751cSrsc #define DEBUG 0
1021a88fd4Skaashoek 
115ce9751cSrsc int getcallerpc(void *v) {
125ce9751cSrsc   return ((int*)v)[-1];
135ce9751cSrsc }
145ce9751cSrsc 
1521a88fd4Skaashoek void
16*4e8f237bSrtm acquire(struct spinlock * lock)
1721a88fd4Skaashoek {
18*4e8f237bSrtm   struct proc * cp = curproc[cpu()];
1921a88fd4Skaashoek 
205ce9751cSrsc   // on a real machine there would be a memory barrier here
21*4e8f237bSrtm   if(DEBUG) cprintf("cpu%d: acquiring at %x\n", cpu(), getcallerpc(&lock));
22*4e8f237bSrtm   if (cp && lock->p == cp && lock->locked){
23*4e8f237bSrtm     lock->count += 1;
24*4e8f237bSrtm   } else {
25b548df15Srtm     cli();
26*4e8f237bSrtm     while ( cmpxchg(0, 1, &lock->locked) != 1 ) { ; }
27*4e8f237bSrtm     lock->locker_pc = getcallerpc(&lock);
28*4e8f237bSrtm     lock->count = 1;
29*4e8f237bSrtm     lock->p = cp;
30*4e8f237bSrtm   }
31*4e8f237bSrtm   if(DEBUG) cprintf("cpu%d: acquired at %x\n", cpu(), getcallerpc(&lock));
3221a88fd4Skaashoek }
3321a88fd4Skaashoek 
3421a88fd4Skaashoek void
35*4e8f237bSrtm release(struct spinlock * lock)
3621a88fd4Skaashoek {
37*4e8f237bSrtm   struct proc * cp = curproc[cpu()];
38*4e8f237bSrtm 
39*4e8f237bSrtm   if(DEBUG) cprintf ("cpu%d: releasing at %x\n", cpu(), getcallerpc(&lock));
40*4e8f237bSrtm 
41*4e8f237bSrtm   if(lock->p != cp || lock->count < 1 || lock->locked != 1)
42*4e8f237bSrtm     panic("release");
43*4e8f237bSrtm 
44*4e8f237bSrtm   lock->count -= 1;
45*4e8f237bSrtm   if(lock->count < 1){
46*4e8f237bSrtm     lock->p = 0;
47*4e8f237bSrtm     cmpxchg(1, 0, &lock->locked);
48b548df15Srtm     sti();
49*4e8f237bSrtm     // on a real machine there would be a memory barrier here
5021a88fd4Skaashoek   }
5121a88fd4Skaashoek }
52