@@ -7,6 +7,97 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
8
8
## [ Unreleased]
9
9
10
+ ## [ v0.2.6] - 2017-05-08
11
+
12
+ ### Fixed
13
+
14
+ - [ breaking-change] . MEMORY UNSAFETY. ` Mutex ` could be used as a channel to send
15
+ interrupt tokens from one interrupt to other thus breaking the context ` Local `
16
+ abstraction. See reproduction case below. This has been fixed by making
17
+ ` Mutex ` ` Sync ` only if the protected data is ` Send ` .
18
+
19
+ ``` rust
20
+ #![feature(const_fn)]
21
+ #![feature(used)]
22
+ #![no_std]
23
+
24
+ extern crate cortex_m;
25
+ extern crate cortex_m_rt;
26
+ extern crate stm32f30x;
27
+
28
+ use core :: cell :: RefCell ;
29
+
30
+ use cortex_m :: ctxt :: Local ;
31
+ use cortex_m :: interrupt :: Mutex ;
32
+ use stm32f30x :: interrupt :: {self , Exti0 , Exti1 };
33
+
34
+ fn main () {
35
+ // ..
36
+
37
+ // trigger exti0
38
+ // then trigger exti0 again
39
+ }
40
+
41
+ static CHANNEL : Mutex <RefCell <Option <Exti0 >>> = Mutex :: new (RefCell :: new (None ));
42
+ // Supposedly task *local* data
43
+ static LOCAL : Local <i32 , Exti0 > = Local :: new (0 );
44
+
45
+ extern " C" fn exti0 (mut ctxt : Exti0 ) {
46
+ static FIRST : Local <bool , Exti0 > = Local :: new (true );
47
+
48
+ let first = * FIRST . borrow (& ctxt );
49
+
50
+ // toggle
51
+ if first {
52
+ * FIRST . borrow_mut (& mut ctxt ) = false ;
53
+ }
54
+
55
+ if first {
56
+ cortex_m :: interrupt :: free (
57
+ | cs | {
58
+ let channel = CHANNEL . borrow (cs );
59
+
60
+ // BAD: transfer interrupt token to another interrupt
61
+ * channel . borrow_mut () = Some (ctxt );
62
+ },
63
+ );
64
+
65
+ return ;
66
+ }
67
+ let _local = LOCAL . borrow_mut (& mut ctxt );
68
+
69
+ // ..
70
+
71
+ // trigger exti1 here
72
+
73
+ // ..
74
+
75
+ // `LOCAL` mutably borrowed up to this point
76
+ }
77
+
78
+ extern " C" fn exti1 (_ctxt : Exti1 ) {
79
+ cortex_m :: interrupt :: free (| cs | {
80
+ let channel = CHANNEL . borrow (cs );
81
+ let mut channel = channel . borrow_mut ();
82
+
83
+ if let Some (mut other_task ) = channel . take () {
84
+ // BAD: `exti1` has access to `exti0`'s interrupt token
85
+ // so it can now mutably access local while `exti0` is also using it
86
+ let _local = LOCAL . borrow_mut (& mut other_task );
87
+ }
88
+ });
89
+ }
90
+
91
+ #[allow(dead_code)]
92
+ #[used]
93
+ #[link_section = " .rodata.interrupts" ]
94
+ static INTERRUPTS : interrupt :: Handlers = interrupt :: Handlers {
95
+ Exti0 : exti0 ,
96
+ Exti1 : exti1 ,
97
+ .. interrupt :: DEFAULT_HANDLERS
98
+ };
99
+ ```
100
+
10
101
## [ v0.2.5] - 2017-05-07
11
102
12
103
### Added
@@ -15,17 +106,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
15
106
16
107
### Fixed
17
108
18
- - MEMORY SAFETY . ` interrupt::enable ` was safe to call inside an
19
- ` interrupt::free ` critical section thus breaking the preemption protection.
20
- The ` interrupt::enable ` method is now ` unsafe ` .
109
+ - [ breaking-change ] . MEMORY UNSAFETY . ` interrupt::enable ` was safe to call
110
+ inside an ` interrupt::free ` critical section thus breaking the preemption
111
+ protection. The ` interrupt::enable ` method is now ` unsafe ` .
21
112
22
113
## [ v0.2.4] - 2017-04-20 - YANKED
23
114
24
115
### Fixed
25
116
26
- - MEMORY SAFETY. ` interrupt::free ` leaked the critical section making it
27
- possible to access a ` Mutex ` when interrupts are enabled (see below). This has
28
- been fixed by changing the signature of ` interrupt::free ` .
117
+ - [ breaking-change] . MEMORY UNSAFETY. ` interrupt::free ` leaked the critical
118
+ section making it possible to access a ` Mutex ` when interrupts are enabled
119
+ (see below). This has been fixed by changing the signature of
120
+ ` interrupt::free ` .
29
121
30
122
``` rust
31
123
static FOO : Mutex <bool > = Mutex :: new (false );
@@ -41,18 +133,18 @@ fn main() {
41
133
42
134
### Fixed
43
135
44
- - MEMORY SAFETY . Some concurrency models that use "partial" critical sections
45
- (cf. BASEPRI) can be broken by changing the priority of interrupts or by
46
- changing BASEPRI in some scenarios. For this reason ` NVIC.set_priority ` and
47
- ` register::basepri::write ` are now ` unsafe ` .
136
+ - [ breaking-change ] . MEMORY UNSAFETY . Some concurrency models that use "partial"
137
+ critical sections (cf. BASEPRI) can be broken by changing the priority of
138
+ interrupts or by changing BASEPRI in some scenarios. For this reason
139
+ ` NVIC.set_priority ` and ` register::basepri::write ` are now ` unsafe ` .
48
140
49
141
## [ v0.2.2] - 2017-04-08 - YANKED
50
142
51
143
### Fixed
52
144
53
- - MEMORY SAFETY BUG . The ` Mutex.borrow_mut ` method has been removed as it can be
54
- used to bypass Rust's borrow checker and get, for example, two mutable
55
- references to the same data.
145
+ - [ breaking-change ] . MEMORY UNSAFETY . The ` Mutex.borrow_mut ` method has been
146
+ removed as it can be used to bypass Rust's borrow checker and get, for
147
+ example, two mutable references to the same data.
56
148
57
149
``` rust
58
150
static FOO : Mutex <bool > = Mutex :: new (false );
0 commit comments