Changeset View
Changeset View
Standalone View
Standalone View
sys/sys/seqc.h
Show All 39 Lines | |||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
/* A hack to get MPASS macro */ | /* A hack to get MPASS macro */ | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#define SEQC_MOD 1 | |||||
/* | /* | ||||
* Predicts from inline functions are not honored by clang. | * Predicts from inline functions are not honored by clang. | ||||
*/ | */ | ||||
#define seqc_in_modify(seqc) ({ \ | #define seqc_in_modify(seqc) ({ \ | ||||
seqc_t __seqc = (seqc); \ | seqc_t __seqc = (seqc); \ | ||||
\ | \ | ||||
__predict_false(__seqc & 1); \ | __predict_false(__seqc & SEQC_MOD); \ | ||||
}) | }) | ||||
static __inline void | static __inline void | ||||
seqc_write_begin(seqc_t *seqcp) | seqc_write_begin(seqc_t *seqcp) | ||||
{ | { | ||||
critical_enter(); | critical_enter(); | ||||
MPASS(!seqc_in_modify(*seqcp)); | MPASS(!seqc_in_modify(*seqcp)); | ||||
*seqcp += 1; | *seqcp += SEQC_MOD; | ||||
atomic_thread_fence_rel(); | atomic_thread_fence_rel(); | ||||
} | } | ||||
static __inline void | static __inline void | ||||
seqc_write_end(seqc_t *seqcp) | seqc_write_end(seqc_t *seqcp) | ||||
{ | { | ||||
atomic_thread_fence_rel(); | atomic_thread_fence_rel(); | ||||
*seqcp += 1; | *seqcp += SEQC_MOD; | ||||
MPASS(!seqc_in_modify(*seqcp)); | MPASS(!seqc_in_modify(*seqcp)); | ||||
critical_exit(); | critical_exit(); | ||||
} | } | ||||
static __inline seqc_t | static __inline seqc_t | ||||
seqc_read_any(const seqc_t *seqcp) | seqc_read_any(const seqc_t *seqcp) | ||||
{ | { | ||||
return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp))); | return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp))); | ||||
} | } | ||||
static __inline seqc_t | static __inline seqc_t | ||||
seqc_read_notmodify(const seqc_t *seqcp) | seqc_read_notmodify(const seqc_t *seqcp) | ||||
{ | { | ||||
return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~1); | return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~SEQC_MOD); | ||||
} | } | ||||
static __inline seqc_t | static __inline seqc_t | ||||
seqc_read(const seqc_t *seqcp) | seqc_read(const seqc_t *seqcp) | ||||
{ | { | ||||
seqc_t ret; | seqc_t ret; | ||||
for (;;) { | for (;;) { | ||||
Show All 24 Lines | |||||
/* | /* | ||||
* Variant which does not critical enter/exit. | * Variant which does not critical enter/exit. | ||||
*/ | */ | ||||
static __inline void | static __inline void | ||||
seqc_sleepable_write_begin(seqc_t *seqcp) | seqc_sleepable_write_begin(seqc_t *seqcp) | ||||
{ | { | ||||
MPASS(!seqc_in_modify(*seqcp)); | MPASS(!seqc_in_modify(*seqcp)); | ||||
*seqcp += 1; | *seqcp += SEQC_MOD; | ||||
atomic_thread_fence_rel(); | atomic_thread_fence_rel(); | ||||
} | } | ||||
static __inline void | static __inline void | ||||
seqc_sleepable_write_end(seqc_t *seqcp) | seqc_sleepable_write_end(seqc_t *seqcp) | ||||
{ | { | ||||
atomic_thread_fence_rel(); | atomic_thread_fence_rel(); | ||||
*seqcp += 1; | *seqcp += SEQC_MOD; | ||||
MPASS(!seqc_in_modify(*seqcp)); | MPASS(!seqc_in_modify(*seqcp)); | ||||
} | } | ||||
#endif /* _KERNEL */ | #endif /* _KERNEL */ | ||||
#endif /* _SYS_SEQC_H_ */ | #endif /* _SYS_SEQC_H_ */ |