Created
December 20, 2016 05:48
-
-
Save kalamay/647dd8f28e7747f106bda866923497ba to your computer and use it in GitHub Desktop.
Lock macros.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on: http://locklessinc.com/articles/locks/ | |
#include <unistd.h> | |
#define XPAUSE() __asm__ __volatile__("pause\n": : :"memory") | |
#define XBARRIER() __asm__ __volatile__("": : :"memory") | |
#define XCMPXCHG(P, O, N) __sync_bool_compare_and_swap((P), (O), (N)) | |
#define XATOMIC_FETCH_ADD(P, V) __sync_fetch_and_add((P), (V)) | |
#define XATOMIC_ADD_FETCH(P, V) __sync_add_and_fetch((P), (V)) | |
#define XWAIT(cond) do { \ | |
for (unsigned n = 0; (cond); n++) { \ | |
if (n < 10000) { XPAUSE (); } \ | |
else { usleep (10); } \ | |
} \ | |
} while (0) | |
union xlock { | |
uint64_t u; | |
struct { | |
uint32_t ticket; | |
uint32_t users; | |
} s; | |
}; | |
#define XLOCK_MAKE() { .u = 0 } | |
#define XLOCK(l) do { \ | |
uint32_t me = XATOMIC_FETCH_ADD (&l.s.users, 1); \ | |
XWAIT (l.s.ticket != me); \ | |
} while (0) | |
#define XLOCK_TRY(l) __extension__ ({ \ | |
uint32_t me = l.s.users; \ | |
uint32_t menew = me + 1; \ | |
uint64_t cmp = ((uint64_t)me << 32) + me; \ | |
uint64_t cmpnew = ((uint64_t)menew << 32) + me; \ | |
XCMPXCHG (&l.u, cmp, cmpnew); \ | |
}) | |
#define XUNLOCK(l) do { \ | |
XBARRIER (); \ | |
l.s.ticket++; \ | |
} while (0) | |
union xlock_rw { | |
uint64_t u; | |
uint32_t us; | |
struct { | |
uint16_t writers; | |
uint16_t readers; | |
uint16_t users; | |
uint16_t pad; | |
} s; | |
}; | |
#define XLOCK_RW_MAKE() { .u = 0 } | |
#define XLOCK_WR(l) do { \ | |
uint64_t me = XATOMIC_FETCH_ADD (&l.u, (uint64_t)1 << 32); \ | |
uint16_t val = (uint16_t)(me >> 32); \ | |
XWAIT (val != l.s.writers); \ | |
} while (0) | |
#define XLOCK_WR_TRY(l) __extension__ ({ \ | |
uint64_t me = l.s.users; \ | |
uint16_t menew = me + 1; \ | |
uint64_t readers = l.s.readers << 16; \ | |
uint64_t cmp = (me << 32) + readers + me; \ | |
uint64_t cmpnew = ((uint64_t)menew << 32) + readers + me; \ | |
XCMPXCHG (&l.u, cmp, cmpnew); \ | |
}) | |
#define XUNLOCK_WR(l) do { \ | |
union xlock_rw t = l; \ | |
XBARRIER (); \ | |
t.s.writers++; \ | |
t.s.readers++; \ | |
l.us = t.us; \ | |
} while (0) | |
#define XLOCK_RD(l) do { \ | |
uint64_t me = XATOMIC_FETCH_ADD (&l.u, (uint64_t)1 << 32); \ | |
uint16_t val = (uint16_t)(me >> 32); \ | |
XWAIT (val != l.s.readers); \ | |
++l.s.readers; \ | |
} while (0) | |
#define XLOCK_RD_TRY(l) __extension__ ({ \ | |
uint64_t me = l.s.users; \ | |
uint64_t writers = l.s.writers; \ | |
uint16_t menew = me + 1; \ | |
uint64_t cmp = (me << 32) + (me << 16) + writers; \ | |
uint64_t cmpnew = ((uint64_t) menew << 32) + (menew << 16) + writers; \ | |
XCMPXCHG (&l.u, cmp, cmpnew); \ | |
}) | |
#define XUNLOCK_RD(l) do { \ | |
XATOMIC_ADD_FETCH (&l.s.writers, 1); \ | |
} while (0) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment