Skip to content
This repository was archived by the owner on Jul 6, 2019. It is now read-only.

Commit caa9c29

Browse files
committed
volatile_cell replayer is now thread-safe
1 parent 58478b7 commit caa9c29

File tree

2 files changed

+66
-43
lines changed

2 files changed

+66
-43
lines changed

src/hal/lpc11xx/syscon.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,25 @@ mod test {
7878

7979
#[test]
8080
fn returns_isr_location() {
81-
let mut replayer = VolatileCellReplayer::new();
82-
set_replayer(&mut replayer);
81+
init_replayer!();
8382

84-
expect_volatile_read!(replayer, 0x4004_8000, 0b10);
83+
expect_volatile_read!(0x4004_8000, 0b10);
8584

8685
expect!(get_isr_location()).to(be_equal_to(ISRLocation::Flash));
8786

88-
expect_replayer_valid!(replayer);
87+
expect_replayer_valid!();
8988
}
9089

9190
#[test]
9291
fn sets_isr_location() {
93-
let mut replayer = VolatileCellReplayer::new();
94-
set_replayer(&mut replayer);
92+
init_replayer!();
93+
94+
expect_volatile_write!(0x4004_8000, 2);
9595

96-
expect_volatile_write!(replayer, 0x4004_8000, 0b00);
96+
set_isr_location(ISRLocation::Flash);
97+
98+
expect_replayer_valid!();
99+
}
97100

98101
set_isr_location(ISRLocation::Bootloader);
99102

@@ -102,33 +105,32 @@ mod test {
102105

103106
#[test]
104107
fn initialize_system_clock() {
105-
let mut replayer = VolatileCellReplayer::new();
106-
set_replayer(&mut replayer);
108+
init_replayer!();
107109

108110
// read PDRUNCFG, returns reset value
109-
expect_volatile_read!(replayer, 0x4004_8238, 0x0000_EDF0);
111+
expect_volatile_read!( 0x4004_8238, 0x0000_EDF0);
110112
// write PDRUNCFG, set SYSOSC_PD to POWERED
111-
expect_volatile_write!(replayer, 0x4004_8238, 0x0000_EDD0);
113+
expect_volatile_write!(0x4004_8238, 0x0000_EDD0);
112114

113115
// write SYSOSCCTRL, set BYPASS to off, FREQRANGE 1-20MHz
114-
expect_volatile_write!(replayer, 0x4004_8020, 0x0000_0000);
116+
expect_volatile_write!(0x4004_8020, 0x0000_0000);
115117

116118
// write SYSPLLCLKSEL, set SEL to system oscillator
117-
expect_volatile_write!(replayer, 0x4004_8040, 0x0000_0001);
119+
expect_volatile_write!(0x4004_8040, 0x0000_0001);
118120

119121
// write SYSPLLCLKUEN, set update/no change/update
120-
expect_volatile_write!(replayer, 0x4004_8044, 0x0000_0001);
121-
expect_volatile_write!(replayer, 0x4004_8044, 0x0000_0000);
122-
expect_volatile_write!(replayer, 0x4004_8044, 0x0000_0001);
122+
expect_volatile_write!(0x4004_8044, 0x0000_0001);
123+
expect_volatile_write!(0x4004_8044, 0x0000_0000);
124+
expect_volatile_write!(0x4004_8044, 0x0000_0001);
123125

124126
// poll-read SYSPLLCLKUEN until returns update
125-
expect_volatile_read!(replayer, 0x4004_8044, 0x0000_0000);
126-
expect_volatile_read!(replayer, 0x4004_8044, 0x0000_0000);
127-
expect_volatile_read!(replayer, 0x4004_8044, 0x0000_0000);
128-
expect_volatile_read!(replayer, 0x4004_8044, 0x0000_0001);
127+
expect_volatile_read!( 0x4004_8044, 0x0000_0000);
128+
expect_volatile_read!( 0x4004_8044, 0x0000_0000);
129+
expect_volatile_read!( 0x4004_8044, 0x0000_0000);
130+
expect_volatile_read!( 0x4004_8044, 0x0000_0001);
129131

130132
init_system_clock();
131133

132-
expect_replayer_valid!(replayer);
134+
expect_replayer_valid!();
133135
}
134136
}

volatile_cell/lib.rs

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern crate core;
2929
#[cfg(feature="replayer")] use std::fmt;
3030
#[cfg(feature="replayer")] use core::cmp::PartialEq;
3131
#[cfg(feature="replayer")] use core::clone::Clone;
32+
#[cfg(feature="replayer")] use core::cell::RefCell;
3233

3334
#[cfg(not(feature="replayer"))] use core::intrinsics::{volatile_load, volatile_store};
3435
#[cfg(feature="replayer")] use core::intrinsics::transmute;
@@ -72,13 +73,13 @@ impl<T> VolatileCell<T> {
7273
impl VolatileCell<u32> {
7374
pub fn get(&self) -> u32 {
7475
unsafe {
75-
(*GlobalReplayer).get_cell(transmute(&self.value))
76+
GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) })
7677
}
7778
}
7879

