On Fri, Nov 22, 2024 at 07:48:16PM +0100, Alice Ryhl wrote: > On Fri, Nov 22, 2024 at 7:03 PM Boqun Feng <boqun.feng@xxxxxxxxx> wrote: > > > > On Fri, Nov 22, 2024 at 03:40:33PM +0000, Alice Ryhl wrote: > > > +/// Represents a [`Task`] obtained from the `current` global. > > > +/// > > > +/// This type exists to provide more efficient operations that are only valid on the current task. > > > +/// For example, to retrieve the pid-namespace of a task, you must use rcu protection unless it is > > > +/// the current task. > > > +/// > > > +/// # Invariants > > > +/// > > > +/// Must be equal to `current` of some thread that is currently running somewhere. > > > +pub struct CurrentTask(Task); > > > + > > > > I think you need to make `CurrentTask` `!Sync`, right? Otherwise, other > > threads can access the shared reference of a `CurrentTask` and the ->mm > > field. I'm thinking if we have a scoped thread/workqueue support in the > > future: > > > > let task = current!(); > > Workqueue::scoped(|s| { > > s.spawn(|| { > > let mm = task.mm(); > > // do something with the mm > > }); > > }); > > I don't think this is a problem? As long as a thread exists somewhere > with `current` being equal to the task, we should be fine? > I think I had a misunderstanding on what you meant by "operations that are only valid on the current task", you mean these operations can be run by other threads, but it has to be *on* a task_struct that's "currently running", right? BTW, you probably want to reword a bit, because the "current" task may be blocked, so technically it's not "running". Basically, the operations that `CurrentTask` have are the methods that are safe to call (even on a different thread) for the "current" task, as long as it exists (not dead or exited). In that definition, not being `Sync` is fine. But I have to admit I'm a bit worried that people may be confused, and add new methods that can be only run by the current thread in the future. > > > +impl CurrentTask { > > > + /// Access the address space of this task. > > > + /// > > > + /// To increment the refcount of the referenced `mm`, you can use `ARef::from`. > > > + #[inline] > > > + pub fn mm(&self) -> Option<&MmWithUser> { > > > > Hmm... similar issue, `MmWithUser` is `Sync`. > > What is the problem with that? > It should be no problem under your definition of `CurrentTask`. Regards, Boqun > > > + let mm = unsafe { (*self.as_ptr()).mm }; > > > + > > > + if mm.is_null() { > > > + None > > > + } else { > > > + // SAFETY: If `current->mm` is non-null, then it references a valid mm with a non-zero > > > + // value of `mm_users`. The returned `&MmWithUser` borrows from `CurrentTask`, so the > > > + // `&MmWithUser` cannot escape the current task, meaning `mm_users` can't reach zero > > > + // while the reference is still live. > > > > Regards, > > Boqun > > > > > + Some(unsafe { MmWithUser::from_raw(mm) }) > > > + } > > > + } > > > +} > > > + > > > // SAFETY: The type invariants guarantee that `Task` is always refcounted. > > > unsafe impl crate::types::AlwaysRefCounted for Task { > > > fn inc_ref(&self) { > > > > > > -- > > > 2.47.0.371.ga323438b13-goog > > >