// Lock is used in places like pthread_rwlock_t, which can be initialized without calling // an initialization function. So make sure Lock can be initialized by setting its memory to 0. class Lock { private: enum LockState {
Unlocked = 0,
LockedWithoutWaiter,
LockedWithWaiter,
};
_Atomic(LockState) state; bool process_shared;
void lock() {
LockState old_state = Unlocked; if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed))) { return;
} while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) { // TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
__futex_wait_ex(&state, process_shared, LockedWithWaiter);
} return;
}
void unlock() { bool shared = process_shared; /* cache to local variable */ if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) { // The Lock object may have been deallocated between the atomic exchange and the futex wake // call, so avoid accessing any fields of Lock here. In that case, the wake call may target // unmapped memory or trigger a spurious futex wakeup. The same situation happens with // pthread mutexes. References: // - https://lkml.org/lkml/2014/11/27/472 // - http://austingroupbugs.net/view.php?id=811#c2267
__futex_wake_ex(&state, shared, 1);
}
}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.