diff options
| author | Qi Wang <interwq@gwu.edu> | 2019-04-03 00:50:42 (GMT) |
|---|---|---|
| committer | Qi Wang <interwq@gwu.edu> | 2019-04-03 00:50:42 (GMT) |
| commit | b0b3e49a54ec29e32636f4577d9d5a896d67fd20 (patch) | |
| tree | e80fd5feaedd401e7e2c884e73f8c884f51b5a65 /include/jemalloc/internal/seq.h | |
| parent | 61efbda7098de6fe64c362d309824864308c36d4 (diff) | |
| parent | f7489dc8f1fac233b0cd4e40331de8b738b1f2e2 (diff) | |
| download | jemalloc-5.2.0.zip jemalloc-5.2.0.tar.gz jemalloc-5.2.0.tar.bz2 | |
Merge branch 'dev'5.2.0
Diffstat (limited to 'include/jemalloc/internal/seq.h')
| -rw-r--r-- | include/jemalloc/internal/seq.h | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/include/jemalloc/internal/seq.h b/include/jemalloc/internal/seq.h new file mode 100644 index 0000000..ef2df4c --- /dev/null +++ b/include/jemalloc/internal/seq.h @@ -0,0 +1,55 @@ +#ifndef JEMALLOC_INTERNAL_SEQ_H +#define JEMALLOC_INTERNAL_SEQ_H + +#include "jemalloc/internal/atomic.h" + +/* + * A simple seqlock implementation. + */ + +#define seq_define(type, short_type) \ +typedef struct { \ + atomic_zu_t seq; \ + atomic_zu_t data[ \ + (sizeof(type) + sizeof(size_t) - 1) / sizeof(size_t)]; \ +} seq_##short_type##_t; \ + \ +/* \ + * No internal synchronization -- the caller must ensure that there's \ + * only a single writer at a time. \ + */ \ +static inline void \ +seq_store_##short_type(seq_##short_type##_t *dst, type *src) { \ + size_t buf[sizeof(dst->data) / sizeof(size_t)]; \ + buf[sizeof(buf) / sizeof(size_t) - 1] = 0; \ + memcpy(buf, src, sizeof(type)); \ + size_t old_seq = atomic_load_zu(&dst->seq, ATOMIC_RELAXED); \ + atomic_store_zu(&dst->seq, old_seq + 1, ATOMIC_RELAXED); \ + atomic_fence(ATOMIC_RELEASE); \ + for (size_t i = 0; i < sizeof(buf) / sizeof(size_t); i++) { \ + atomic_store_zu(&dst->data[i], buf[i], ATOMIC_RELAXED); \ + } \ + atomic_store_zu(&dst->seq, old_seq + 2, ATOMIC_RELEASE); \ +} \ + \ +/* Returns whether or not the read was consistent. */ \ +static inline bool \ +seq_try_load_##short_type(type *dst, seq_##short_type##_t *src) { \ + size_t buf[sizeof(src->data) / sizeof(size_t)]; \ + size_t seq1 = atomic_load_zu(&src->seq, ATOMIC_ACQUIRE); \ + if (seq1 % 2 != 0) { \ + return false; \ + } \ + for (size_t i = 0; i < sizeof(buf) / sizeof(size_t); i++) { \ + buf[i] = atomic_load_zu(&src->data[i], ATOMIC_RELAXED); \ + } \ + atomic_fence(ATOMIC_ACQUIRE); \ + size_t seq2 = atomic_load_zu(&src->seq, ATOMIC_RELAXED); \ + if (seq1 != seq2) { \ + return false; \ + } \ + memcpy(dst, buf, sizeof(type)); \ + return true; \ +} + +#endif /* JEMALLOC_INTERNAL_SEQ_H */ |
