Skip to content

Commit 69eb75f

Browse files
committed
allow using more time sources
1 parent d7dca40 commit 69eb75f

File tree

1 file changed

+163
-41
lines changed

1 file changed

+163
-41
lines changed

src/timed_span.rs

Lines changed: 163 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::arch::asm;
21
use std::sync::atomic::{AtomicU64, Ordering};
32

43
macro_rules! entries {
@@ -90,57 +89,180 @@ pub fn print_counters() {
9089
}
9190
}
9291

93-
#[cfg(target_arch = "aarch64")]
94-
#[inline]
95-
fn read_cycle_counter() -> u64 {
96-
let val: u64;
97-
unsafe {
98-
asm!(
99-
"mrs {}, CNTVCT_EL0",
100-
out(reg) val,
101-
options(nostack, nomem)
102-
);
103-
}
104-
val
105-
}
92+
#[allow(dead_code)]
93+
mod tsc {
94+
use std::arch::asm;
95+
use std::sync::atomic::{AtomicU64, Ordering};
96+
#[cfg(target_arch = "aarch64")]
97+
#[inline]
98+
fn read_cycle_counter() -> u64 {
99+
let val: u64;
100+
unsafe {
101+
asm!(
102+
"mrs {}, CNTVCT_EL0",
103+
out(reg) val,
104+
options(nostack, nomem)
105+
);
106+
}
107+
val
108+
}
106109

107-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
108-
#[inline]
109-
fn read_cycle_counter() -> u64 {
110-
let lo: u32;
111-
let hi: u32;
112-
unsafe {
113-
asm!(
114-
"rdtsc",
115-
out("eax") lo,
116-
out("edx") hi,
117-
options(nostack, nomem)
118-
);
119-
}
120-
((hi as u64) << 32) | (lo as u64)
121-
}
110+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
111+
#[inline]
112+
fn read_cycle_counter() -> u64 {
113+
let lo: u32;
114+
let hi: u32;
115+
unsafe {
116+
asm!(
117+
"rdtsc",
118+
out("eax") lo,
119+
out("edx") hi,
120+
options(nostack, nomem)
121+
);
122+
}
123+
((hi as u64) << 32) | (lo as u64)
124+
}
125+
126+
pub struct TimedSpanGuard<'a> {
127+
start: u64,
128+
counter: &'a AtomicU64,
129+
}
130+
131+
impl<'a> TimedSpanGuard<'a> {
132+
pub fn new(counter: &'a AtomicU64) -> Self {
133+
Self {
134+
start: read_cycle_counter(),
135+
counter,
136+
}
137+
}
138+
}
122139

123-
pub struct TimedSpanGuard<'a> {
124-
start: u64,
125-
counter: &'a AtomicU64,
140+
impl<'a> Drop for TimedSpanGuard<'a> {
141+
fn drop(&mut self) {
142+
let end = read_cycle_counter();
143+
self.counter.fetch_add(end - self.start, Ordering::Relaxed);
144+
}
145+
}
126146
}
127147

128-
impl<'a> TimedSpanGuard<'a> {
129-
pub fn new(counter: &'a AtomicU64) -> Self {
130-
Self {
131-
start: read_cycle_counter(),
132-
counter,
148+
#[allow(dead_code)]
149+
mod std_instant {
150+
use std::sync::atomic::{AtomicU64, Ordering};
151+
use std::time::Instant;
152+
pub struct TimedSpanGuard<'a> {
153+
start: Instant,
154+
counter: &'a AtomicU64,
155+
}
156+
157+
impl<'a> TimedSpanGuard<'a> {
158+
pub fn new(counter: &'a AtomicU64) -> Self {
159+
Self {
160+
start: Instant::now(),
161+
counter,
162+
}
163+
}
164+
}
165+
166+
impl<'a> Drop for TimedSpanGuard<'a> {
167+
fn drop(&mut self) {
168+
let duration = self.start.elapsed().as_nanos() as u64;
169+
self.counter.fetch_add(duration, Ordering::Relaxed);
133170
}
134171
}
135172
}
136173

137-
impl<'a> Drop for TimedSpanGuard<'a> {
138-
fn drop(&mut self) {
139-
let end = read_cycle_counter();
140-
self.counter.fetch_add(end - self.start, Ordering::Relaxed);
174+
#[allow(dead_code)]
175+
mod clock_monotonic {
176+
use std::sync::atomic::{AtomicU64, Ordering};
177+
178+
#[cfg(target_os="linux")]
179+
mod linux {
180+
// linux/time.h
181+
// const CLOCK_REALTIME : i32 = 0;
182+
// const CLOCK_MONOTONIC : i32 = 1;
183+
// const CLOCK_PROCESS_CPUTIME_ID: i32 = 2;
184+
// const CLOCK_THREAD_CPUTIME_ID : i32 = 3;
185+
const CLOCK_MONOTONIC_RAW : i32 = 4;
186+
// const CLOCK_REALTIME_COARSE : i32 = 5;
187+
const CLOCK_MONOTONIC_COARSE : i32 = 6;
188+
// const CLOCK_BOOTTIME : i32 = 7;
189+
// const CLOCK_REALTIME_ALARM : i32 = 8;
190+
// const CLOCK_BOOTTIME_ALARM : i32 = 9;
191+
192+
#[allow(non_camel_case_types)]
193+
#[repr(C)]
194+
struct timespec {
195+
tv_sec: u64,
196+
tv_nsec: i32,
197+
}
198+
199+
extern "C" {
200+
fn clock_gettime(clockid: i32, tp: &mut timespec) -> i32;
201+
}
202+
pub fn get_time() -> u64 {
203+
let mut time = timespec { tv_sec: 0, tv_nsec: 0 };
204+
let rv = unsafe { clock_gettime(CLOCK_MONOTONIC_RAW, &mut time) };
205+
debug_assert!(rv == 0, "failed clock_gettime?");
206+
time.tv_sec * 1_000_000_000 + time.tv_nsec as u64
207+
}
208+
}
209+
#[cfg(target_os="linux")]
210+
use linux::get_time;
211+
212+
#[cfg(all(target_os="macos", target_arch="aarch64"))]
213+
mod macos {
214+
const CLOCK_MONOTONIC_RAW : i32 = 4;
215+
const CLOCK_MONOTONIC_RAW_APPROX: i32 = 5;
216+
const CLOCK_MONOTONIC : i32 = 6;
217+
// const CALENDAR_CLOCK: u64 = 1;
218+
#[allow(non_camel_case_types)]
219+
#[repr(C)]
220+
struct timespec {
221+
tv_sec: u64,
222+
tv_nsec: i32,
223+
}
224+
extern "C" {
225+
// host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
226+
// fn clock_get_time(clock_serv: &mut u64, cur_time: &mut mach_timespec) -> i64;
227+
// mach_port_deallocate(mach_task_self(), cclock);
228+
fn clock_gettime(clock_serv: i32, cur_time: &mut timespec) -> i64;
229+
}
230+
231+
pub fn get_time() -> u64 {
232+
let mut time = timespec { tv_sec: 0, tv_nsec: 0 };
233+
let _rv = unsafe { clock_gettime(CLOCK_MONOTONIC_RAW, &mut time) };
234+
let rv = unsafe { clock_gettime(CLOCK_MONOTONIC_RAW, &mut time) };
235+
debug_assert!(rv == 0, "failed clock_gettime?");
236+
(time.tv_sec as u64 * 1_000_000_000) + time.tv_nsec as u64
237+
}
238+
}
239+
240+
#[cfg(all(target_os="macos", target_arch="aarch64"))]
241+
use macos::get_time;
242+
243+
pub struct TimedSpanGuard<'a> {
244+
start: u64,
245+
counter: &'a AtomicU64,
246+
}
247+
248+
impl<'a> TimedSpanGuard<'a> {
249+
pub fn new(counter: &'a AtomicU64) -> Self {
250+
Self {
251+
start: get_time(),
252+
counter,
253+
}
254+
}
255+
}
256+
257+
impl<'a> Drop for TimedSpanGuard<'a> {
258+
fn drop(&mut self) {
259+
let end = get_time();
260+
self.counter.fetch_add(end - self.start, Ordering::Relaxed);
261+
}
141262
}
142263
}
143264

265+
pub use tsc::TimedSpanGuard;
144266
pub const ENABLED: bool = true;
145267

146268
macro_rules! timed_span {

0 commit comments

Comments
 (0)