1 1.1 christos #ifndef JEMALLOC_INTERNAL_SEQ_H 2 1.1 christos #define JEMALLOC_INTERNAL_SEQ_H 3 1.1 christos 4 1.1 christos #include "jemalloc/internal/atomic.h" 5 1.1 christos 6 1.1 christos /* 7 1.1 christos * A simple seqlock implementation. 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #define seq_define(type, short_type) \ 11 1.1 christos typedef struct { \ 12 1.1 christos atomic_zu_t seq; \ 13 1.1 christos atomic_zu_t data[ \ 14 1.1 christos (sizeof(type) + sizeof(size_t) - 1) / sizeof(size_t)]; \ 15 1.1 christos } seq_##short_type##_t; \ 16 1.1 christos \ 17 1.1 christos /* \ 18 1.1 christos * No internal synchronization -- the caller must ensure that there's \ 19 1.1 christos * only a single writer at a time. \ 20 1.1 christos */ \ 21 1.1 christos static inline void \ 22 1.1 christos seq_store_##short_type(seq_##short_type##_t *dst, type *src) { \ 23 1.1 christos size_t buf[sizeof(dst->data) / sizeof(size_t)]; \ 24 1.1 christos buf[sizeof(buf) / sizeof(size_t) - 1] = 0; \ 25 1.1 christos memcpy(buf, src, sizeof(type)); \ 26 1.1 christos size_t old_seq = atomic_load_zu(&dst->seq, ATOMIC_RELAXED); \ 27 1.1 christos atomic_store_zu(&dst->seq, old_seq + 1, ATOMIC_RELAXED); \ 28 1.1 christos atomic_fence(ATOMIC_RELEASE); \ 29 1.1 christos for (size_t i = 0; i < sizeof(buf) / sizeof(size_t); i++) { \ 30 1.1 christos atomic_store_zu(&dst->data[i], buf[i], ATOMIC_RELAXED); \ 31 1.1 christos } \ 32 1.1 christos atomic_store_zu(&dst->seq, old_seq + 2, ATOMIC_RELEASE); \ 33 1.1 christos } \ 34 1.1 christos \ 35 1.1 christos /* Returns whether or not the read was consistent. */ \ 36 1.1 christos static inline bool \ 37 1.1 christos seq_try_load_##short_type(type *dst, seq_##short_type##_t *src) { \ 38 1.1 christos size_t buf[sizeof(src->data) / sizeof(size_t)]; \ 39 1.1 christos size_t seq1 = atomic_load_zu(&src->seq, ATOMIC_ACQUIRE); \ 40 1.1 christos if (seq1 % 2 != 0) { \ 41 1.1 christos return false; \ 42 1.1 christos } \ 43 1.1 christos for (size_t i = 0; i < sizeof(buf) / sizeof(size_t); i++) { \ 44 1.1 christos buf[i] = atomic_load_zu(&src->data[i], ATOMIC_RELAXED); \ 45 1.1 christos } \ 46 1.1 christos atomic_fence(ATOMIC_ACQUIRE); \ 47 1.1 christos size_t seq2 = atomic_load_zu(&src->seq, ATOMIC_RELAXED); \ 48 1.1 christos if (seq1 != seq2) { \ 49 1.1 christos return false; \ 50 1.1 christos } \ 51 1.1 christos memcpy(dst, buf, sizeof(type)); \ 52 1.1 christos return true; \ 53 1.1 christos } 54 1.1 christos 55 1.1 christos #endif /* JEMALLOC_INTERNAL_SEQ_H */ 56