spinlock.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*****************************************************************
  2. * spinlock.c
  3. * adapted from MIT xv6 by Zhiyi Huang, [email protected]
  4. * University of Otago
  5. *
  6. ********************************************************************/
  7. #include "types.h"
  8. #include "defs.h"
  9. #include "param.h"
  10. #include "arm.h"
  11. #include "memlayout.h"
  12. #include "mmu.h"
  13. #include "proc.h"
  14. #include "spinlock.h"
  15. void
  16. initlock(struct spinlock *lk, char *name)
  17. {
  18. lk->name = name;
  19. lk->locked = 0;
  20. lk->cpu = 0;
  21. }
  22. // Acquire the lock.
  23. // Loops (spins) until the lock is acquired.
  24. // Holding a lock for a long time may cause
  25. // other CPUs to waste time spinning to acquire it.
  26. void
  27. acquire(struct spinlock *lk)
  28. {
  29. pushcli(); // disable interrupts to avoid deadlock.
  30. if(holding(lk)){
  31. cprintf("lock name: %s, locked: %d, cpu: %x CPSR: %x\n", lk->name, lk->locked, lk->cpu, readcpsr());
  32. panic("acquire");
  33. }
  34. lk->locked = 1;
  35. // Record info about lock acquisition for debugging.
  36. lk->cpu = curr_cpu;
  37. }
  38. // Release the lock.
  39. void
  40. release(struct spinlock *lk)
  41. {
  42. if(!holding(lk))
  43. panic("release");
  44. lk->pcs[0] = 0;
  45. lk->cpu = 0;
  46. lk->locked = 0;
  47. popcli();
  48. }
  49. // Record the current call stack in pcs[] by following the %ebp chain.
  50. void
  51. getcallerpcs(void *v, uint pcs[])
  52. {
  53. }
  54. // Check whether this cpu is holding the lock.
  55. int
  56. holding(struct spinlock *lock)
  57. {
  58. int rv;
  59. rv = lock->locked && lock->cpu == curr_cpu;
  60. /* if(rv){
  61. cprintf("The held lock: %s, locked: %d, cpu: %x\n", lock->name, lock->locked, lock->cpu);
  62. }*/
  63. return rv;
  64. }
  65. // Pushcli/popcli are like cli/sti except that they are matched:
  66. // it takes two popcli to undo two pushcli. Also, if interrupts
  67. // are off, then pushcli, popcli leaves them off.
  68. void
  69. pushcli(void)
  70. {
  71. uint cpsr;
  72. cpsr = readcpsr();
  73. cli();
  74. if(curr_cpu->ncli++ == 0)
  75. curr_cpu->intena = (cpsr & PSR_DISABLE_IRQ) ? 0: 1;
  76. }
  77. void
  78. popcli(void)
  79. {
  80. if(!(readcpsr()&PSR_DISABLE_IRQ))
  81. panic("popcli - interruptible");
  82. if(--curr_cpu->ncli < 0)
  83. panic("popcli");
  84. if(curr_cpu->ncli == 0 && curr_cpu->intena)
  85. sti();
  86. }