|
69 | 69 |
|
70 | 70 | #include "locking/rtmutex_common.h"
|
71 | 71 |
|
| 72 | +/* |
| 73 | + * Basic futex operation and ordering guarantees: |
| 74 | + * |
| 75 | + * The waiter reads the futex value in user space and calls |
| 76 | + * futex_wait(). This function computes the hash bucket and acquires |
| 77 | + * the hash bucket lock. After that it reads the futex user space value |
| 78 | + * again and verifies that the data has not changed. If it has not |
| 79 | + * changed it enqueues itself into the hash bucket, releases the hash |
| 80 | + * bucket lock and schedules. |
| 81 | + * |
| 82 | + * The waker side modifies the user space value of the futex and calls |
| 83 | + * futex_wake(). This functions computes the hash bucket and acquires |
| 84 | + * the hash bucket lock. Then it looks for waiters on that futex in the |
| 85 | + * hash bucket and wakes them. |
| 86 | + * |
| 87 | + * Note that the spin_lock serializes waiters and wakers, so that the |
| 88 | + * following scenario is avoided: |
| 89 | + * |
| 90 | + * CPU 0 CPU 1 |
| 91 | + * val = *futex; |
| 92 | + * sys_futex(WAIT, futex, val); |
| 93 | + * futex_wait(futex, val); |
| 94 | + * uval = *futex; |
| 95 | + * *futex = newval; |
| 96 | + * sys_futex(WAKE, futex); |
| 97 | + * futex_wake(futex); |
| 98 | + * if (queue_empty()) |
| 99 | + * return; |
| 100 | + * if (uval == val) |
| 101 | + * lock(hash_bucket(futex)); |
| 102 | + * queue(); |
| 103 | + * unlock(hash_bucket(futex)); |
| 104 | + * schedule(); |
| 105 | + * |
| 106 | + * This would cause the waiter on CPU 0 to wait forever because it |
| 107 | + * missed the transition of the user space value from val to newval |
| 108 | + * and the waker did not find the waiter in the hash bucket queue. |
| 109 | + * The spinlock serializes that: |
| 110 | + * |
| 111 | + * CPU 0 CPU 1 |
| 112 | + * val = *futex; |
| 113 | + * sys_futex(WAIT, futex, val); |
| 114 | + * futex_wait(futex, val); |
| 115 | + * lock(hash_bucket(futex)); |
| 116 | + * uval = *futex; |
| 117 | + * *futex = newval; |
| 118 | + * sys_futex(WAKE, futex); |
| 119 | + * futex_wake(futex); |
| 120 | + * lock(hash_bucket(futex)); |
| 121 | + * if (uval == val) |
| 122 | + * queue(); |
| 123 | + * unlock(hash_bucket(futex)); |
| 124 | + * schedule(); if (!queue_empty()) |
| 125 | + * wake_waiters(futex); |
| 126 | + * unlock(hash_bucket(futex)); |
| 127 | + */ |
| 128 | + |
72 | 129 | int __read_mostly futex_cmpxchg_enabled;
|
73 | 130 |
|
74 | 131 | /*
|
|
0 commit comments