lock.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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 <u.h>
  10. #include <libc.h>
  11. #ifdef PTHREAD
  12. static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
  13. static void
  14. lockinit(Lock *lk)
  15. {
  16. pthread_mutexattr_t attr;
  17. pthread_mutex_lock(&initmutex);
  18. if(lk->init == 0){
  19. pthread_mutexattr_init(&attr);
  20. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
  21. pthread_mutex_init(&lk->mutex, &attr);
  22. pthread_mutexattr_destroy(&attr);
  23. lk->init = 1;
  24. }
  25. pthread_mutex_unlock(&initmutex);
  26. }
  27. void
  28. lock(Lock *lk)
  29. {
  30. if(!lk->init)
  31. lockinit(lk);
  32. if(pthread_mutex_lock(&lk->mutex) != 0)
  33. abort();
  34. }
  35. int
  36. canlock(Lock *lk)
  37. {
  38. int r;
  39. if(!lk->init)
  40. lockinit(lk);
  41. r = pthread_mutex_trylock(&lk->mutex);
  42. if(r == 0)
  43. return 1;
  44. if(r == EBUSY)
  45. return 0;
  46. abort();
  47. }
  48. void
  49. unlock(Lock *lk)
  50. {
  51. if(pthread_mutex_unlock(&lk->mutex) != 0)
  52. abort();
  53. }
  54. #else
  55. /* old, non-pthread systems */
  56. int
  57. canlock(Lock *lk)
  58. {
  59. return !tas(&lk->key);
  60. }
  61. void
  62. lock(Lock *lk)
  63. {
  64. int i;
  65. /* easy case */
  66. if(canlock(lk))
  67. return;
  68. /* for multi processor machines */
  69. for(i=0; i<100; i++)
  70. if(canlock(lk))
  71. return;
  72. for(i=0; i<100; i++) {
  73. osyield();
  74. if(canlock(lk))
  75. return;
  76. }
  77. /* looking bad - make sure it is not a priority problem */
  78. for(i=0; i<12; i++) {
  79. osmsleep(1<<i);
  80. if(canlock(lk))
  81. return;
  82. }
  83. /* we are in trouble */
  84. for(;;) {
  85. if(canlock(lk))
  86. return;
  87. iprint("lock loop %ld: val=%d &lock=%ux pc=%p\n", getpid(), lk->key, lk, getcallerpc());
  88. osmsleep(1000);
  89. }
  90. }
  91. void
  92. unlock(Lock *lk)
  93. {
  94. assert(lk->key);
  95. lk->key = 0;
  96. }
  97. #endif
  98. void
  99. ilock(Lock *lk)
  100. {
  101. lock(lk);
  102. }
  103. void
  104. iunlock(Lock *lk)
  105. {
  106. unlock(lk);
  107. }