Skip to content

rust: task: Add schedule() - #861

Open
fbq wants to merge 1 commit into
Rust-for-Linux:rustfrom
fbq:dev/rust/schedule
Open

fbq wants to merge 1 commit into
Rust-for-Linux:rustfrom
fbq:dev/rust/schedule

Conversation

@fbq

@fbq fbq commented Aug 6, 2022

Copy link
Copy Markdown
Member

Signed-off-by: Boqun Feng boqun.feng@gmail.com

Comment thread rust/kernel/task.rs Outdated
///
/// # Context
///
/// This function might sleep, don't call in atomic contexts.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we're trying to avoid the imperative mode in documentation, so instead of having "do this" or "don't do that", we'd rather have something like "Callers must not be in atomic context because this might sleep".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done locally, thanks!

Comment thread rust/kernel/task.rs Outdated
/// [`std::thread::yield_now`]: https://doc.rust-lang.org/std/thread/fn.yield_now.html
#[doc(alias = "yield_now")]
pub fn schedule() {
// SAFETY: If we can schedule back from other thread, then this can be treated as a no-op. A

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we violate safety by calling schedule?

If we call this from atomic context, we may deadlock the system, which doesn't violate memory safety. If we call it with state set to TASK_DEAD, the function never returning doesn't violate safety either, does it? Is there anything else that we could do?

@fbq fbq Aug 6, 2022 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's about the safety of thread users.

We can treat

set_special_state(TASK_DEAD);
schedule();

, as a decrease on the ref-count of the task_struct.

Normally it's OK if we maintain all references to task_struct via ref-counts. However, there are a few places in kernel C side where a task_struct is referenced with raw pointer. The assumption is that no one should call do_exit() or set TASK_DEAD unless they are writing task_struct or kthread code. If Rust code is allowed to freely do_exit() or set TASK_DEAD, then C side will have dangling pointers to task_struct.

For example, in workqueue, a worker (kernel thread) is referenced without any ref-count addition, so if a Future sets TASK_DEAD and schedule, the worker thread may get freed. And the memory will get corrupted.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's about the safety of thread users.

We can treat

set_special_state(TASK_DEAD);
schedule();

, as a decrease on the ref-count of the task_struct.

Normally it's OK if we maintain all references to task_struct via ref-counts. However, there are a few places in kernel C side where a task_struct is referenced with raw pointer. The assumption is that no one should call do_exit() or set TASK_DEAD unless they are writing task_struct or kthread code. If Rust code is allowed to freely do_exit() or set TASK_DEAD, then C side will have dangling pointers to task_struct.

For example, in workqueue, a worker (kernel thread) is referenced without any ref-count addition, so if a Future sets TASK_DEAD and schedule, the worker thread may get freed. And the memory will get corrupted.

I must admit I did think this far originally. It just looked very dangerous to me if we allow Rust code to set the current thread state to TASK_DEAD. I will update the SAFETY: comments

Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
@fbq
fbq force-pushed the dev/rust/schedule branch from 1388d4a to 12aac8e Compare August 17, 2022 20:56
Comment thread rust/kernel/task.rs
// `TASK_DEAD` + `schedule`. We can make [`Task::schedule`] because of this, but it doesn't
// provide extra safety if we make setting `TASK_DEAD` unsafe. And given [`Task::schedule`]
// may be widely used, let's make it safe and require all `TASK_DEAD` settings to take great
// caution.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

End up kinda saying "the safety is a design choice", I'm not happy about this, but it's the best I can get.

This branch has not been deployed

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants