⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spinlock.c

📁 美国mit操作系统课程所用的一个教学操作系统xv6
💻 C
字号:
// Mutual exclusion spin locks.#include "types.h"#include "defs.h"#include "param.h"#include "x86.h"#include "mmu.h"#include "proc.h"#include "spinlock.h"extern int use_console_lock;voidinitlock(struct spinlock *lock, char *name){  lock->name = name;  lock->locked = 0;  lock->cpu = 0xffffffff;}// Acquire the lock.// Loops (spins) until the lock is acquired.// Holding a lock for a long time may cause// other CPUs to waste time spinning to acquire it.voidacquire(struct spinlock *lock){  pushcli();  if(holding(lock))    panic("acquire");  // The xchg is atomic.  // It also serializes, so that reads after acquire are not  // reordered before it.    while(xchg(&lock->locked, 1) == 1)    ;  // Record info about lock acquisition for debugging.  // The +10 is only so that we can tell the difference  // between forgetting to initialize lock->cpu  // and holding a lock on cpu 0.  lock->cpu = cpu() + 10;  getcallerpcs(&lock, lock->pcs);}// Release the lock.voidrelease(struct spinlock *lock){  if(!holding(lock))    panic("release");  lock->pcs[0] = 0;  lock->cpu = 0xffffffff;  // The xchg serializes, so that reads before release are   // not reordered after it.  (This reordering would be allowed  // by the Intel manuals, but does not happen on current   // Intel processors.  The xchg being asm volatile also keeps  // gcc from delaying the above assignments.)  xchg(&lock->locked, 0);  popcli();}// Record the current call stack in pcs[] by following the %ebp chain.voidgetcallerpcs(void *v, uint pcs[]){  uint *ebp;  int i;    ebp = (uint*)v - 2;  for(i = 0; i < 10; i++){    if(ebp == 0 || ebp == (uint*)0xffffffff)      break;    pcs[i] = ebp[1];     // saved %eip    ebp = (uint*)ebp[0]; // saved %ebp  }  for(; i < 10; i++)    pcs[i] = 0;}// Check whether this cpu is holding the lock.intholding(struct spinlock *lock){  return lock->locked && lock->cpu == cpu() + 10;}// Pushcli/popcli are like cli/sti except that they are matched:// it takes two popcli to undo two pushcli.  Also, if interrupts// are off, then pushcli, popcli leaves them off.voidpushcli(void){  int eflags;    eflags = read_eflags();  cli();  if(cpus[cpu()].ncli++ == 0)    cpus[cpu()].intena = eflags & FL_IF;}voidpopcli(void){  if(read_eflags()&FL_IF)    panic("popcli - interruptible");  if(--cpus[cpu()].ncli < 0)    panic("popcli");  if(cpus[cpu()].ncli == 0 && cpus[cpu()].intena)    sti();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -