Skip to content

Commit accab42

Browse files
veluca93Virv12
authored andcommitted
Remove Timer from the main OS struct.
1 parent 1e4ebff commit accab42

4 files changed

Lines changed: 53 additions & 52 deletions

File tree

pixie-uefi/src/os/executor.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use super::{sync::SyncRefCell, UefiOS};
1+
use crate::os::timer::Timer;
2+
3+
use super::sync::SyncRefCell;
24
use alloc::{boxed::Box, collections::VecDeque, sync::Arc, task::Wake};
35
use core::{
46
cell::RefCell,
@@ -63,7 +65,7 @@ pub struct Executor {
6365
}
6466

6567
impl Executor {
66-
pub fn run(os: UefiOS) -> ! {
68+
pub fn run() -> ! {
6769
loop {
6870
let task = EXECUTOR
6971
.borrow_mut()
@@ -75,9 +77,9 @@ impl Executor {
7577
let waker = Waker::from(task.clone());
7678
let mut context = Context::from_waker(&waker);
7779
let mut fut = task.inner.borrow_mut().future.take().unwrap();
78-
let begin = os.timer().micros();
80+
let begin = Timer::micros();
7981
let status = fut.as_mut().poll(&mut context);
80-
let end = os.timer().micros();
82+
let end = Timer::micros();
8183
task.inner.borrow_mut().micros += end - begin;
8284
if status.is_pending() {
8385
task.inner.borrow_mut().future = Some(fut);

pixie-uefi/src/os/mod.rs

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ mod timer;
5757
pub use net::{TcpStream, UdpHandle, PACKET_SIZE};
5858

5959
struct UefiOSImpl {
60-
timer: Timer,
6160
rng: Rng,
6261
tasks: Vec<Arc<Task>>,
6362
input: ScopedProtocol<Input>,
@@ -163,7 +162,7 @@ impl UefiOS {
163162
.unwrap();
164163
}
165164

166-
let timer = Timer::new();
165+
Timer::ensure_init();
167166
let rng = Rng::new();
168167

169168
let input_handles = uefi::boot::find_handles::<Input>().unwrap();
@@ -179,7 +178,6 @@ impl UefiOS {
179178
vga.clear().unwrap();
180179

181180
*OS.borrow_mut() = Some(UefiOSImpl {
182-
timer,
183181
rng,
184182
tasks: Vec::new(),
185183
input,
@@ -227,9 +225,8 @@ impl UefiOS {
227225
os.spawn(
228226
"[net_poll]",
229227
poll_fn(move |cx| {
230-
let (mut net, timer) =
231-
RefMut::map_split(os.borrow_mut(), |os| (&mut os.net, &mut os.timer));
232-
net.as_mut().unwrap().poll(&timer);
228+
let mut os = os.borrow_mut();
229+
os.net.as_mut().unwrap().poll();
233230
// TODO(veluca): figure out whether we can suspend the task.
234231
cx.waker().wake_by_ref();
235232
Poll::Pending
@@ -239,10 +236,10 @@ impl UefiOS {
239236
os.spawn("[net_speed]", async move {
240237
let mut prx = 0;
241238
let mut ptx = 0;
242-
let mut ptm = os.timer().instant();
239+
let mut ptm = Timer::instant();
243240
loop {
244241
{
245-
let now = os.timer().instant();
242+
let now = Timer::instant();
246243
let dt = (now - ptm).total_micros() as f64 / 1_000_000.0;
247244
ptm = now;
248245

@@ -263,7 +260,7 @@ impl UefiOS {
263260
}
264261
});
265262

266-
Executor::run(os)
263+
Executor::run()
267264
}
268265

269266
fn borrow(&self) -> Ref<'static, UefiOSImpl> {
@@ -274,10 +271,6 @@ impl UefiOS {
274271
RefMut::map(OS.borrow_mut(), |f| f.as_mut().unwrap())
275272
}
276273

277-
pub fn timer(&self) -> Ref<'static, Timer> {
278-
Ref::map(self.borrow(), |f| &f.timer)
279-
}
280-
281274
pub fn rng(&self) -> RefMut<'static, Rng> {
282275
RefMut::map(self.borrow_mut(), |f| &mut f.rng)
283276
}
@@ -317,9 +310,9 @@ impl UefiOS {
317310
}
318311

319312
pub fn sleep_us(self, us: u64) -> impl Future<Output = ()> {
320-
let tgt = self.timer().micros() as u64 + us;
313+
let tgt = Timer::micros() as u64 + us;
321314
poll_fn(move |cx| {
322-
let now = self.timer().micros() as u64;
315+
let now = Timer::micros() as u64;
323316
if now >= tgt {
324317
Poll::Ready(())
325318
} else {
@@ -431,7 +424,7 @@ impl UefiOS {
431424
fn draw_ui(&self) {
432425
// Write the header.
433426
{
434-
let time = self.timer().micros() as f32 * 0.000_001;
427+
let time = Timer::micros() as f32 * 0.000_001;
435428
let ip = self.net().ip();
436429
let mut os = self.borrow_mut();
437430

@@ -572,7 +565,7 @@ impl log::Log for UefiOS {
572565
}
573566

574567
fn log(&self, record: &log::Record) {
575-
let now = self.timer().micros() as f64 * 0.000_001;
568+
let now = Timer::micros() as f64 * 0.000_001;
576569
self.append_message(
577570
now,
578571
record.level(),

pixie-uefi/src/os/net.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl NetworkInterface {
183183

184184
let mut interface_config = Config::new(hw_addr);
185185
interface_config.random_seed = os.rng().rand_u64();
186-
let now = Instant::from_micros(os.timer().micros());
186+
let now = Timer::instant();
187187
let interface = Interface::new(interface_config, &mut device, now);
188188
let mut dhcp_socket = Dhcpv4Socket::new();
189189
dhcp_socket.set_outgoing_options(&[DhcpOption {
@@ -220,8 +220,8 @@ impl NetworkInterface {
220220
self.interface.ipv4_addr()
221221
}
222222

223-
pub(super) fn poll(&mut self, timer: &Timer) -> bool {
224-
let now = timer.instant();
223+
pub(super) fn poll(&mut self) -> bool {
224+
let now = Timer::instant();
225225
let status = self
226226
.interface
227227
.poll(now, &mut self.device, &mut self.socket_set);

pixie-uefi/src/os/timer.rs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,49 @@
1-
use core::arch::x86_64::_rdtsc;
1+
use core::{
2+
arch::x86_64::_rdtsc,
3+
sync::atomic::{AtomicBool, AtomicI64, Ordering},
4+
};
25
use smoltcp::time::Instant;
36

4-
pub struct Timer {
5-
ticks_at_start: i64,
6-
ticks_per_micro: i64,
7+
static TICKS_AT_START: AtomicI64 = AtomicI64::new(0);
8+
static TICKS_PER_MICRO: AtomicI64 = AtomicI64::new(0);
9+
static INITIALIZED: AtomicBool = AtomicBool::new(false);
10+
11+
pub struct Timer {}
12+
13+
fn rdtsc() -> i64 {
14+
// SAFETY: modern x86 CPUs have this instruction.
15+
unsafe { _rdtsc() as i64 }
716
}
817

918
impl Timer {
10-
fn rdtsc() -> i64 {
11-
// SAFETY: modern x86 CPUs have this instruction.
12-
unsafe { _rdtsc() as i64 }
13-
}
14-
15-
pub fn new() -> Timer {
19+
pub(super) fn ensure_init() {
20+
if INITIALIZED.load(Ordering::Relaxed) {
21+
return;
22+
}
1623
// Read timer clock & wait to stabilize the counter.
17-
Self::rdtsc();
24+
rdtsc();
1825
uefi::boot::stall(20000);
19-
let tsc_before = Self::rdtsc();
26+
let tsc_before = rdtsc();
2027
uefi::boot::stall(20000);
21-
let tsc_after = Self::rdtsc();
28+
let tsc_after = rdtsc();
2229

23-
Timer {
24-
ticks_at_start: tsc_after,
25-
// TICKS_PER_MICRO is a multiple of 10 on every reasonable system.
26-
ticks_per_micro: (tsc_after - tsc_before) / (20000 * 10) * 10,
27-
}
28-
}
29-
30-
pub fn micros(&self) -> i64 {
31-
(Self::rdtsc() - self.ticks_at_start) / self.ticks_per_micro
30+
TICKS_AT_START.store(tsc_after, Ordering::Relaxed);
31+
// TICKS_PER_MICRO is a multiple of 10 on every reasonable system.
32+
TICKS_PER_MICRO.store(
33+
(tsc_after - tsc_before) / (20000 * 10) * 10,
34+
Ordering::Relaxed,
35+
);
36+
INITIALIZED.store(true, Ordering::Relaxed);
3237
}
3338

34-
pub fn instant(&self) -> Instant {
35-
Instant::from_micros(self.micros())
39+
pub fn micros() -> i64 {
40+
Self::ensure_init();
41+
let ticks_at_start = TICKS_AT_START.load(Ordering::Relaxed);
42+
let ticks_per_micro = TICKS_PER_MICRO.load(Ordering::Relaxed);
43+
(rdtsc() - ticks_at_start) / ticks_per_micro
3644
}
37-
}
3845

39-
impl Default for Timer {
40-
fn default() -> Self {
41-
Self::new()
46+
pub fn instant() -> Instant {
47+
Instant::from_micros(Timer::micros())
4248
}
4349
}

0 commit comments

Comments
 (0)