aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-08-06 16:31:34 -0400
committerBrian Cully <bjc@kublai.com>2019-08-06 16:31:34 -0400
commit392239c7f522acb7ca5847a48dd9ab2480242924 (patch)
treeb02f1f568085ae1dcb3c33c780d49a8d1a77a2eb
parentb0c6c4f9a45cf2b965acd3d10499e9df54929b36 (diff)
downloadclint-392239c7f522acb7ca5847a48dd9ab2480242924.tar.gz
clint-392239c7f522acb7ca5847a48dd9ab2480242924.zip
Add compatibilty with rust-stable.
* Add feature flag for const-fn functionality, which simplifies some things and lets this crate run on architectures where atomic CAS isn't available (e.g., thumbv6). * Remove `const fn` where necessary to compile under rust-stable. * BREAKING CHANGE - Change signature of `Handler::replace` to take a mutable borrow. This is required because the underlying type is now a NonNull, which needs `mut`. The old behavior was never desired, but a consequence of trying to avoid `Option` by using a default handler. * Use lazy_static crate for initialization of Handler/HandlerArray. * Specify Sync for Handler. This is not amazing, since it isn't, but it's necessary for initialization in static contexts inside `lazy_static`. This should be fine, because any actual manipulation of the handler is done in unsafe functions.
-rw-r--r--Cargo.lock45
-rw-r--r--Cargo.toml3
-rw-r--r--examples/dummy.rs11
-rw-r--r--examples/scope.rs7
-rw-r--r--src/array.rs23
-rw-r--r--src/handler.rs64
-rw-r--r--tests/compile-fail/handler.rs19
-rw-r--r--tests/tests.rs2
8 files changed, 131 insertions, 43 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cfcfe67..0b5518f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -77,6 +77,7 @@ dependencies = [
"compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cortex-m-rt 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -95,6 +96,7 @@ dependencies = [
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tester 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -185,6 +187,15 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "lazy_static"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -389,6 +400,25 @@ dependencies = [
]
[[package]]
+name = "term"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tester"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -436,6 +466,11 @@ dependencies = [
[[package]]
name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -444,6 +479,11 @@ dependencies = [
]
[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -474,6 +514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
"checksum getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "72327b15c228bfe31f1390f93dd5e9279587f0463836393c9df719ce62a3e450"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -501,6 +542,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum syn 0.15.33 (registry+https://github.com/rust-lang/crates.io-index)" = "ec52cd796e5f01d0067225a5392e70084acc4c0013fa71d55166d38a8b307836"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
+"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
+"checksum tester 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e812cb26c597f86a49b26dbb58b878bd2a2b4b93fc069dc39499228fe556ff6"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
@@ -509,6 +552,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum vcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45c297f0afb6928cd08ab1ff9d95e99392595ea25ae1b5ecf822ff8764e57a0d"
"checksum volatile-register 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d67cb4616d99b940db1d6bd28844ff97108b498a6ca850e5b6191a532063286"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 6d6f192..81c783b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,12 +14,13 @@ readme = "README.md"
cortex-m = "~0.6"
cortex-m-rt = "~0.6"
compiletest_rs = "~0.3"
+lazy_static = "~1.3"
[target.'cfg(all(target_arch = "arm", target_os = "none"))'.dependencies]
cortex-m = "~0.6"
[features]
-default = ["isr-32"]
+default = ["isr-32", "compiletest_rs/stable"]
const-fn = []
# Number of ISR closures to hold in a HandlerTable. This is pretty
diff --git a/examples/dummy.rs b/examples/dummy.rs
index 7e7c237..cfcd717 100644
--- a/examples/dummy.rs
+++ b/examples/dummy.rs
@@ -1,24 +1,29 @@
use clint::Handler;
+#[macro_use]
+extern crate lazy_static;
+
// Wrapper used to call through to `example_handler` via `closure` in
// `main`. `Handler::new()` places a do-nothing handler in this at
// compile-time, in case the interrupt using this handler is fired
// before being `replace`d in `main`.
-static mut HANDLER: Handler = Handler::new();
+lazy_static! {
+ static ref HANDLER: Handler<'static> = Handler::new();
+}
fn main() {
let mut x: u32 = 0;
// Create a closure to take a mutable reference to `x` for use in
// `example_handler`.
- let closure = move || example_handler(&mut x);
+ let mut closure = move || example_handler(&mut x);
// Swap out the do-nothing handler with our closure that calls
// through to `example_handler`. Ideally, the interrupt which uses
// this handler would be disabled while this happens, but as this
// is a demo, and there aren't any actual interrupts firing, this
// is left as an exercise to the reader.
- unsafe { HANDLER.replace(&closure) };
+ unsafe { HANDLER.replace(&mut closure) };
// Simulate firing the interrupt.
dummy_interrupt();
diff --git a/examples/scope.rs b/examples/scope.rs
index cd17570..8df0702 100644
--- a/examples/scope.rs
+++ b/examples/scope.rs
@@ -1,6 +1,11 @@
use clint::HandlerArray;
-static HANDLERS: HandlerArray = HandlerArray::new();
+#[macro_use]
+extern crate lazy_static;
+
+lazy_static! {
+ static ref HANDLERS: HandlerArray<'static> = HandlerArray::new();
+}
fn main() {
let mut cl = || println!("whoa!");
diff --git a/src/array.rs b/src/array.rs
index e01fe74..d460824 100644
--- a/src/array.rs
+++ b/src/array.rs
@@ -18,7 +18,12 @@
//! use clint::HandlerArray;
//! use cortex_m_rt::exception;
//!
-//! static HANDLERS: HandlerArray = HandlerArray::new();
+//! #[macro_use]
+//! extern crate lazy_static;
+//!
+//! lazy_static! {
+//! static ref HANDLERS: HandlerArray<'static> = HandlerArray::new();
+//! }
//!
//! fn main() {
//! // NB: This closure has to be created outside of `with_overrides` to
@@ -75,12 +80,28 @@ pub struct HandlerArray<'a> {
impl<'a> HandlerArray<'a> {
/// Create a new `HandlerArray` filled with no-op handlers.
+ #[cfg(feature = "const-fn")]
pub const fn new() -> Self {
Self {
h: UnsafeCell::new([Handler::new(); NR_ISR]),
}
}
+ #[cfg(not(feature = "const-fn"))]
+ pub fn new() -> Self {
+ let h = {
+ let mut ui_h: [core::mem::MaybeUninit<Handler>; NR_ISR] =
+ unsafe { core::mem::MaybeUninit::uninit().assume_init() };
+ for h in &mut ui_h[..] {
+ unsafe { core::ptr::write(h.as_mut_ptr(), Handler::new()) }
+ }
+ unsafe { core::mem::transmute(ui_h) }
+ };
+ Self {
+ h: UnsafeCell::new(h),
+ }
+ }
+
/// Register `f` for entry `nr` in this array using the default
/// critical section locker.
pub fn register<F>(&self, nr: usize, f: &'a mut F)
diff --git a/src/handler.rs b/src/handler.rs
index 545e622..1087b21 100644
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -56,18 +56,23 @@
//! use clint::Handler;
//! use cortex_m_rt::exception;
//!
-//! static mut SYSTICK_HANDLER: Handler = Handler::new();
+//! #[macro_use]
+//! extern crate lazy_static;
+//!
+//! lazy_static! {
+//! static ref SYSTICK_HANDLER: Handler<'static> = Handler::new();
+//! }
//!
//! fn main() {
//! // NB: `closure` is in the lexical scope of `main`, and thus
//! // cannot go out of scope.
-//! let closure = || {
+//! let mut closure = || {
//! // Your interrupt handling code.
//! };
//! // Replace the handler for SysTick with closure while interrupts are
//! // disabled.
//! cortex_m::interrupt::free(|_| {
-//! unsafe { SYSTICK_HANDLER.replace(&closure) };
+//! unsafe { SYSTICK_HANDLER.replace(&mut closure) };
//! });
//!
//! loop {
@@ -81,34 +86,37 @@
//! }
//! ```
#[cfg(not(feature = "const-fn"))]
+use core::cell::UnsafeCell;
+#[cfg(not(feature = "const-fn"))]
use core::ptr::NonNull;
#[cfg(feature = "const-fn")]
pub struct Handler<'a> {
// Handler that will be executed on `call`.
- h: *const dyn FnMut(),
+ h: *mut dyn FnMut(),
lifetime: core::marker::PhantomData<&'a dyn FnMut()>,
}
#[cfg(not(feature = "const-fn"))]
pub struct Handler<'a> {
// Handler that will be executed on `call`.
- h: Option<NonNull<dyn FnMut() + 'a>>,
+ h: UnsafeCell<Option<NonNull<dyn FnMut() + 'a>>>,
}
impl<'a> Handler<'a> {
/// Returns a new Handler that initially does nothing when
/// called. Override its behavior by using `replace`.
+ #[cfg(feature = "const-fn")]
pub const fn new() -> Self {
- #[cfg(feature = "const-fn")]
- {
- Self {
- h: &Self::default_handler,
- lifetime: core::marker::PhantomData,
- }
+ Self {
+ h: &Self::default_handler,
+ lifetime: core::marker::PhantomData,
}
- #[cfg(not(feature = "const-fn"))]
- {
- Self { h: None }
+ }
+
+ #[cfg(not(feature = "const-fn"))]
+ pub fn new() -> Self {
+ Self {
+ h: UnsafeCell::new(None),
}
}
@@ -119,7 +127,7 @@ impl<'a> Handler<'a> {
/// There is no exclusion on replacing the handler's behavior
/// while it is being executed. It is your responsibility to make
/// sure that it's not being executed when you call `replace`.
- pub unsafe fn replace(&mut self, f: &(dyn FnMut() + Send + 'a)) {
+ pub unsafe fn replace(&self, f: &mut (dyn FnMut() + Send + 'a)) {
#[cfg(feature = "const-fn")]
{
self.h = core::mem::transmute::<_, &'a _>(f);
@@ -128,7 +136,7 @@ impl<'a> Handler<'a> {
{
// let ptr: *mut dyn FnMut() = core::mem::transmute::<_, &'a _>(f);
// self.h = Some(NonNull::new(ptr));
- self.h = Some(NonNull::new_unchecked(f));
+ *self.h.get() = Some(NonNull::new_unchecked(f));
}
}
@@ -147,7 +155,8 @@ impl<'a> Handler<'a> {
}
#[cfg(not(feature = "const-fn"))]
{
- self.h.map(|mut f| (f.as_mut())());
+ let h: Option<NonNull<dyn FnMut()>> = *self.h.get();
+ h.map(|mut f| (f.as_mut())());
}
}
@@ -159,29 +168,24 @@ impl<'a> Handler<'a> {
impl<'a> core::fmt::Debug for Handler<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- let (f0, f1) = unsafe { core::mem::transmute::<_, (usize, usize)>(self.h) };
+ let (f0, f1) = unsafe { core::mem::transmute::<_, (usize, usize)>(*self.h.get()) };
write!(f, "Handler{{ h: (0x{:x}, 0x{:x}) }}", f0, f1)
}
}
-// FIXME: This probably shouldn't be Copy/Clone, but it needs to be in
-// order for array initialization to work with [Handler::new(); 32].
-impl<'a> core::marker::Copy for Handler<'a> {}
-impl<'a> core::clone::Clone for Handler<'a> {
- fn clone(&self) -> Self {
- *self
- }
-}
+unsafe impl Sync for Handler<'_> {}
#[cfg(test)]
mod test {
use super::*;
+ use lazy_static::*;
+
#[test]
fn replace() {
static mut X: usize = 0;
- let mut handler = Handler::new();
+ let handler = Handler::new();
unsafe {
handler.replace(&mut || X += 1);
assert_eq!(X, 0);
@@ -193,7 +197,9 @@ mod test {
#[test]
fn replace_static() {
- static mut HANDLER: Handler = Handler::new();
+ lazy_static! {
+ static ref HANDLER: Handler<'static> = Handler::new();
+ }
static mut X: usize = 0;
unsafe {
@@ -207,7 +213,7 @@ mod test {
#[test]
fn replace_with_default() {
- let mut handler = Handler::new();
+ let handler = Handler::new();
unsafe {
handler.replace(&mut Handler::default_handler);
handler.call()
diff --git a/tests/compile-fail/handler.rs b/tests/compile-fail/handler.rs
index fdc464a..64ab961 100644
--- a/tests/compile-fail/handler.rs
+++ b/tests/compile-fail/handler.rs
@@ -1,8 +1,13 @@
extern crate clint;
+#[macro_use]
+extern crate lazy_static;
+
use clint::Handler;
-static mut HANDLER: Handler = Handler::new();
+lazy_static! {
+ static ref HANDLER: Handler<'static> = Handler::new();
+}
fn main() {
need_move();
@@ -12,11 +17,11 @@ fn main() {
fn need_move() {
let x = vec![1, 2, 3];
- let c = || {
+ let mut c = || {
println!("x(h-c): {:?}", x); //~ ERROR does not live long enough
};
unsafe {
- HANDLER.replace(&c);
+ HANDLER.replace(&mut c);
HANDLER.call();
HANDLER.call();
}
@@ -25,11 +30,11 @@ fn need_move() {
fn borrow_error() {
let x = vec![1, 2, 3];
- let c = move || {
+ let mut c = move || {
println!("x(h-c): {:?}", x);
};
unsafe {
- HANDLER.replace(&c);
+ HANDLER.replace(&mut c);
HANDLER.call();
HANDLER.call();
}
@@ -38,11 +43,11 @@ fn borrow_error() {
fn no_borrow_needed() {
let x = vec![1, 2, 3];
- let c = || {
+ let mut c = || {
println!("x(h-c): hi!");
};
unsafe {
- HANDLER.replace(&c);
+ HANDLER.replace(&mut c);
HANDLER.call();
HANDLER.call();
}
diff --git a/tests/tests.rs b/tests/tests.rs
index c295c5a..eedb4b0 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -5,7 +5,7 @@ fn run_mode(mode: &'static str) {
config.mode = mode.parse().expect("invalid mode");
config.src_base = PathBuf::from(format!("tests/{}", mode));
- config.target_rustcflags = Some("-L target/debug".to_string());
+ config.target_rustcflags = Some("-L target/debug/deps".to_string());
config.clean_rmeta();
compiletest_rs::run_tests(&config);