use core::{hint::unlikely, ptr::read_volatile};
use crate::processor::{cpu_relax, smp_rmb, smp_wmb};
#[derive(Default)]
pub struct SeqCount {
seqence: u32,
}
impl SeqCount {
pub const fn new() -> Self {
Self { seqence: 0 }
}
#[inline(always)]
fn __read_seqcount_begin(&self) -> u32 {
loop {
let ret = unsafe { read_volatile(&raw const self.seqence) };
if unlikely((ret & 1) != 0) {
cpu_relax();
continue;
}
return ret;
}
}
#[inline(always)]
pub fn read_seqcount_begin(&self) -> u32 {
let ret = self.__read_seqcount_begin();
smp_rmb();
ret
}
#[inline(always)]
fn __read_seqcount_retry(&self, start: u32) -> bool {
unlikely(self.seqence != start)
}
#[inline(always)]
pub fn read_seqcount_retry(&self, start: u32) -> bool {
smp_rmb();
self.__read_seqcount_retry(start)
}
#[inline(always)]
pub fn read_seqcount(&self) -> u32 {
let ret = unsafe { read_volatile(&raw const self.seqence) };
smp_rmb();
ret
}
#[inline(always)]
pub fn write_seqcount_begin(&mut self) {
self.seqence += 1;
smp_wmb();
}
#[inline(always)]
pub fn write_seqcount_end(&mut self) {
smp_wmb();
self.seqence += 1;
}
#[inline(always)]
pub fn write_seqcount_latch(&mut self) {
smp_wmb();
self.seqence += 1;
smp_wmb();
}
#[inline(always)]
pub fn write_seqcount_barrier(&mut self) {
self.seqence += 1;
smp_wmb();
self.seqence += 1;
}
}