rwlock.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * StarPU
  3. * Copyright (C) Université Bordeaux 1, CNRS 2008-2010 (see AUTHORS file)
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. /**
  17. * A dummy implementation of a rw_lock using spinlocks ...
  18. */
  19. #include "rwlock.h"
  20. static void _take_busy_lock(starpu_rw_lock_t *lock)
  21. {
  22. uint32_t prev;
  23. do {
  24. prev = STARPU_TEST_AND_SET(&lock->busy, 1);
  25. } while (prev);
  26. }
  27. static void _release_busy_lock(starpu_rw_lock_t *lock)
  28. {
  29. STARPU_RELEASE(&lock->busy);
  30. }
  31. void _starpu_init_rw_lock(starpu_rw_lock_t *lock)
  32. {
  33. STARPU_ASSERT(lock);
  34. lock->writer = 0;
  35. lock->readercnt = 0;
  36. lock->busy = 0;
  37. }
  38. int _starpu_take_rw_lock_write_try(starpu_rw_lock_t *lock)
  39. {
  40. _take_busy_lock(lock);
  41. if (lock->readercnt > 0 || lock->writer)
  42. {
  43. /* fail to take the lock */
  44. _release_busy_lock(lock);
  45. return -1;
  46. }
  47. else {
  48. STARPU_ASSERT(lock->readercnt == 0);
  49. STARPU_ASSERT(lock->writer == 0);
  50. /* no one was either writing nor reading */
  51. lock->writer = 1;
  52. _release_busy_lock(lock);
  53. return 0;
  54. }
  55. }
  56. int _starpu_take_rw_lock_read_try(starpu_rw_lock_t *lock)
  57. {
  58. _take_busy_lock(lock);
  59. if (lock->writer)
  60. {
  61. /* there is a writer ... */
  62. _release_busy_lock(lock);
  63. return -1;
  64. }
  65. else {
  66. STARPU_ASSERT(lock->writer == 0);
  67. /* no one is writing */
  68. /* XXX check wrap arounds ... */
  69. lock->readercnt++;
  70. _release_busy_lock(lock);
  71. return 0;
  72. }
  73. }
  74. void _starpu_take_rw_lock_write(starpu_rw_lock_t *lock)
  75. {
  76. do {
  77. _take_busy_lock(lock);
  78. if (lock->readercnt > 0 || lock->writer)
  79. {
  80. /* fail to take the lock */
  81. _release_busy_lock(lock);
  82. }
  83. else {
  84. STARPU_ASSERT(lock->readercnt == 0);
  85. STARPU_ASSERT(lock->writer == 0);
  86. /* no one was either writing nor reading */
  87. lock->writer = 1;
  88. _release_busy_lock(lock);
  89. return;
  90. }
  91. } while (1);
  92. }
  93. void _starpu_take_rw_lock_read(starpu_rw_lock_t *lock)
  94. {
  95. do {
  96. _take_busy_lock(lock);
  97. if (lock->writer)
  98. {
  99. /* there is a writer ... */
  100. _release_busy_lock(lock);
  101. }
  102. else {
  103. STARPU_ASSERT(lock->writer == 0);
  104. /* no one is writing */
  105. /* XXX check wrap arounds ... */
  106. lock->readercnt++;
  107. _release_busy_lock(lock);
  108. return;
  109. }
  110. } while (1);
  111. }
  112. void _starpu_release_rw_lock(starpu_rw_lock_t *lock)
  113. {
  114. _take_busy_lock(lock);
  115. /* either writer or reader (exactly one !) */
  116. if (lock->writer)
  117. {
  118. STARPU_ASSERT(lock->readercnt == 0);
  119. lock->writer = 0;
  120. }
  121. else {
  122. /* reading mode */
  123. STARPU_ASSERT(lock->writer == 0);
  124. lock->readercnt--;
  125. }
  126. _release_busy_lock(lock);
  127. }