Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defmt_rtt can panic on multicore #637

Closed
jannic opened this issue Nov 25, 2021 · 6 comments
Closed

defmt_rtt can panic on multicore #637

jannic opened this issue Nov 25, 2021 · 6 comments
Labels
type: enhancement Enhancement or feature request

Comments

@jannic
Copy link
Contributor

jannic commented Nov 25, 2021

The code at

if TAKEN.load(Ordering::Relaxed) {
panic!("defmt logger taken reentrantly")
}
is not multi-core safe: If two cores both try to acquire the lock, the second one will panic.

@Dirbaio
Copy link
Contributor

Dirbaio commented Nov 26, 2021

defmt-rtt assumes singlecore, it uses interrupt::disable() like cortex_m::interrupt::free().

You'd have to change it to use a custom critical section for your chip (RP2040 I guess?). I have a version of defmt-rtt that uses critical-section here, together with the impl here rp-rs/rp-hal#151 it should work.

Perhaps changing defmt-rtt to use critical-section would be a welcome addition to upstream defmt-rtt?

@jannic
Copy link
Contributor Author

jannic commented Nov 26, 2021

Ok, that makes sense. However I wonder why TAKEN is an atomic, if it's only used on single core while interrupts are disabled.

Yes, my use case is rp2040, how did you guess? :-)

@jonathanpallant
Copy link
Contributor

Can defmt be generic over some type T: DefmtLock? You can have a default implementation for systems with atomic values, and a user can substitute in an implementation that uses a stronger lock (e.g. RP2040 has spin-locks) without having to fork the code.

@jannic
Copy link
Contributor Author

jannic commented Nov 26, 2021

If defmt-rtt used critical-section like in the version @Dirbaio mentioned, individual firmwares could replace the actual implementation using the custom-impl feature of critical-section. It would not be necessary for defmt-rtt to directly support different implementations.
Not sure if the additional dependency is justified, though.

@Dirbaio
Copy link
Contributor

Dirbaio commented Nov 26, 2021

@jannic Ok, that makes sense. However I wonder why TAKEN is an atomic, if it's only used on single core while interrupts are disabled.

I think it could be a static mut as well, but relaxed atomics require less unsafe and have no extra overhead.

@jonathanpallant Can defmt be generic over some type T: DefmtLock?

Unfortunately the Logger is global, it can't have generics. defmt-rtt could offer some macro for you to set your own lock impl, but then the UX is the same as critical-section.

@Urhengulas Urhengulas added the type: enhancement Enhancement or feature request label Dec 1, 2021
bors bot added a commit that referenced this issue Feb 10, 2022
640: use crate critical-section in defmt-rtt r=jonas-schievink a=jannic

As an example how #637 could be solved, I changed defmt-rtt to use https://github.com/embassy-rs/critical-section.
Together with the implementation from https://github.com/9names/rp-hal/blob/critical_section/rp2040-hal/src/critical_section_impl.rs, I was able to run `loop { info!("A!"); }` and `loop { info!("B!"); }` on the two cores of an RP2040 concurrently, getting the desired output:

```
INFO  A!
└─ rp2040_project_template::__cortex_m_rt_main @ src/main.rs:66
INFO  B!
└─ rp2040_project_template::test @ src/main.rs:104
INFO  A!
└─ rp2040_project_template::__cortex_m_rt_main @ src/main.rs:66
INFO  B!
[...]
```

With the original defmt-rtt implementation, one of the cores panics immediately.

Co-authored-by: Jan Niehusmann <jan@gondor.com>
@jannic
Copy link
Contributor Author

jannic commented Feb 10, 2022

Fixed by #640

@jannic jannic closed this as completed Feb 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement Enhancement or feature request
Projects
None yet
Development

No branches or pull requests

4 participants