DESIGN-rwlock.txt 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. Reader Writer Locks pseudocode
  2. ==============================
  3. pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
  4. pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
  5. pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
  6. struct pthread_rwlock_t {
  7. unsigned int lock:
  8. - internal mutex
  9. unsigned int writers_preferred;
  10. - locking mode: 0 recursive, readers preferred
  11. 1 nonrecursive, writers preferred
  12. unsigned int readers;
  13. - number of read-only references various threads have
  14. pthread_t writer;
  15. - descriptor of the writer or 0
  16. unsigned int readers_wakeup;
  17. - 'all readers should wake up' futex.
  18. unsigned int writer_wakeup;
  19. - 'one writer should wake up' futex.
  20. unsigned int nr_readers_queued;
  21. - number of readers queued up.
  22. unsigned int nr_writers_queued;
  23. - number of writers queued up.
  24. }
  25. pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
  26. {
  27. lll_lock(rwlock->lock);
  28. for (;;) {
  29. if (!rwlock->writer && (!rwlock->nr_writers_queued ||
  30. !rwlock->writers_preferred))
  31. break;
  32. rwlock->nr_readers_queued++;
  33. val = rwlock->readers_wakeup;
  34. lll_unlock(rwlock->lock);
  35. futex_wait(&rwlock->readers_wakeup, val)
  36. lll_lock(rwlock->lock);
  37. rwlock->nr_readers_queued--;
  38. }
  39. rwlock->readers++;
  40. lll_unlock(rwlock->lock);
  41. }
  42. pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
  43. {
  44. int result = EBUSY;
  45. lll_lock(rwlock->lock);
  46. if (!rwlock->writer && (!rwlock->nr_writers_queued ||
  47. !rwlock->writers_preferred))
  48. rwlock->readers++;
  49. lll_unlock(rwlock->lock);
  50. return result;
  51. }
  52. pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
  53. {
  54. lll_lock(rwlock->lock);
  55. for (;;) {
  56. if (!rwlock->writer && !rwlock->readers)
  57. break;
  58. rwlock->nr_writers_queued++;
  59. val = rwlock->writer_wakeup;
  60. lll_unlock(rwlock->lock);
  61. futex_wait(&rwlock->writer_wakeup, val);
  62. lll_lock(rwlock->lock);
  63. rwlock->nr_writers_queued--;
  64. }
  65. rwlock->writer = pthread_self();
  66. lll_unlock(rwlock->lock);
  67. }
  68. pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
  69. {
  70. lll_lock(rwlock->lock);
  71. if (rwlock->writer)
  72. rwlock->writer = 0;
  73. else
  74. rwlock->readers--;
  75. if (!rwlock->readers) {
  76. if (rwlock->nr_writers_queued) {
  77. ++rwlock->writer_wakeup;
  78. lll_unlock(rwlock->lock);
  79. futex_wake(&rwlock->writer_wakeup, 1);
  80. return;
  81. } else
  82. if (rwlock->nr_readers_queued) {
  83. ++rwlock->readers_wakeup;
  84. lll_unlock(rwlock->lock);
  85. futex_wake(&rwlock->readers_wakeup, MAX_INT);
  86. return;
  87. }
  88. }
  89. lll_unlock(rwlock->lock);
  90. }