OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The Native Client Authors. All rights reserved. | 2 * Copyright 2015 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 /* | 7 /* |
8 * Native Client rwlock implementation | 8 * Native Client rwlock implementation |
9 * | 9 * |
10 * This implementation is a 'write-preferring' reader-writer lock which | 10 * This implementation is a 'write-preferring' reader-writer lock which |
11 * avoids writer starvation by preventing readers from acquiring the lock | 11 * avoids writer starvation by preventing readers from acquiring the lock |
12 * while there are waiting writers (with an exception to prevent deadlocks | 12 * while there are waiting writers (with an exception to prevent deadlocks |
13 * in the case of recursive read lock (see read_lock_available)). See: | 13 * in the case of recursive read lock (see read_lock_available)). See: |
14 * http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock | 14 * http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock |
15 * | 15 * |
16 * The thundering herd problem is avoided by only waking a single | 16 * The thundering herd problem is avoided (at least for waiting writers) |
17 * waiter (either a single writer or a single reader) when the | 17 * by only waking a single writer at a time. |
18 * lock is released. | |
19 */ | 18 */ |
20 | 19 |
21 #include <errno.h> | 20 #include <errno.h> |
22 | 21 |
23 #include "native_client/src/untrusted/pthread/pthread.h" | 22 #include "native_client/src/untrusted/pthread/pthread.h" |
24 #include "native_client/src/untrusted/pthread/pthread_internal.h" | 23 #include "native_client/src/untrusted/pthread/pthread_internal.h" |
25 #include "native_client/src/untrusted/pthread/pthread_types.h" | 24 #include "native_client/src/untrusted/pthread/pthread_types.h" |
26 | 25 |
27 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) { | 26 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr) { |
28 attr->type = PTHREAD_PROCESS_PRIVATE; | 27 attr->type = PTHREAD_PROCESS_PRIVATE; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 rc = EPERM; | 231 rc = EPERM; |
233 goto done; | 232 goto done; |
234 } | 233 } |
235 | 234 |
236 /* Release write lock. */ | 235 /* Release write lock. */ |
237 rwlock->writer_thread_id = NACL_PTHREAD_ILLEGAL_THREAD_ID; | 236 rwlock->writer_thread_id = NACL_PTHREAD_ILLEGAL_THREAD_ID; |
238 if (rwlock->writers_waiting > 0) { | 237 if (rwlock->writers_waiting > 0) { |
239 /* Wake a waiting writer if there is one. */ | 238 /* Wake a waiting writer if there is one. */ |
240 rc = pthread_cond_signal(&rwlock->write_possible); | 239 rc = pthread_cond_signal(&rwlock->write_possible); |
241 } else { | 240 } else { |
242 /* Otherwise wake a waiting reader. */ | 241 /* |
243 rc = pthread_cond_signal(&rwlock->read_possible); | 242 * Otherwise wake all waiting readers. All of them should be able |
| 243 * to make progress now that the write lock is no longer held. |
| 244 */ |
| 245 rc = pthread_cond_broadcast(&rwlock->read_possible); |
244 } | 246 } |
245 } else { | 247 } else { |
246 if (rwlock->reader_count == 0) { | 248 if (rwlock->reader_count == 0) { |
247 rc = EPERM; | 249 rc = EPERM; |
248 goto done; | 250 goto done; |
249 } | 251 } |
250 | 252 |
251 /* Release read lock. */ | 253 /* Release read lock. */ |
252 rwlock->reader_count--; | 254 rwlock->reader_count--; |
253 __nc_get_tdb()->rdlock_count--; | 255 __nc_get_tdb()->rdlock_count--; |
(...skipping 30 matching lines...) Expand all Loading... |
284 | 286 |
285 /* Finally unlock the mutex and destroy it. */ | 287 /* Finally unlock the mutex and destroy it. */ |
286 pthread_mutex_unlock(&rwlock->mutex); | 288 pthread_mutex_unlock(&rwlock->mutex); |
287 int rc3 = pthread_mutex_destroy(&rwlock->mutex); | 289 int rc3 = pthread_mutex_destroy(&rwlock->mutex); |
288 if (rc1 != 0) | 290 if (rc1 != 0) |
289 return rc1; | 291 return rc1; |
290 if (rc2 != 0) | 292 if (rc2 != 0) |
291 return rc2; | 293 return rc2; |
292 return rc3; | 294 return rc3; |
293 } | 295 } |
OLD | NEW |