Skip to content

Conversation

@ninehusky
Copy link

Pull Request Overview

Using the no_panic infrastructure we added to flux, this PR will assure that the following six drivers cannot panic:

  • button.rs
  • led.rs
  • console.rs
  • alarm.rs
  • spi_peripheral.rs
  • stream.rs

Testing Strategy

This won't be merged for a bit, but I want to track the extern specs that we add so it's not just one big blob at the very end.

@ninehusky
Copy link
Author

ninehusky commented Nov 19, 2025

A list of all external functions called (to be cleaned up later):

	<I as core::iter::IntoIterator>::into_iter: 10
	<T as core::convert::Into<U>>::into: 3
	<core::iter::Enumerate<I> as core::iter::Iterator>::next: 6
	<core::iter::Zip<A, B> as core::iter::Iterator>::next: 1
	<core::slice::Iter<'a, T> as core::iter::Iterator>::next: 1
	<kernel::ProcessId as core::cmp::PartialEq>::eq: 1
	<kernel::grant::GrantData<'a, T> as core::ops::Deref>::deref: 11
	<kernel::grant::GrantData<'a, T> as core::ops::DerefMut>::deref_mut: 18
	<kernel::grant::Iter<'a, T, Upcalls, AllowROs, AllowRWs> as core::iter::Iterator>::next: 1
	<kernel::hil::gpio::InterruptValueWrapper<'a, IP> as kernel::hil::gpio::Configure>::make_input: 1
	<kernel::hil::gpio::InterruptValueWrapper<'a, IP> as kernel::hil::gpio::Configure>::set_floating_state: 1
	<kernel::hil::gpio::InterruptValueWrapper<'a, IP> as kernel::hil::gpio::InterruptWithValue<'a>>::disable_interrupts: 2
	<kernel::hil::gpio::InterruptValueWrapper<'a, IP> as kernel::hil::gpio::InterruptWithValue<'a>>::enable_interrupts: 1
	<kernel::hil::gpio::InterruptValueWrapper<'a, IP> as kernel::hil::gpio::InterruptWithValue<'a>>::set_value: 1
	<kernel::processbuffer::ReadOnlyProcessBuffer as kernel::processbuffer::ReadableProcessBuffer>::enter: 2
	<kernel::processbuffer::ReadOnlyProcessBuffer as kernel::processbuffer::ReadableProcessBuffer>::len: 2
	<kernel::processbuffer::ReadOnlyProcessBufferRef<'_> as core::ops::Deref>::deref: 4
	<kernel::processbuffer::ReadWriteProcessBuffer as kernel::processbuffer::ReadableProcessBuffer>::len: 3
	<kernel::processbuffer::ReadWriteProcessBuffer as kernel::processbuffer::WriteableProcessBuffer>::mut_enter: 2
	<kernel::processbuffer::ReadWriteProcessBufferRef<'_> as core::ops::Deref>::deref: 5
	<kernel::processbuffer::ReadableProcessSlice as core::ops::Index<core::ops::Range<usize>>>::index: 1
	<kernel::processbuffer::WriteableProcessSlice as core::ops::Index<core::ops::Range<usize>>>::index: 1
	<kernel::processbuffer::WriteableProcessSlice as core::ops::Index<usize>>::index: 1
	core::cell::Cell::<T>::get: 6
	core::cell::Cell::<T>::new: 4
	core::cell::Cell::<T>::set: 7
	core::cmp::Ord::min: 3
	core::cmp::PartialOrd::lt: 1
	core::convert::From::from: 11
	core::iter::Iterator::enumerate: 6
	core::iter::Iterator::filter_map: 1
	core::iter::Iterator::next: 1
	core::iter::Iterator::rev: 2
	core::iter::Iterator::take: 1
	core::iter::Iterator::zip: 1
	core::ops::FnOnce::call_once: 1
	core::option::Option::<T>::inspect: 1
	core::option::Option::<T>::map: 4
	core::option::Option::<T>::map_or: 1
	core::option::Option::<T>::unwrap_or_default: 1
	core::panicking::panic: 1
	core::result::Result::<T, E>::and_then: 4
	core::result::Result::<T, E>::map_err: 1
	core::result::Result::<T, E>::map_or: 5
	core::result::Result::<T, E>::map_or_else: 1
	core::result::Result::<T, E>::ok: 8
	core::result::Result::<T, E>::unwrap_or: 5
	core::result::Result::<T, E>::unwrap_or_default: 1
	core::result::Result::<T, E>::unwrap_or_else: 2
	core::slice::<impl [T]>::copy_from_slice: 2
	core::slice::<impl [T]>::iter: 6
	core::slice::index::<impl core::ops::Index<I> for [T]>::index: 3
	core::slice::index::<impl core::ops::IndexMut<I> for [T]>::index_mut: 1
	kernel::errorcode::into_statuscode: 2
	kernel::grant::Grant::<T, Upcalls, AllowROs, AllowRWs>::each: 2
	kernel::grant::Grant::<T, Upcalls, AllowROs, AllowRWs>::enter: 15
	kernel::grant::Grant::<T, Upcalls, AllowROs, AllowRWs>::iter: 2
	kernel::grant::GrantKernelData::<'a>::get_readonly_processbuffer: 4
	kernel::grant::GrantKernelData::<'a>::get_readwrite_processbuffer: 5
	kernel::grant::GrantKernelData::<'a>::schedule_upcall: 8
	kernel::grant::ProcessGrant::<'a, T, Upcalls, AllowROs, AllowRWs>::enter: 2
	kernel::grant::ProcessGrant::<'a, T, Upcalls, AllowROs, AllowRWs>::processid: 2
	kernel::hil::gpio::Input::read_activation: 1
	kernel::hil::led::Led::init: 1
	kernel::hil::led::Led::off: 2
	kernel::hil::led::Led::on: 1
	kernel::hil::led::Led::toggle: 1
	kernel::hil::spi::SpiSlaveDevice::get_phase: 1
	kernel::hil::spi::SpiSlaveDevice::get_polarity: 1
	kernel::hil::spi::SpiSlaveDevice::read_write_bytes: 1
	kernel::hil::spi::SpiSlaveDevice::set_phase: 2
	kernel::hil::spi::SpiSlaveDevice::set_polarity: 2
	kernel::hil::time::Alarm::disarm: 1
	kernel::hil::time::Alarm::set_alarm: 1
	kernel::hil::time::Ticks::into_u32: 3
	kernel::hil::time::Ticks::into_u32_left_justified: 3
	kernel::hil::time::Ticks::into_usize: 1
	kernel::hil::time::Ticks::u32_left_justified_scale_freq: 1
	kernel::hil::time::Ticks::u32_padding: 4
	kernel::hil::time::Ticks::width: 1
	kernel::hil::time::Ticks::within_range: 1
	kernel::hil::time::Ticks::wrapping_add: 7
	kernel::hil::time::Ticks::wrapping_sub: 5
	kernel::hil::time::Time::now: 2
	kernel::hil::uart::Receive::receive_abort: 1
	kernel::hil::uart::Receive::receive_buffer: 1
	kernel::hil::uart::Transmit::transmit_buffer: 1
	kernel::processbuffer::ReadableProcessByte::get: 2
	kernel::processbuffer::ReadableProcessSlice::get: 1
	kernel::processbuffer::ReadableProcessSlice::iter: 2
	kernel::processbuffer::ReadableProcessSlice::len: 1
	kernel::processbuffer::WriteableProcessSlice::iter: 1
	kernel::processbuffer::WriteableProcessSlice::len: 1
	kernel::syscall::CommandReturn::failure: 23
	kernel::syscall::CommandReturn::success: 12
	kernel::syscall::CommandReturn::success_u32: 10
	kernel::utilities::cells::OptionalCell::<T>::clear: 1
	kernel::utilities::cells::OptionalCell::<T>::empty: 3
	kernel::utilities::cells::OptionalCell::<T>::is_none: 2
	kernel::utilities::cells::OptionalCell::<T>::is_some: 1
	kernel::utilities::cells::OptionalCell::<T>::map: 2
	kernel::utilities::cells::OptionalCell::<T>::map_or: 1
	kernel::utilities::cells::OptionalCell::<T>::set: 3
	kernel::utilities::cells::OptionalCell::<T>::take: 2
	kernel::utilities::cells::TakeCell::<'a, T>::empty: 2
	kernel::utilities::cells::TakeCell::<'a, T>::is_none: 1
	kernel::utilities::cells::TakeCell::<'a, T>::map_or: 2
	kernel::utilities::cells::TakeCell::<'a, T>::new: 2
	kernel::utilities::cells::TakeCell::<'a, T>::put: 2
	kernel::utilities::cells::TakeCell::<'a, T>::replace: 6
	kernel::utilities::cells::TakeCell::<'a, T>::take: 4

