/* See LICENSE file for copyright and license details. */ #define LIBAXL_CONNECTION_RWLOCK\ volatile _Atomic char nrguard_send;\ volatile _Atomic char nrguard_recv;\ MUTEX exguard_send;\ MUTEX exguard_recv;\ MUTEX exwait_send;\ MUTEX exwait_recv;\ volatile size_t nreaders_send;\ volatile size_t nreaders_recv #define INIT_LIBAXL_CONNECTION_RWLOCK(CONN)\ do {\ atomic_init(&(CONN)->nrguard_send, 0);\ atomic_init(&(CONN)->nrguard_recv, 0);\ INIT_MUTEX((CONN)->exguard_send);\ INIT_MUTEX((CONN)->exguard_recv);\ INIT_MUTEX((CONN)->exwait_send);\ INIT_MUTEX((CONN)->exwait_recv);\ (CONN)->nreaders_send = 0;\ (CONN)->nreaders_recv = 0;\ } while (0) #define WLOCK_CONNECTION_(CONN, SUFFIX) _LOCK((CONN)->exguard_##SUFFIX) #define WTRYLOCK_CONNECTION_(CONN, SUFFIX) _TRYLOCK((CONN)->exguard_##SUFFIX) #define WUNLOCK_CONNECTION_(CONN, SUFFIX) _UNLOCK((CONN)->exguard_##SUFFIX) #define RLOCK_CONNECTION_(CONN, SUFFIX)\ do {\ char old_val__;\ do {\ do {\ old_val__ = atomic_fetch_or(&(CONN)->nrguard_##SUFFIX, 1);\ } while (old_val__ == 1);\ if (old_val__ == 0) {\ if (!(CONN)->nreaders_##SUFFIX++) {\ if (WTRYLOCK_CONNECTION_(CONN, SUFFIX)) {\ atomic_store(&(CONN)->nrguard_##SUFFIX, 2);\ } else {\ _LOCK((CONN)->exwait_##SUFFIX);\ atomic_store(&(CONN)->nrguard_##SUFFIX, 2);\ WLOCK_CONNECTION_(CONN, SUFFIX);\ _UNLOCK((CONN)->exwait_##SUFFIX);\ }\ }\ atomic_store(&(CONN)->nrguard_##SUFFIX, 0);\ break;\ } else {\ _WAIT((CONN)->exwait_##SUFFIX);\ }\ } while (old_val__ == 2);\ } while (0) #define RUNLOCK_CONNECTION_(CONN, SUFFIX)\ do {\ char old_val__;\ do {\ old_val__ = atomic_fetch_or(&(CONN)->nrguard_##SUFFIX, 1);\ } while (old_val__);\ if (!--(CONN)->nreaders_##SUFFIX)\ WUNLOCK_CONNECTION_((CONN), SUFFIX);\ atomic_store(&(CONN)->nrguard_##SUFFIX, 0);\ } while (0) #define WLOCK_CONNECTION_SEND(CONN) WLOCK_CONNECTION_(CONN, send) #define WUNLOCK_CONNECTION_SEND(CONN) WUNLOCK_CONNECTION_(CONN, send) #define RLOCK_CONNECTION_SEND(CONN) RLOCK_CONNECTION_(CONN, send) #define RUNLOCK_CONNECTION_SEND(CONN) RUNLOCK_CONNECTION_(CONN, send) #define WLOCK_CONNECTION_RECV(CONN) WLOCK_CONNECTION_(CONN, recv) #define WUNLOCK_CONNECTION_RECV(CONN) WUNLOCK_CONNECTION_(CONN, recv) #define RLOCK_CONNECTION_RECV(CONN) RLOCK_CONNECTION_(CONN, recv) #define RUNLOCK_CONNECTION_RECV(CONN) RUNLOCK_CONNECTION_(CONN, recv)