Skip to content

Commit 5b7b031

Browse files
committed
SQUASH: changes requested in code review
1 parent 28d4d40 commit 5b7b031

File tree

2 files changed

+59
-23
lines changed

2 files changed

+59
-23
lines changed

sys/kern/src/arch/arm_m.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -1185,10 +1185,14 @@ unsafe extern "C" fn pendsv_entry() {
11851185
crate::profiling::event_secondary_syscall_enter();
11861186

11871187
let current = CURRENT_TASK_PTR.load(Ordering::Relaxed);
1188+
// We're being slightly pedantic about this, since it's straightforward (if
1189+
// weird) for pre-kernel main to trigger a PendSV, and it's not possible to
1190+
// disable this interrupt source.
11881191
uassert!(!current.is_null()); // irq before kernel started?
11891192

11901193
// Safety: we're dereferencing the current task pointer, which we're
1191-
// trusting the rest of this module to maintain correctly.
1194+
// trusting the rest of this module to maintain correctly (and we've just
1195+
// checked that the kernel has started).
11921196
let current = usize::from(unsafe { (*current).descriptor().index });
11931197

11941198
with_task_table(|tasks| {
@@ -1222,10 +1226,19 @@ pub unsafe extern "C" fn DefaultHandler() {
12221226
};
12231227

12241228
let current = CURRENT_TASK_PTR.load(Ordering::Relaxed);
1225-
uassert!(!current.is_null()); // irq before kernel started?
12261229

1227-
{
1228-
let t = unsafe { &mut *current };
1230+
// Because this handler is reachable in response to an NMI, it's possible to
1231+
// get here before the kernel has started. So before dereferencing the task
1232+
// pointer, check for NULL (the state at reset). If we manage to get here
1233+
// before the kernel has started, we'll skip the stack watermark update and
1234+
// hit a panic below.
1235+
1236+
// Safety: this dereferences the pointer only if it isn't NULL. If it
1237+
// isn't NULL, that means we've initialized it elsewhere in this module
1238+
// and it's a valid (but aliased) pointer to a task. We can safely
1239+
// dereference it as long as we throw it away before hitting
1240+
// `with_task_table` below.
1241+
if let Some(t) = unsafe { current.as_mut() } {
12291242
t.update_stack_watermark();
12301243
}
12311244

@@ -1251,6 +1264,8 @@ pub unsafe extern "C" fn DefaultHandler() {
12511264
.get(abi::InterruptNum(irq_num))
12521265
.unwrap_or_else(|| panic!("unhandled IRQ {irq_num}"));
12531266

1267+
// with_task_table will panic if the kernel has not yet been
1268+
// started. This is good.
12541269
let switch = with_task_table(|tasks| {
12551270
disable_irq(irq_num, false);
12561271

sys/kern/src/task.rs

+40-19
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,12 @@ pub struct Task {
5050
/// restarted.
5151
descriptor: &'static TaskDesc,
5252

53-
/// Tracks the lowest stack pointer value (e.g. fullest stack) observed on
54-
/// any kernel entry for this instance of this task.
53+
/// Stack watermark tracking support.
5554
///
56-
/// Initialized to `u32::MAX` if the task has not yet run.
55+
/// This field is completely missing if the feature is disabled to make that
56+
/// clear to debug tools.
5757
#[cfg(feature = "stack-watermark")]
58-
stack_pointer_low: u32,
59-
60-
/// Tracks the lowest stack pointer value (e.g. fullest stack) observed on
61-
/// any kernel entry across *any* instance of this task.
62-
///
63-
/// Initialized to `u32::MAX` if the task has not yet run.
64-
#[cfg(feature = "stack-watermark")]
65-
past_stack_pointer_low: u32,
58+
stack_watermark: StackWatermark,
6659
}
6760

6861
impl Task {
@@ -84,9 +77,7 @@ impl Task {
8477
save: crate::arch::SavedState::default(),
8578
timer: crate::task::TimerState::default(),
8679
#[cfg(feature = "stack-watermark")]
87-
stack_pointer_low: u32::MAX,
88-
#[cfg(feature = "stack-watermark")]
89-
past_stack_pointer_low: u32::MAX,
80+
stack_watermark: StackWatermark::default(),
9081
}
9182
}
9283

@@ -341,9 +332,11 @@ impl Task {
341332

342333
#[cfg(feature = "stack-watermark")]
343334
{
344-
self.past_stack_pointer_low =
345-
u32::min(self.past_stack_pointer_low, self.stack_pointer_low);
346-
self.stack_pointer_low = u32::MAX;
335+
self.stack_watermark.past_low = u32::min(
336+
self.stack_watermark.past_low,
337+
self.stack_watermark.current_low,
338+
);
339+
self.stack_watermark.current_low = u32::MAX;
347340
}
348341

349342
crate::arch::reinitialize(self);
@@ -356,8 +349,10 @@ impl Task {
356349
pub fn update_stack_watermark(&mut self) {
357350
#[cfg(feature = "stack-watermark")]
358351
{
359-
self.stack_pointer_low =
360-
u32::min(self.stack_pointer_low, self.save().stack_pointer());
352+
self.stack_watermark.current_low = u32::min(
353+
self.stack_watermark.current_low,
354+
self.save().stack_pointer(),
355+
);
361356
}
362357
}
363358

@@ -418,6 +413,32 @@ impl Task {
418413
}
419414
}
420415

416+
#[cfg(feature = "stack-watermark")]
417+
#[derive(Copy, Clone, Debug)]
418+
struct StackWatermark {
419+
/// Tracks the lowest stack pointer value (e.g. fullest stack) observed on
420+
/// any kernel entry for this instance of this task.
421+
///
422+
/// Initialized to `u32::MAX` if the task has not yet run.
423+
current_low: u32,
424+
425+
/// Tracks the lowest stack pointer value (e.g. fullest stack) observed on
426+
/// any kernel entry across *any* instance of this task.
427+
///
428+
/// Initialized to `u32::MAX` if the task has not yet run.
429+
past_low: u32,
430+
}
431+
432+
#[cfg(feature = "stack-watermark")]
433+
impl Default for StackWatermark {
434+
fn default() -> Self {
435+
Self {
436+
current_low: u32::MAX,
437+
past_low: u32::MAX,
438+
}
439+
}
440+
}
441+
421442
/// Interface that must be implemented by the `arch::SavedState` type. This
422443
/// gives architecture-independent access to task state for the rest of the
423444
/// kernel.

0 commit comments

Comments
 (0)