rwsem.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /* rwsem.c: R/W semaphores: contention handling functions
  2. *
  3. * Written by David Howells (dhowells@redhat.com).
  4. * Derived from arch/i386/kernel/semaphore.c
  5. *
  6. * Writer lock-stealing by Alex Shi <alex.shi@intel.com>
  7. * and Michel Lespinasse <walken@google.com>
  8. */
  9. #include <linux/rwsem.h>
  10. #include <linux/sched.h>
  11. #include <linux/init.h>
  12. #include <linux/export.h>
  13. /*
  14. * Initialize an rwsem:
  15. */
  16. void __init_rwsem(struct rw_semaphore *sem, const char *name,
  17. struct lock_class_key *key)
  18. {
  19. #ifdef CONFIG_DEBUG_LOCK_ALLOC
  20. /*
  21. * Make sure we are not reinitializing a held semaphore:
  22. */
  23. debug_check_no_locks_freed((void *)sem, sizeof(*sem));
  24. lockdep_init_map(&sem->dep_map, name, key, 0);
  25. #endif
  26. sem->count = RWSEM_UNLOCKED_VALUE;
  27. raw_spin_lock_init(&sem->wait_lock);
  28. INIT_LIST_HEAD(&sem->wait_list);
  29. }
  30. EXPORT_SYMBOL(__init_rwsem);
  31. enum rwsem_waiter_type {
  32. RWSEM_WAITING_FOR_WRITE,
  33. RWSEM_WAITING_FOR_READ
  34. };
  35. struct rwsem_waiter {
  36. struct list_head list;
  37. struct task_struct *task;
  38. enum rwsem_waiter_type type;
  39. };
  40. enum rwsem_wake_type {
  41. RWSEM_WAKE_ANY, /* Wake whatever's at head of wait list */
  42. RWSEM_WAKE_READERS, /* Wake readers only */
  43. RWSEM_WAKE_READ_OWNED /* Waker thread holds the read lock */
  44. };
  45. /*
  46. * handle the lock release when processes blocked on it that can now run
  47. * - if we come here from up_xxxx(), then:
  48. * - the 'active part' of count (&0x0000ffff) reached 0 (but may have changed)
  49. * - the 'waiting part' of count (&0xffff0000) is -ve (and will still be so)
  50. * - there must be someone on the queue
  51. * - the spinlock must be held by the caller
  52. * - woken process blocks are discarded from the list after having task zeroed
  53. * - writers are only woken if downgrading is false
  54. */
  55. static struct rw_semaphore *
  56. __rwsem_do_wake(struct rw_semaphore *sem, enum rwsem_wake_type wake_type)
  57. {
  58. struct rwsem_waiter *waiter;
  59. struct task_struct *tsk;
  60. struct list_head *next;
  61. long oldcount, woken, loop, adjustment;
  62. waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
  63. if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
  64. if (wake_type == RWSEM_WAKE_ANY)
  65. /* Wake writer at the front of the queue, but do not
  66. * grant it the lock yet as we want other writers
  67. * to be able to steal it. Readers, on the other hand,
  68. * will block as they will notice the queued writer.
  69. */
  70. wake_up_process(waiter->task);
  71. goto out;
  72. }
  73. /* Writers might steal the lock before we grant it to the next reader.
  74. * We prefer to do the first reader grant before counting readers
  75. * so we can bail out early if a writer stole the lock.
  76. */
  77. adjustment = 0;
  78. if (wake_type != RWSEM_WAKE_READ_OWNED) {
  79. adjustment = RWSEM_ACTIVE_READ_BIAS;
  80. try_reader_grant:
  81. oldcount = rwsem_atomic_update(adjustment, sem) - adjustment;
  82. if (unlikely(oldcount < RWSEM_WAITING_BIAS)) {
  83. /* A writer stole the lock. Undo our reader grant. */
  84. if (rwsem_atomic_update(-adjustment, sem) &
  85. RWSEM_ACTIVE_MASK)
  86. goto out;
  87. /* Last active locker left. Retry waking readers. */
  88. goto try_reader_grant;
  89. }
  90. }
  91. /* Grant an infinite number of read locks to the readers at the front
  92. * of the queue. Note we increment the 'active part' of the count by
  93. * the number of readers before waking any processes up.
  94. */
  95. woken = 0;
  96. do {
  97. woken++;
  98. if (waiter->list.next == &sem->wait_list)
  99. break;
  100. waiter = list_entry(waiter->list.next,
  101. struct rwsem_waiter, list);
  102. } while (waiter->type != RWSEM_WAITING_FOR_WRITE);
  103. adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
  104. if (waiter->type != RWSEM_WAITING_FOR_WRITE)
  105. /* hit end of list above */
  106. adjustment -= RWSEM_WAITING_BIAS;
  107. if (adjustment)
  108. rwsem_atomic_add(adjustment, sem);
  109. next = sem->wait_list.next;
  110. loop = woken;
  111. do {
  112. waiter = list_entry(next, struct rwsem_waiter, list);
  113. next = waiter->list.next;
  114. tsk = waiter->task;
  115. smp_mb();
  116. waiter->task = NULL;
  117. wake_up_process(tsk);
  118. put_task_struct(tsk);
  119. } while (--loop);
  120. sem->wait_list.next = next;
  121. next->prev = &sem->wait_list;
  122. out:
  123. return sem;
  124. }
  125. /*
  126. * wait for the read lock to be granted
  127. */
  128. struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
  129. {
  130. long count, adjustment = -RWSEM_ACTIVE_READ_BIAS;
  131. struct rwsem_waiter waiter;
  132. struct task_struct *tsk = current;
  133. /* set up my own style of waitqueue */
  134. waiter.task = tsk;
  135. waiter.type = RWSEM_WAITING_FOR_READ;
  136. get_task_struct(tsk);
  137. raw_spin_lock_irq(&sem->wait_lock);
  138. if (list_empty(&sem->wait_list))
  139. adjustment += RWSEM_WAITING_BIAS;
  140. list_add_tail(&waiter.list, &sem->wait_list);
  141. /* we're now waiting on the lock, but no longer actively locking */
  142. count = rwsem_atomic_update(adjustment, sem);
  143. /* If there are no active locks, wake the front queued process(es).
  144. *
  145. * If there are no writers and we are first in the queue,
  146. * wake our own waiter to join the existing active readers !
  147. */
  148. if (count == RWSEM_WAITING_BIAS ||
  149. (count > RWSEM_WAITING_BIAS &&
  150. adjustment != -RWSEM_ACTIVE_READ_BIAS))
  151. sem = __rwsem_do_wake(sem, RWSEM_WAKE_ANY);
  152. raw_spin_unlock_irq(&sem->wait_lock);
  153. /* wait to be given the lock */
  154. while (true) {
  155. set_task_state(tsk, TASK_UNINTERRUPTIBLE);
  156. if (!waiter.task)
  157. break;
  158. schedule();
  159. }
  160. tsk->state = TASK_RUNNING;
  161. return sem;
  162. }
  163. /*
  164. * wait until we successfully acquire the write lock
  165. */
  166. struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
  167. {
  168. long count, adjustment = -RWSEM_ACTIVE_WRITE_BIAS;
  169. struct rwsem_waiter waiter;
  170. struct task_struct *tsk = current;
  171. /* set up my own style of waitqueue */
  172. waiter.task = tsk;
  173. waiter.type = RWSEM_WAITING_FOR_WRITE;
  174. raw_spin_lock_irq(&sem->wait_lock);
  175. if (list_empty(&sem->wait_list))
  176. adjustment += RWSEM_WAITING_BIAS;
  177. list_add_tail(&waiter.list, &sem->wait_list);
  178. /* we're now waiting on the lock, but no longer actively locking */
  179. count = rwsem_atomic_update(adjustment, sem);
  180. /* If there were already threads queued before us and there are no
  181. * active writers, the lock must be read owned; so we try to wake
  182. * any read locks that were queued ahead of us. */
  183. if (count > RWSEM_WAITING_BIAS &&
  184. adjustment == -RWSEM_ACTIVE_WRITE_BIAS)
  185. sem = __rwsem_do_wake(sem, RWSEM_WAKE_READERS);
  186. /* wait until we successfully acquire the lock */
  187. set_task_state(tsk, TASK_UNINTERRUPTIBLE);
  188. while (true) {
  189. if (!(count & RWSEM_ACTIVE_MASK)) {
  190. /* Try acquiring the write lock. */
  191. count = RWSEM_ACTIVE_WRITE_BIAS;
  192. if (!list_is_singular(&sem->wait_list))
  193. count += RWSEM_WAITING_BIAS;
  194. if (sem->count == RWSEM_WAITING_BIAS &&
  195. cmpxchg(&sem->count, RWSEM_WAITING_BIAS, count) ==
  196. RWSEM_WAITING_BIAS)
  197. break;
  198. }
  199. raw_spin_unlock_irq(&sem->wait_lock);
  200. /* Block until there are no active lockers. */
  201. do {
  202. schedule();
  203. set_task_state(tsk, TASK_UNINTERRUPTIBLE);
  204. } while ((count = sem->count) & RWSEM_ACTIVE_MASK);
  205. raw_spin_lock_irq(&sem->wait_lock);
  206. }
  207. list_del(&waiter.list);
  208. raw_spin_unlock_irq(&sem->wait_lock);
  209. tsk->state = TASK_RUNNING;
  210. return sem;
  211. }
  212. /*
  213. * handle waking up a waiter on the semaphore
  214. * - up_read/up_write has decremented the active part of count if we come here
  215. */
  216. struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
  217. {
  218. unsigned long flags;
  219. raw_spin_lock_irqsave(&sem->wait_lock, flags);
  220. /* do nothing if list empty */
  221. if (!list_empty(&sem->wait_list))
  222. sem = __rwsem_do_wake(sem, RWSEM_WAKE_ANY);
  223. raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
  224. return sem;
  225. }
  226. /*
  227. * downgrade a write lock into a read lock
  228. * - caller incremented waiting part of count and discovered it still negative
  229. * - just wake up any readers at the front of the queue
  230. */
  231. struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
  232. {
  233. unsigned long flags;
  234. raw_spin_lock_irqsave(&sem->wait_lock, flags);
  235. /* do nothing if list empty */
  236. if (!list_empty(&sem->wait_list))
  237. sem = __rwsem_do_wake(sem, RWSEM_WAKE_READ_OWNED);
  238. raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
  239. return sem;
  240. }
  241. EXPORT_SYMBOL(rwsem_down_read_failed);
  242. EXPORT_SYMBOL(rwsem_down_write_failed);
  243. EXPORT_SYMBOL(rwsem_wake);
  244. EXPORT_SYMBOL(rwsem_downgrade_wake);