Changeset View
Changeset View
Standalone View
Standalone View
sys/sys/smr.h
Show First 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
#define SMR_SEQ_GEQ(a, b) ((smr_delta_t)((a)-(b)) >= 0) | #define SMR_SEQ_GEQ(a, b) ((smr_delta_t)((a)-(b)) >= 0) | ||||
#define SMR_SEQ_DELTA(a, b) ((smr_delta_t)((a)-(b))) | #define SMR_SEQ_DELTA(a, b) ((smr_delta_t)((a)-(b))) | ||||
#define SMR_SEQ_MIN(a, b) (SMR_SEQ_LT((a), (b)) ? (a) : (b)) | #define SMR_SEQ_MIN(a, b) (SMR_SEQ_LT((a), (b)) ? (a) : (b)) | ||||
#define SMR_SEQ_MAX(a, b) (SMR_SEQ_GT((a), (b)) ? (a) : (b)) | #define SMR_SEQ_MAX(a, b) (SMR_SEQ_GT((a), (b)) ? (a) : (b)) | ||||
#define SMR_SEQ_INVALID 0 | #define SMR_SEQ_INVALID 0 | ||||
/* Shared SMR state. */ | /* Shared SMR state. */ | ||||
union s_wr { | |||||
jeff: I feel like this is a little ugly but ok. If someone has another suggestion to ensure the… | |||||
rlibbyUnsubmitted Not Done Inline ActionsI know that gcc explicitly blesses type punning with a union, but from what I was able to find, I think clang does not (e.g. https://reviews.llvm.org/D30538). However, we seem to use -fno-strict-aliasing, so I think we should be okay anyway. I did look at the (amd64) code generation and it looked fine as far as I was able to tell. An alternative would be to _Static_assert the size, drop the union, and do the read/write like uint64_t old, new; old = atomic_load_acq_64(&s->s_wr); memcpy(&s_wr, &old, sizeof()); ... memcpy(&new, &s_wr, sizeof()); atomic_cmpset_64(&s->s_wr, &old, new); But one may find this to be even uglier. rlibby: I know that gcc explicitly blesses type punning with a union, but from what I was able to find… | |||||
struct { | |||||
smr_seq_t seq; /* Current write sequence #. */ | |||||
int ticks; /* tick of last update (LAZY) */ | |||||
}; | |||||
uint64_t _pair; | |||||
}; | |||||
struct smr_shared { | struct smr_shared { | ||||
const char *s_name; /* Name for debugging/reporting. */ | const char *s_name; /* Name for debugging/reporting. */ | ||||
smr_seq_t s_wr_seq; /* Current write sequence #. */ | union s_wr s_wr; /* Write sequence */ | ||||
smr_seq_t s_rd_seq; /* Minimum observed read sequence. */ | smr_seq_t s_rd_seq; /* Minimum observed read sequence. */ | ||||
}; | }; | ||||
typedef struct smr_shared *smr_shared_t; | typedef struct smr_shared *smr_shared_t; | ||||
/* Per-cpu SMR state. */ | /* Per-cpu SMR state. */ | ||||
struct smr { | struct smr { | ||||
smr_seq_t c_seq; /* Current observed sequence. */ | smr_seq_t c_seq; /* Current observed sequence. */ | ||||
smr_shared_t c_shared; /* Shared SMR state. */ | smr_shared_t c_shared; /* Shared SMR state. */ | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Return the current write sequence number. This is not the same as the | * Return the current write sequence number. This is not the same as the | ||||
* current goal which may be in the future. | * current goal which may be in the future. | ||||
*/ | */ | ||||
static inline smr_seq_t | static inline smr_seq_t | ||||
smr_shared_current(smr_shared_t s) | smr_shared_current(smr_shared_t s) | ||||
{ | { | ||||
return (atomic_load_int(&s->s_wr_seq)); | return (atomic_load_int(&s->s_wr.seq)); | ||||
} | } | ||||
static inline smr_seq_t | static inline smr_seq_t | ||||
smr_current(smr_t smr) | smr_current(smr_t smr) | ||||
{ | { | ||||
return (smr_shared_current(zpcpu_get(smr)->c_shared)); | return (smr_shared_current(zpcpu_get(smr)->c_shared)); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 159 Lines • Show Last 20 Lines |
I feel like this is a little ugly but ok. If someone has another suggestion to ensure the grouping and alignment I'm all ears.