7980
pub fn set(&self, value: u32) {
8081
unsafe {
81-
(*GlobalReplayer).set_cell(transmute(&self.value), value)
82+
GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value) })
8283
}
8384
}
8485
}
@@ -87,13 +88,13 @@ impl VolatileCell<u32> {
8788
impl VolatileCell<u16> {
8889
pub fn get(&self) -> u16 {
8990
unsafe {
90-
(*GlobalReplayer).get_cell(transmute(&self.value)) as u16
91+
GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) }) as u16
9192
}
9293
}
9394

9495
pub fn set(&self, value: u16) {
9596
unsafe {
96-
(*GlobalReplayer).set_cell(transmute(&self.value), value as u32)
97+
GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value as u32) })
9798
}
9899
}
99100
}
@@ -102,13 +103,13 @@ impl VolatileCell<u16> {
102103
impl VolatileCell<u8> {
103104
pub fn get(&self) -> u8 {
104105
unsafe {
105-
(*GlobalReplayer).get_cell(transmute(&self.value)) as u8
106+
GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) }) as u8
106107
}
107108
}
108109

109110
pub fn set(&self, value: u8) {
110111
unsafe {
111-
(*GlobalReplayer).set_cell(transmute(&self.value), value as u32)
112+
GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value as u32) })
112113
}
113114
}
114115
}
@@ -234,13 +235,22 @@ impl VolatileCellReplayer {
234235
}
235236

236237
#[cfg(feature="replayer")]
237-
static mut GlobalReplayer: *mut VolatileCellReplayer = 0 as *mut VolatileCellReplayer;
238+
thread_local!(static GLOBAL_REPLAYER: RefCell<VolatileCellReplayer> = RefCell::new(VolatileCellReplayer::new()));
238239

239240
#[cfg(feature="replayer")]
240-
pub fn set_replayer(replayer: &mut VolatileCellReplayer) {
241-
unsafe {
242-
GlobalReplayer = replayer;
243-
}
241+
pub fn set_replayer(replayer: VolatileCellReplayer) {
242+
GLOBAL_REPLAYER.with(|gr| {
243+
let mut bm = gr.borrow_mut();
244+
*bm = replayer;
245+
});
246+
}
247+
248+
#[cfg(feature="replayer")]
249+
pub fn with_mut_replayer<F>(f: F) where F: core::ops::FnOnce(&mut VolatileCellReplayer) {
250+
GLOBAL_REPLAYER.with(|gr| {
251+
let mut bm = gr.borrow_mut();
252+
f(&mut *bm);
253+
});
244254
}
245255

246256
struct BeEqualToWithContext<E> {
@@ -271,23 +281,34 @@ impl<A, E> Matcher<A, E> for BeEqualToWithContext<E>
271281

272282
#[macro_export]
273283
macro_rules! expect_volatile_read {
274-
($replayer: ident, $addr: expr, $val: expr) => (
275-
$replayer.expect_read($addr, $val,
276-
expectest::core::SourceLocation::new(file!(), line!()))
277-
);
284+
($addr: expr, $val: expr) => (
285+
$crate::with_mut_replayer(|r| {
286+
r.expect_read($addr, $val, expectest::core::SourceLocation::new(file!(), line!()));
287+
})
288+
);
278289
}
279290

280291
#[macro_export]
281292
macro_rules! expect_volatile_write {
282-
($replayer: ident, $addr: expr, $val: expr) => (
283-
$replayer.expect_write($addr, $val,
284-
expectest::core::SourceLocation::new(file!(), line!()))
285-
);
293+
($addr: expr, $val: expr) => (
294+
$crate::with_mut_replayer(|r| {
295+
r.expect_write($addr, $val, expectest::core::SourceLocation::new(file!(), line!()));
296+
})
297+
);
286298
}
287299

288300
#[macro_export]
289301
macro_rules! expect_replayer_valid {
290-
($replayer: ident) => (
291-
$replayer.verify(expectest::core::SourceLocation::new(file!(), line!()))
292-
);
302+
() => (
303+
$crate::with_mut_replayer(|r| {
304+
r.verify(expectest::core::SourceLocation::new(file!(), line!()));
305+
})
306+
);
307+
}
308+
309+
#[macro_export]
310+
macro_rules! init_replayer {
311+
() => (
312+
set_replayer(VolatileCellReplayer::new());
313+
);
293314
}

0 commit comments

Comments
 (0)