Skip to content

Commit

Permalink
Add task cancellation test
Browse files Browse the repository at this point in the history
It doesn't currently pass, but should in the near future.

Signed-off-by: Klim Tsoutsman <[email protected]>
  • Loading branch information
tsoutsman committed Dec 23, 2022
1 parent 4c82f35 commit 8bd4630
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions applications/test_task_cancel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "test_task_cancel"
version = "0.1.0"
authors = ["Klim Tsoutsman <[email protected]>"]
description = "Task cancellation test"
edition = "2021"

[dependencies]
log = "0.4"
spawn = { path = "../../kernel/spawn" }
spin = "0.9"
task = { path = "../../kernel/task" }
49 changes: 49 additions & 0 deletions applications/test_task_cancel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// TODO: Properly implement Task::kill so the test passes.

#![no_std]

extern crate alloc;

use alloc::{string::String, sync::Arc, vec::Vec};
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::Mutex;

pub fn main(_: Vec<String>) -> isize {
let lock = Arc::new(Mutex::new(()));
let task = spawn::new_task_builder(other, lock.clone())
.spawn()
.expect("failed to spawn task");

while !lock.is_locked() {}

task.kill(task::KillReason::Requested)
.expect("failed to abort task");

log::debug!("waiting for lock to be unlocked");

// For us to acquire the lock, the drop handler of the other thread's guard must
// have been invoked.
let _ = lock.lock();

0
}

#[inline(never)]
fn other(lock: Arc<Mutex<()>>) {
let _guard = lock.lock();
loop {
// In order to properly unwind the task we need to reach an instruction that is
// covered by the unwind tables. Rust generates an unwind row for all call
// sites so by placing a call site in the loop we ensure that the task will
// reach an instruction from which it can unwind when it is told to cancel.
unwind_row_generator();
}
}

#[inline(never)]
fn unwind_row_generator() {
static __COUNTER: AtomicUsize = AtomicUsize::new(0);

// Prevents unwind_row_generator from being optimised away.
__COUNTER.fetch_add(1, Ordering::Relaxed);
}
2 changes: 2 additions & 0 deletions theseus_features/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ test_realtime = { path = "../applications/test_realtime", optional = true }
test_restartable = { path = "../applications/test_restartable", optional = true }
test_serial_echo = { path = "../applications/test_serial_echo", optional = true }
test_std_fs = { path = "../applications/test_std_fs", optional = true }
test_task_cancel = { path = "../applications/test_task_cancel", optional = true }
test_wait_queue = { path = "../applications/test_wait_queue", optional = true }
test_wasmtime = { path = "../applications/test_wasmtime", optional = true }
tls_test = { path = "../applications/tls_test", optional = true }
Expand Down Expand Up @@ -147,6 +148,7 @@ theseus_tests = [
"test_restartable",
"test_serial_echo",
"test_std_fs",
"test_task_cancel",
"test_wait_queue",
"test_wasmtime",
"tls_test",
Expand Down

0 comments on commit 8bd4630

Please sign in to comment.