| 21 | //------------------------------------------------------------------------------ |
| 22 | |
| 23 | static void _CreateRWLock |
| 24 | ( |
| 25 | Graph *g |
| 26 | ) { |
| 27 | // create a read write lock which favors writes |
| 28 | // |
| 29 | // consider the following locking sequence: |
| 30 | // T0 read lock (acquired) |
| 31 | // T1 write lock (waiting) |
| 32 | // T2 read lock (acquired if lock favor reads, waiting if favor writes) |
| 33 | // |
| 34 | // we don't want to cause write starvation as this can impact overall |
| 35 | // system performance |
| 36 | |
| 37 | // specify prefer write in lock creation attributes |
| 38 | int res = 0 ; |
| 39 | UNUSED(res) ; |
| 40 | |
| 41 | pthread_rwlockattr_t attr ; |
| 42 | res = pthread_rwlockattr_init(&attr) ; |
| 43 | ASSERT(res == 0) ; |
| 44 | |
| 45 | #if !defined(__APPLE__) && !defined(__FreeBSD__) |
| 46 | int pref = PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP ; |
| 47 | res = pthread_rwlockattr_setkind_np(&attr, pref) ; |
| 48 | ASSERT(res == 0) ; |
| 49 | #endif |
| 50 | |
| 51 | res = pthread_rwlock_init(&g->_rwlock, &attr); |
| 52 | ASSERT(res == 0) ; |
| 53 | } |
| 54 | |
| 55 | // acquire a lock that does not restrict access from additional reader threads |
| 56 | void Graph_AcquireReadLock(Graph *g) { |