Changes in kernel/generic/src/synch/futex.c [a49a1a1:4774a32] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/synch/futex.c
ra49a1a1 r4774a32 37 37 38 38 #include <synch/futex.h> 39 #include <synch/ mutex.h>39 #include <synch/rwlock.h> 40 40 #include <synch/spinlock.h> 41 41 #include <synch/synch.h> … … 65 65 66 66 /** 67 * Mutexprotecting global futex hash table.67 * Read-write lock protecting global futex hash table. 68 68 * It is also used to serialize access to all futex_t structures. 69 69 * Must be acquired before the task futex B+tree lock. 70 70 */ 71 static mutex_t futex_ht_lock;71 static rwlock_t futex_ht_lock; 72 72 73 73 /** Futex hash table. */ … … 84 84 void futex_init(void) 85 85 { 86 mutex_initialize(&futex_ht_lock, MUTEX_PASSIVE);86 rwlock_initialize(&futex_ht_lock); 87 87 hash_table_create(&futex_ht, FUTEX_HT_SIZE, 1, &futex_ht_ops); 88 88 } … … 113 113 uintptr_t paddr; 114 114 pte_t *t; 115 ipl_t ipl; 115 116 int rc; 116 117 118 ipl = interrupts_disable(); 119 117 120 /* 118 121 * Find physical address of futex counter. … … 122 125 if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) { 123 126 page_table_unlock(AS, true); 127 interrupts_restore(ipl); 124 128 return (unative_t) ENOENT; 125 129 } … … 127 131 page_table_unlock(AS, true); 128 132 133 interrupts_restore(ipl); 134 129 135 futex = futex_find(paddr); 130 136 … … 150 156 uintptr_t paddr; 151 157 pte_t *t; 158 ipl_t ipl; 159 160 ipl = interrupts_disable(); 152 161 153 162 /* … … 158 167 if (!t || !PTE_VALID(t) || !PTE_PRESENT(t)) { 159 168 page_table_unlock(AS, true); 169 interrupts_restore(ipl); 160 170 return (unative_t) ENOENT; 161 171 } … … 163 173 page_table_unlock(AS, true); 164 174 175 interrupts_restore(ipl); 176 165 177 futex = futex_find(paddr); 166 178 … … 188 200 * or allocate new one if it does not exist already. 189 201 */ 190 mutex_lock(&futex_ht_lock);202 rwlock_read_lock(&futex_ht_lock); 191 203 item = hash_table_find(&futex_ht, &paddr); 192 204 if (item) { … … 200 212 /* 201 213 * The futex is new to the current task. 202 * Upgrade its reference count and put it to the203 * current task's B+tree of known futexes.214 * However, we only have read access. 215 * Gain write access and try again. 204 216 */ 205 futex->refcount++;206 btree_insert(&TASK->futexes, paddr, futex, leaf);217 mutex_unlock(&TASK->futexes_lock); 218 goto gain_write_access; 207 219 } 208 220 mutex_unlock(&TASK->futexes_lock); 221 222 rwlock_read_unlock(&futex_ht_lock); 209 223 } else { 210 futex = (futex_t *) malloc(sizeof(futex_t), 0); 211 futex_initialize(futex); 212 futex->paddr = paddr; 213 hash_table_insert(&futex_ht, &paddr, &futex->ht_link); 224 gain_write_access: 225 /* 226 * Upgrade to writer is not currently supported, 227 * therefore, it is necessary to release the read lock 228 * and reacquire it as a writer. 229 */ 230 rwlock_read_unlock(&futex_ht_lock); 231 232 rwlock_write_lock(&futex_ht_lock); 233 /* 234 * Avoid possible race condition by searching 235 * the hash table once again with write access. 236 */ 237 item = hash_table_find(&futex_ht, &paddr); 238 if (item) { 239 futex = hash_table_get_instance(item, futex_t, ht_link); 214 240 215 /* 216 * This is the first task referencing the futex. 217 * It can be directly inserted into its 218 * B+tree of known futexes. 219 */ 220 mutex_lock(&TASK->futexes_lock); 221 btree_insert(&TASK->futexes, paddr, futex, NULL); 222 mutex_unlock(&TASK->futexes_lock); 223 241 /* 242 * See if this futex is known to the current task. 243 */ 244 mutex_lock(&TASK->futexes_lock); 245 if (!btree_search(&TASK->futexes, paddr, &leaf)) { 246 /* 247 * The futex is new to the current task. 248 * Upgrade its reference count and put it to the 249 * current task's B+tree of known futexes. 250 */ 251 futex->refcount++; 252 btree_insert(&TASK->futexes, paddr, futex, 253 leaf); 254 } 255 mutex_unlock(&TASK->futexes_lock); 256 257 rwlock_write_unlock(&futex_ht_lock); 258 } else { 259 futex = (futex_t *) malloc(sizeof(futex_t), 0); 260 futex_initialize(futex); 261 futex->paddr = paddr; 262 hash_table_insert(&futex_ht, &paddr, &futex->ht_link); 263 264 /* 265 * This is the first task referencing the futex. 266 * It can be directly inserted into its 267 * B+tree of known futexes. 268 */ 269 mutex_lock(&TASK->futexes_lock); 270 btree_insert(&TASK->futexes, paddr, futex, NULL); 271 mutex_unlock(&TASK->futexes_lock); 272 273 rwlock_write_unlock(&futex_ht_lock); 274 } 224 275 } 225 mutex_unlock(&futex_ht_lock);226 276 227 277 return futex; … … 274 324 link_t *cur; 275 325 276 mutex_lock(&futex_ht_lock);326 rwlock_write_lock(&futex_ht_lock); 277 327 mutex_lock(&TASK->futexes_lock); 278 328 … … 294 344 295 345 mutex_unlock(&TASK->futexes_lock); 296 mutex_unlock(&futex_ht_lock);346 rwlock_write_unlock(&futex_ht_lock); 297 347 } 298 348
Note:
See TracChangeset
for help on using the changeset viewer.