Skip to content

Instantly share code, notes, and snippets.

@kalamay
Created December 20, 2016 05:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kalamay/647dd8f28e7747f106bda866923497ba to your computer and use it in GitHub Desktop.
Save kalamay/647dd8f28e7747f106bda866923497ba to your computer and use it in GitHub Desktop.
Lock macros.
// 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