celox_runtime/
event_buffer.rs1use std::cell::UnsafeCell;
2use std::sync::atomic::{AtomicU64, Ordering};
3
4pub struct RuntimeEventBuffer {
5 words: Box<[UnsafeCell<u64>]>,
6 byte_size: usize,
7}
8
9unsafe impl Send for RuntimeEventBuffer {}
10unsafe impl Sync for RuntimeEventBuffer {}
11
12impl RuntimeEventBuffer {
13 pub fn new(byte_size: usize) -> Self {
14 let word_count = byte_size.div_ceil(8);
15 let words = (0..word_count)
16 .map(|_| UnsafeCell::new(0u64))
17 .collect::<Vec<_>>()
18 .into_boxed_slice();
19 Self { words, byte_size }
20 }
21
22 pub fn as_ptr(&self) -> *const u8 {
23 self.words.as_ptr() as *const u8
24 }
25
26 pub fn as_mut_ptr(&self) -> *mut u8 {
27 self.words.as_ptr() as *mut u8
28 }
29
30 pub fn byte_size(&self) -> usize {
31 self.byte_size
32 }
33
34 pub fn load_atomic_u64(&self, byte_offset: usize, ordering: Ordering) -> u64 {
35 assert_eq!(byte_offset % 8, 0);
36 assert!(byte_offset + 8 <= self.byte_size);
37 let word = byte_offset / 8;
38 unsafe {
39 let ptr = self.words[word].get() as *const AtomicU64;
40 (*ptr).load(ordering)
41 }
42 }
43
44 pub fn read_u64(&self, byte_offset: usize) -> u64 {
45 assert_eq!(byte_offset % 8, 0);
46 assert!(byte_offset + 8 <= self.byte_size);
47 let word = byte_offset / 8;
48 unsafe { std::ptr::read_volatile(self.words[word].get()) }
49 }
50
51 pub fn reset(&self) {
52 for word in &self.words {
53 unsafe {
54 std::ptr::write_volatile(word.get(), 0);
55 }
56 }
57 }
58}