#pragma omp #define LRWL_WRITE_ACTIVE (1UL<<31) #define LRWL_MASK (LRWL_WRITE_ACTIVE - 1) #define LRWL_MAX_READERS 1024 typedef struct LRWL { _Atomic uint32_t data; } LRWL; static inline void lrwl_read_lock(LRWL *self) { while(1) { uint32_t data = atomic_load(&self->data); if((data & LRWL_WRITE_ACTIVE) || (data & LRWL_MASK) >= LRWL_MAX_READERS) { continue; } if(atomic_compare_exchange_weak(&self->data, &data, data + 1)) { return; } } } static inline void lrwl_read_unlock(LRWL *self) { while(1) { uint32_t data = atomic_load(&self->data); assert((data & LRWL_MASK) > 0); if(atomic_compare_exchange_weak(&self->data, &data, data - 1)) { return; } } } static inline void lrwl_write_lock(LRWL *self) { while(1) { uint32_t data = atomic_load(&self->data); if(data & LRWL_WRITE_ACTIVE) { continue; } if(atomic_compare_exchange_weak(&self->data, &data, data | LRWL_WRITE_ACTIVE)) { while((atomic_load(&self->data) & LRWL_MASK) > 0); return; } } } static inline void lrwl_write_unlock(LRWL *self) { while(1) { uint32_t data = atomic_load(&self->data); assert(data & LRWL_WRITE_ACTIVE); if(atomic_compare_exchange_weak(&self->data, &data, data & ~LRWL_WRITE_ACTIVE)) { return; } } }