Skip to content

Commit eee9840

Browse files
committed
fc_util: some refactoring
1. Move time related functions to a separate module. 2. Create a new module called rand and move rand related functionality like `xor_rng_u32` there. Signed-off-by: Diana Popa <[email protected]>
1 parent cac25cf commit eee9840

File tree

12 files changed

+256
-242
lines changed

12 files changed

+256
-242
lines changed

api_server/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,16 +196,17 @@ impl ApiServer {
196196
let listener = UnixListener::bind(path, &handle).map_err(Error::Io)?;
197197

198198
if let Some(start_time) = start_time_us {
199-
let delta_us = (fc_util::get_time(fc_util::ClockType::Monotonic) / 1000) - start_time;
199+
let delta_us =
200+
(fc_util::time::get_time(fc_util::time::ClockType::Monotonic) / 1000) - start_time;
200201
METRICS
201202
.api_server
202203
.process_startup_time_us
203204
.add(delta_us as usize);
204205
}
205206

206207
if let Some(cpu_start_time) = start_time_cpu_us {
207-
let delta_us =
208-
fc_util::get_time(fc_util::ClockType::ProcessCpu) / 1000 - cpu_start_time;
208+
let delta_us = fc_util::time::get_time(fc_util::time::ClockType::ProcessCpu) / 1000
209+
- cpu_start_time;
209210
METRICS
210211
.api_server
211212
.process_startup_time_cpu_us

devices/src/legacy/rtc_pl031.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl RTC {
7777
RTC {
7878
// This is used only for duration measuring purposes.
7979
previous_now: Instant::now(),
80-
tick_offset: fc_util::get_time(fc_util::ClockType::Real) as i64,
80+
tick_offset: fc_util::time::get_time(fc_util::time::ClockType::Real) as i64,
8181
match_value: 0,
8282
load: 0,
8383
imsc: 0,
@@ -93,7 +93,7 @@ impl RTC {
9393
fn get_time(&self) -> u32 {
9494
let ts = (self.tick_offset as i128)
9595
+ (Instant::now().duration_since(self.previous_now).as_nanos() as i128);
96-
(ts / fc_util::NANOS_PER_SECOND as i128) as u32
96+
(ts / fc_util::time::NANOS_PER_SECOND as i128) as u32
9797
}
9898

9999
fn handle_write(&mut self, offset: u64, val: u32) -> Result<()> {
@@ -112,7 +112,7 @@ impl RTC {
112112
self.previous_now = Instant::now();
113113
// If the unwrap fails, then the internal value of the clock has been corrupted and
114114
// we want to terminate the execution of the process.
115-
self.tick_offset = fc_util::seconds_to_nanoseconds(i64::from(val)).unwrap();
115+
self.tick_offset = fc_util::time::seconds_to_nanoseconds(i64::from(val)).unwrap();
116116
}
117117
RTCIMSC => {
118118
self.imsc = val & 1;
@@ -207,8 +207,8 @@ mod tests {
207207
assert_eq!(v, 123);
208208

209209
// Read and write to the LR register.
210-
let v = fc_util::get_time(fc_util::ClockType::Real);
211-
LittleEndian::write_u32(&mut data, (v / fc_util::NANOS_PER_SECOND) as u32);
210+
let v = fc_util::time::get_time(fc_util::time::ClockType::Real);
211+
LittleEndian::write_u32(&mut data, (v / fc_util::time::NANOS_PER_SECOND) as u32);
212212
let tick_offset_before = rtc.tick_offset;
213213
let previous_now_before = rtc.previous_now;
214214
rtc.write(RTCLR, &mut data);
@@ -217,7 +217,7 @@ mod tests {
217217

218218
rtc.read(RTCLR, &mut data);
219219
let v_read = LittleEndian::read_u32(&data);
220-
assert_eq!((v / fc_util::NANOS_PER_SECOND) as u32, v_read);
220+
assert_eq!((v / fc_util::time::NANOS_PER_SECOND) as u32, v_read);
221221

222222
// Read and write to IMSC register.
223223
// Test with non zero value.

dumbo/src/ns.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::net::Ipv4Addr;
99
use std::num::NonZeroUsize;
1010
use std::result::Result;
1111

12-
use fc_util::timestamp_cycles;
12+
use fc_util::time::timestamp_cycles;
1313
use logger::{Metric, METRICS};
1414
use net_util::MacAddr;
1515
use pdu::arp::{test_speculative_tpa, Error as ArpFrameError, EthIPv4ArpFrame, ETH_IPV4_FRAME_LEN};

dumbo/src/tcp/connection.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
use std::num::{NonZeroU16, NonZeroU64, NonZeroUsize, Wrapping};
1010

11-
use fc_util::timestamp_cycles;
11+
use fc_util::rand::xor_rng_u32;
1212
use pdu::bytes::NetworkBytes;
1313
use pdu::tcp::{Error as TcpSegmentError, Flags as TcpFlags, TcpSegment};
1414
use pdu::Incomplete;
@@ -112,16 +112,6 @@ pub enum WriteNextError {
112112
TcpSegment(TcpSegmentError),
113113
}
114114

115-
// This generates pseudo random u32 numbers based on the current timestamp. Only works for x86_64,
116-
// but can find something else if we ever need to support different architectures.
117-
fn xor_rng_u32() -> u32 {
118-
let mut t: u32 = timestamp_cycles() as u32;
119-
// Taken from https://en.wikipedia.org/wiki/Xorshift
120-
t ^= t << 13;
121-
t ^= t >> 17;
122-
t ^ (t << 5)
123-
}
124-
125115
/// Contains the state information and implements the logic for a minimalist TCP connection.
126116
///
127117
/// One particular thing is that whenever the connection sends a `RST` segment, it will also stop
@@ -1784,11 +1774,4 @@ pub(crate) mod tests {
17841774
// and we don't wait for our FIN to be ACKed.
17851775
assert!(c.is_done());
17861776
}
1787-
1788-
#[test]
1789-
fn test_xor_rng_u32() {
1790-
for _ in 0..1000 {
1791-
assert_ne!(xor_rng_u32(), xor_rng_u32());
1792-
}
1793-
}
17941777
}

dumbo/src/tcp/endpoint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use std::num::{NonZeroU16, NonZeroU64, Wrapping};
1515

16-
use fc_util::timestamp_cycles;
16+
use fc_util::time::timestamp_cycles;
1717
use logger::{Metric, METRICS};
1818
use mmds::parse_request;
1919
use pdu::bytes::NetworkBytes;

fc_util/src/lib.rs

Lines changed: 2 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -3,211 +3,6 @@
33

44
extern crate libc;
55

6-
use std::fmt;
7-
6+
pub mod rand;
7+
pub mod time;
88
pub mod validators;
9-
10-
/// Constant to convert seconds to nanoseconds.
11-
pub const NANOS_PER_SECOND: u64 = 1_000_000_000;
12-
13-
/// Wrapper over `libc::clockid_t` to specify Linux Kernel clock source.
14-
pub enum ClockType {
15-
/// Equivalent to `libc::CLOCK_MONOTONIC`.
16-
Monotonic,
17-
/// Equivalent to `libc::CLOCK_REALTIME`.
18-
Real,
19-
/// Equivalent to `libc::CLOCK_PROCESS_CPUTIME_ID`.
20-
ProcessCpu,
21-
/// Equivalent to `libc::CLOCK_THREAD_CPUTIME_ID`.
22-
ThreadCpu,
23-
}
24-
25-
impl Into<libc::clockid_t> for ClockType {
26-
fn into(self) -> libc::clockid_t {
27-
match self {
28-
ClockType::Monotonic => libc::CLOCK_MONOTONIC,
29-
ClockType::Real => libc::CLOCK_REALTIME,
30-
ClockType::ProcessCpu => libc::CLOCK_PROCESS_CPUTIME_ID,
31-
ClockType::ThreadCpu => libc::CLOCK_THREAD_CPUTIME_ID,
32-
}
33-
}
34-
}
35-
36-
/// Structure representing the date in local time with nanosecond precision.
37-
pub struct LocalTime {
38-
/// Seconds in current minute.
39-
sec: i32,
40-
/// Minutes in current hour.
41-
min: i32,
42-
/// Hours in current day, 24H format.
43-
hour: i32,
44-
/// Days in current month.
45-
mday: i32,
46-
/// Months in current year.
47-
mon: i32,
48-
/// Years passed since 1900 BC.
49-
year: i32,
50-
/// Nanoseconds in current second.
51-
nsec: i64,
52-
}
53-
54-
impl LocalTime {
55-
/// Returns the [LocalTime](struct.LocalTime.html) structure for the calling moment.
56-
pub fn now() -> LocalTime {
57-
let mut timespec = libc::timespec {
58-
tv_sec: 0,
59-
tv_nsec: 0,
60-
};
61-
let mut tm: libc::tm = libc::tm {
62-
tm_sec: 0,
63-
tm_min: 0,
64-
tm_hour: 0,
65-
tm_mday: 0,
66-
tm_mon: 0,
67-
tm_year: 0,
68-
tm_wday: 0,
69-
tm_yday: 0,
70-
tm_isdst: 0,
71-
tm_gmtoff: 0,
72-
tm_zone: std::ptr::null(),
73-
};
74-
75-
// Safe because the parameters are valid.
76-
unsafe {
77-
libc::clock_gettime(libc::CLOCK_REALTIME, &mut timespec);
78-
libc::localtime_r(&timespec.tv_sec, &mut tm);
79-
}
80-
81-
LocalTime {
82-
sec: tm.tm_sec,
83-
min: tm.tm_min,
84-
hour: tm.tm_hour,
85-
mday: tm.tm_mday,
86-
mon: tm.tm_mon,
87-
year: tm.tm_year,
88-
nsec: timespec.tv_nsec,
89-
}
90-
}
91-
}
92-
93-
impl fmt::Display for LocalTime {
94-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95-
write!(
96-
f,
97-
"{}-{:02}-{:02}T{:02}:{:02}:{:02}.{:09}",
98-
self.year + 1900,
99-
self.mon + 1,
100-
self.mday,
101-
self.hour,
102-
self.min,
103-
self.sec,
104-
self.nsec
105-
)
106-
}
107-
}
108-
109-
/// Returns a timestamp in nanoseconds from a monotonic clock.
110-
///
111-
/// Uses `_rdstc` on `x86_64` and [`get_time`](fn.get_time.html) on other architectures.
112-
pub fn timestamp_cycles() -> u64 {
113-
#[cfg(target_arch = "x86_64")]
114-
// Safe because there's nothing that can go wrong with this call.
115-
unsafe {
116-
std::arch::x86_64::_rdtsc() as u64
117-
}
118-
#[cfg(not(target_arch = "x86_64"))]
119-
{
120-
get_time(ClockType::Monotonic)
121-
}
122-
}
123-
124-
/// Returns a timestamp in nanoseconds based on the provided clock type.
125-
///
126-
/// # Arguments
127-
///
128-
/// * `clock_type` - Identifier of the Linux Kernel clock on which to act.
129-
pub fn get_time(clock_type: ClockType) -> u64 {
130-
let mut time_struct = libc::timespec {
131-
tv_sec: 0,
132-
tv_nsec: 0,
133-
};
134-
// Safe because the parameters are valid.
135-
unsafe { libc::clock_gettime(clock_type.into(), &mut time_struct) };
136-
seconds_to_nanoseconds(time_struct.tv_sec).unwrap() as u64 + (time_struct.tv_nsec as u64)
137-
}
138-
139-
/// Converts a timestamp in seconds to an equivalent one in nanoseconds.
140-
/// Returns `None` if the conversion overflows.
141-
///
142-
/// # Arguments
143-
///
144-
/// * `value` - Timestamp in seconds.
145-
pub fn seconds_to_nanoseconds(value: i64) -> Option<i64> {
146-
value.checked_mul(NANOS_PER_SECOND as i64)
147-
}
148-
149-
#[cfg(test)]
150-
mod tests {
151-
use super::*;
152-
153-
#[test]
154-
fn test_get_time() {
155-
for _ in 0..1000 {
156-
assert!(get_time(ClockType::Monotonic) <= get_time(ClockType::Monotonic));
157-
}
158-
159-
for _ in 0..1000 {
160-
assert!(get_time(ClockType::ProcessCpu) <= get_time(ClockType::ProcessCpu));
161-
}
162-
163-
for _ in 0..1000 {
164-
assert!(get_time(ClockType::ThreadCpu) <= get_time(ClockType::ThreadCpu));
165-
}
166-
167-
assert_ne!(get_time(ClockType::Real), 0);
168-
}
169-
170-
#[test]
171-
fn test_local_time_display() {
172-
let local_time = LocalTime {
173-
sec: 30,
174-
min: 15,
175-
hour: 10,
176-
mday: 4,
177-
mon: 6,
178-
year: 119,
179-
nsec: 123_456_789,
180-
};
181-
assert_eq!(
182-
String::from("2019-07-04T10:15:30.123456789"),
183-
local_time.to_string()
184-
);
185-
186-
let local_time = LocalTime {
187-
sec: 5,
188-
min: 5,
189-
hour: 5,
190-
mday: 23,
191-
mon: 7,
192-
year: 44,
193-
nsec: 123,
194-
};
195-
assert_eq!(
196-
String::from("1944-08-23T05:05:05.000000123"),
197-
local_time.to_string()
198-
);
199-
200-
let local_time = LocalTime::now();
201-
assert!(local_time.mon >= 0 && local_time.mon <= 11);
202-
}
203-
204-
#[test]
205-
fn test_seconds_to_nanoseconds() {
206-
assert_eq!(
207-
seconds_to_nanoseconds(100).unwrap() as u64,
208-
100 * NANOS_PER_SECOND
209-
);
210-
211-
assert!(seconds_to_nanoseconds(9_223_372_037).is_none());
212-
}
213-
}

fc_util/src/rand.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use super::time;
5+
6+
/// Generates pseudo random u32 numbers based on the current timestamp.
7+
pub fn xor_rng_u32() -> u32 {
8+
let mut t: u32 = time::timestamp_cycles() as u32;
9+
// Taken from https://en.wikipedia.org/wiki/Xorshift.
10+
t ^= t << 13;
11+
t ^= t >> 17;
12+
t ^ (t << 5)
13+
}
14+
15+
#[cfg(test)]
16+
mod tests {
17+
use super::*;
18+
19+
#[test]
20+
fn test_xor_rng_u32() {
21+
for _ in 0..1000 {
22+
assert_ne!(xor_rng_u32(), xor_rng_u32());
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)