9excl.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "stdinc.h"
  10. #include "9.h"
  11. static struct {
  12. VtLock* lock;
  13. Excl* head;
  14. Excl* tail;
  15. } ebox;
  16. struct Excl {
  17. Fsys* fsys;
  18. uint64_t path;
  19. uint32_t time;
  20. Excl* next;
  21. Excl* prev;
  22. };
  23. enum {
  24. LifeTime = (5*60),
  25. };
  26. int
  27. exclAlloc(Fid* fid)
  28. {
  29. uint32_t t;
  30. Excl *excl;
  31. assert(fid->excl == nil);
  32. t = time(0L);
  33. vtLock(ebox.lock);
  34. for(excl = ebox.head; excl != nil; excl = excl->next){
  35. if(excl->fsys != fid->fsys || excl->path != fid->qid.path)
  36. continue;
  37. /*
  38. * Found it.
  39. * Now, check if it's timed out.
  40. * If not, return error, it's locked.
  41. * If it has timed out, zap the old
  42. * one and continue on to allocate a
  43. * a new one.
  44. */
  45. if(excl->time >= t){
  46. vtUnlock(ebox.lock);
  47. vtSetError("exclusive lock");
  48. return 0;
  49. }
  50. excl->fsys = nil;
  51. }
  52. /*
  53. * Not found or timed-out.
  54. * Alloc a new one and initialise.
  55. */
  56. excl = vtMemAllocZ(sizeof(Excl));
  57. excl->fsys = fid->fsys;
  58. excl->path = fid->qid.path;
  59. excl->time = t+LifeTime;
  60. if(ebox.tail != nil){
  61. excl->prev = ebox.tail;
  62. ebox.tail->next = excl;
  63. }
  64. else{
  65. ebox.head = excl;
  66. excl->prev = nil;
  67. }
  68. ebox.tail = excl;
  69. excl->next = nil;
  70. vtUnlock(ebox.lock);
  71. fid->excl = excl;
  72. return 1;
  73. }
  74. int
  75. exclUpdate(Fid* fid)
  76. {
  77. uint32_t t;
  78. Excl *excl;
  79. excl = fid->excl;
  80. t = time(0L);
  81. vtLock(ebox.lock);
  82. if(excl->time < t || excl->fsys != fid->fsys){
  83. vtUnlock(ebox.lock);
  84. vtSetError("exclusive lock broken");
  85. return 0;
  86. }
  87. excl->time = t+LifeTime;
  88. vtUnlock(ebox.lock);
  89. return 1;
  90. }
  91. void
  92. exclFree(Fid* fid)
  93. {
  94. Excl *excl;
  95. if((excl = fid->excl) == nil)
  96. return;
  97. fid->excl = nil;
  98. vtLock(ebox.lock);
  99. if(excl->prev != nil)
  100. excl->prev->next = excl->next;
  101. else
  102. ebox.head = excl->next;
  103. if(excl->next != nil)
  104. excl->next->prev = excl->prev;
  105. else
  106. ebox.tail = excl->prev;
  107. vtUnlock(ebox.lock);
  108. vtMemFree(excl);
  109. }
  110. void
  111. exclInit(void)
  112. {
  113. ebox.lock = vtLockAlloc();
  114. }