| 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 |