Just core-touching:

	<I as core::iter::IntoIterator>::into_iter: 10
	<T as core::convert::Into<U>>::into: 3
	<core::iter::Enumerate<I> as core::iter::Iterator>::next: 6
	<core::iter::Zip<A, B> as core::iter::Iterator>::next: 1
	<core::slice::Iter<'a, T> as core::iter::Iterator>::next: 1
	<kernel::ProcessId as core::cmp::PartialEq>::eq: 1
	<kernel::grant::GrantData<'a, T> as core::ops::Deref>::deref: 11
	<kernel::grant::GrantData<'a, T> as core::ops::DerefMut>::deref_mut: 18
	<kernel::grant::Iter<'a, T, Upcalls, AllowROs, AllowRWs> as core::iter::Iterator>::next: 1
	<kernel::processbuffer::ReadOnlyProcessBufferRef<'_> as core::ops::Deref>::deref: 4
	<kernel::processbuffer::ReadWriteProcessBufferRef<'_> as core::ops::Deref>::deref: 5
	<kernel::processbuffer::ReadableProcessSlice as core::ops::Index<core::ops::Range<usize>>>::index: 1
	<kernel::processbuffer::WriteableProcessSlice as core::ops::Index<core::ops::Range<usize>>>::index: 1
	<kernel::processbuffer::WriteableProcessSlice as core::ops::Index<usize>>::index: 1
	core::cell::Cell::<T>::get: 6
	core::cell::Cell::<T>::new: 4
	core::cell::Cell::<T>::set: 7
	core::cmp::Ord::min: 3
	core::cmp::PartialOrd::lt: 1
	core::convert::From::from: 11
	core::iter::Iterator::enumerate: 6
	core::iter::Iterator::filter_map: 1
	core::iter::Iterator::next: 1
	core::iter::Iterator::rev: 2
	core::iter::Iterator::take: 1
	core::iter::Iterator::zip: 1
	core::ops::FnOnce::call_once: 1
	core::option::Option::<T>::inspect: 1
	core::option::Option::<T>::map: 4
	core::option::Option::<T>::map_or: 1
	core::option::Option::<T>::unwrap_or_default: 1
	core::panicking::panic: 1
	core::result::Result::<T, E>::and_then: 4
	core::result::Result::<T, E>::map_err: 1
	core::result::Result::<T, E>::map_or: 5
	core::result::Result::<T, E>::map_or_else: 1
	core::result::Result::<T, E>::ok: 8
	core::result::Result::<T, E>::unwrap_or: 5
	core::result::Result::<T, E>::unwrap_or_default: 1
	core::result::Result::<T, E>::unwrap_or_else: 2
	core::slice::<impl [T]>::copy_from_slice: 2
	core::slice::<impl [T]>::iter: 6
	core::slice::index::<impl core::ops::Index<I> for [T]>::index: 3
	core::slice::index::<impl core::ops::IndexMut<I> for [T]>::index_mut: 1

@ninehusky
Copy link
Author

Documenting my strategy for panic removal here:

  • If it's easy, then just add no_panic
  • If it's unsafe (e.g., calls some unsafe fn that deals with pointers like from_raw_data for slices), just mark as flux::rs_trusted and move on.
  • If it's a trait definition, mark the trait and the impl as no_panic. This is not always sound, because if you have a no_panic function that takes in some dyn Iterator, you want to make sure that the impl is no_panic, not just the trait. Butwe can come back to that problem in flux later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant