From patchwork Thu Jun 1 13:49:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101943 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp345644vqr; Thu, 1 Jun 2023 06:53:47 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4ppQPpZxmMBQbTVJwii6ueSqMsYVCzHyzwE0uuQyPv83wYer+VV0N4YcD8J6fsR57jIqYl X-Received: by 2002:a92:c144:0:b0:33a:d0f6:9133 with SMTP id b4-20020a92c144000000b0033ad0f69133mr6263427ilh.12.1685627627446; Thu, 01 Jun 2023 06:53:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685627627; cv=none; d=google.com; s=arc-20160816; b=iL2mfqoKki2pVRJIwg33nrW9XjjwTI7NsHGZ6Yk4z6LILilBKozpzsb7pevwei9Nx4 Oe0f3q4OQwjb9BRd+Ydi0D195AWjL4B8rXfPOG+M8TB1OP76dzeQWHV/0Zs1LfyH6ONz UOhVMQI3HLNx8DCpjixlQVWknyqxm9W7DUuv23YtU6BkUBOQwJ8RCllxu33g5LbWi8NV olPD2+uoD0tyU0ydepw3eLAmdMRlNVIteUjRg0fV5rSKJtzl8E3k5B/unjUXFbxdEe0E HAGAdVZbnUxerNL5UuXPc/zhg0rR/pHTSLezvs2h538k/uPotmafIqKh0E0rB1lQJIK6 Fn0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=FuSvyE3H/lsB/N9LBubh06h32izpsOqcuowYerHxhqc=; b=0Sqlq8e72vFYDmqvbljGGU4fnVlpPB7gU+as7lhL97zGAGtlzf25o6rExAioHyxlsg yxcWNDo+DsnQv/HDFaAIQB6GN8QFc5hYLm7EprKio2BsWK+e1ljDIUwAzPH7YH3dtFj8 IDCrEs9bd1T/+Hf3Iz4KX/yKlw1fYZHcKk81py4F3dzqYcgHgG3ObEF3lAnb+UUcpo3+ /6ts5FMjD2EsrpV4kSrTHAIgjP20ndPm/2sJA2k9HbheJ9gCsRzxSjqQXTIzEGRCcWQN rch5QlnJz/47tcKPlwUp7dMPLbJZ2wIsYKMeSdGbLyKCoNM42l20F2xknzRlEtozGfqT TZ3w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=FyvVJlD2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id az9-20020a056a02004900b0053f01212571si3062358pgb.257.2023.06.01.06.53.33; Thu, 01 Jun 2023 06:53:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=FyvVJlD2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232817AbjFANu4 (ORCPT + 99 others); Thu, 1 Jun 2023 09:50:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230222AbjFANux (ORCPT ); Thu, 1 Jun 2023 09:50:53 -0400 Received: from mail-ej1-x649.google.com (mail-ej1-x649.google.com [IPv6:2a00:1450:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE884129 for ; Thu, 1 Jun 2023 06:50:51 -0700 (PDT) Received: by mail-ej1-x649.google.com with SMTP id a640c23a62f3a-94a348facbbso65753966b.1 for ; Thu, 01 Jun 2023 06:50:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627450; x=1688219450; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=FuSvyE3H/lsB/N9LBubh06h32izpsOqcuowYerHxhqc=; b=FyvVJlD2CGIUJvNbQZbNEYbMCpjM2wfkXCGCXQdGdxbllqs61y+dOimrUiXITslDnr L0xzV3vfgwdACLzxRZt2w/DUr0I0hVp38FptQFQB6p9HI8WTeYEqxuLkrzz5udg311TU P31I2p4lYUs39xALew33gD26gaTMk5tNQ6oSCPSJoYX0pP5ep3b5P0RNsM1r1kT4n/fe iI4kk5O3HoJfozo7oHD16yShr/tg4SPDVzuEmF1fYUSe19h8vKIorMgbuPFZHd/uKeEN 9035Iz0htSCg+0b9FgqdQzj12QUgODRxB+tsT3VI3//m07btmf13UfCNEU/ZNeURTvpq Knhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627450; x=1688219450; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=FuSvyE3H/lsB/N9LBubh06h32izpsOqcuowYerHxhqc=; b=PphalykoE+g5objEglB5to6coQbd1WH/nF5j+JplrZ6IjNDtF30j2nNV7VPcODTt9t IOzLIFhyspTCpHaSrJXW9yM3ZZTyWXCR/IvmzmAibI1TMCWm90VsXsUNWCJrqCS3IGU2 98gQnd16N6hJ/DmoAivcf6eFnu4D7uo5VUt5OyDIZ7J3smAvIfmrWjlhXLCMGhT89FMn LetAArXQyRA6nHpsk9bCSnW9lh1+yaAncXlp+fci8MNbhM++fBxVv2xaMtXPe8TNK5JX vhsWKFqgz1snlCVQStlJLd4jPd80VcG8DIpnpj7fW/H6yvQwhZjuumZbOgIrCGM+IInc EcXA== X-Gm-Message-State: AC+VfDyEmreYFa+HYOnjp/C8Jvwv98XVNhEqnYAhXUcgeEQn6Hud6O4d KFBgLPhs+oxB3AnX8M5KezCAwPxCbav98aY= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:907:270c:b0:96f:ddeb:9e8c with SMTP id w12-20020a170907270c00b0096fddeb9e8cmr3366915ejk.6.1685627450568; Thu, 01 Jun 2023 06:50:50 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:39 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-2-aliceryhl@google.com> Subject: [PATCH v2 1/8] rust: workqueue: add low-level workqueue bindings From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767508674978062804?= X-GMAIL-MSGID: =?utf-8?q?1767508674978062804?= Define basic low-level bindings to a kernel workqueue. The API defined here can only be used unsafely. Later commits will provide safe wrappers. Co-developed-by: Gary Guo Signed-off-by: Gary Guo Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Benno Lossin --- rust/bindings/bindings_helper.h | 1 + rust/kernel/lib.rs | 1 + rust/kernel/workqueue.rs | 107 ++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 rust/kernel/workqueue.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 50e7a76d5455..ae2e8f018268 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -10,6 +10,7 @@ #include #include #include +#include /* `bindgen` gets confused at certain things. */ const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 85b261209977..eaded02ffb01 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -43,6 +43,7 @@ pub mod sync; pub mod task; pub mod types; +pub mod workqueue; #[doc(hidden)] pub use bindings; diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs new file mode 100644 index 000000000000..9c630840039b --- /dev/null +++ b/rust/kernel/workqueue.rs @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Work queues. +//! +//! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h) + +use crate::{bindings, types::Opaque}; + +/// A kernel work queue. +/// +/// Wraps the kernel's C `struct workqueue_struct`. +/// +/// It allows work items to be queued to run on thread pools managed by the kernel. Several are +/// always available, for example, `system`, `system_highpri`, `system_long`, etc. +#[repr(transparent)] +pub struct Queue(Opaque); + +// SAFETY: Kernel workqueues are usable from any thread. +unsafe impl Send for Queue {} +unsafe impl Sync for Queue {} + +impl Queue { + /// Use the provided `struct workqueue_struct` with Rust. + /// + /// # Safety + /// + /// The caller must ensure that the provided raw pointer is not dangling, that it points at a + /// valid workqueue, and that it remains valid until the end of 'a. + pub unsafe fn from_raw<'a>(ptr: *const bindings::workqueue_struct) -> &'a Queue { + // SAFETY: The `Queue` type is `#[repr(transparent)]`, so the pointer cast is valid. The + // caller promises that the pointer is not dangling. + unsafe { &*(ptr as *const Queue) } + } + + /// Enqueues a work item. + /// + /// This may fail if the work item is already enqueued in a workqueue. + /// + /// The work item will be submitted using `WORK_CPU_UNBOUND`. + pub fn enqueue(&self, w: W) -> W::EnqueueOutput + where + W: RawWorkItem + Send + 'static, + { + let queue_ptr = self.0.get(); + + // SAFETY: We only return `false` if the `work_struct` is already in a workqueue. The other + // `__enqueue` requirements are not relevant since `W` is `Send` and static. + // + // The call to `bindings::queue_work_on` will dereference the provided raw pointer, which + // is ok because `__enqueue` guarantees that the pointer is valid for the duration of this + // closure. + // + // Furthermore, if the C workqueue code accesses the pointer after this call to + // `__enqueue`, then the work item was successfully enqueued, and `bindings::queue_work_on` + // will have returned true. In this case, `__enqueue` promises that the raw pointer will + // stay valid until we call the function pointer in the `work_struct`, so the access is ok. + unsafe { + w.__enqueue(move |work_ptr| { + bindings::queue_work_on(bindings::WORK_CPU_UNBOUND as _, queue_ptr, work_ptr) + }) + } + } +} + +/// A raw work item. +/// +/// This is the low-level trait that is designed for being as general as possible. +/// +/// The `ID` parameter to this trait exists so that a single type can provide multiple +/// implementations of this trait. For example, if a struct has multiple `work_struct` fields, then +/// you will implement this trait once for each field, using a different id for each field. The +/// actual value of the id is not important as long as you use different ids for different fields +/// of the same struct. (Fields of different structs need not use different ids.) +/// +/// Note that the id is used only to select the right method to call during compilation. It wont be +/// part of the final executable. +/// +/// # Safety +/// +/// Implementers must ensure that any pointers passed to a `queue_work_on` closure by `__enqueue` +/// remain valid for the duration specified in the documentation for `__enqueue`. +pub unsafe trait RawWorkItem { + /// The return type of [`Queue::enqueue`]. + type EnqueueOutput; + + /// Enqueues this work item on a queue using the provided `queue_work_on` method. + /// + /// # Guarantees + /// + /// If this method calls the provided closure, then the raw pointer is guaranteed to point at a + /// valid `work_struct` for the duration of the call to the closure. If the closure returns + /// true, then it is further guaranteed that the pointer remains valid until someone calls the + /// function pointer stored in the `work_struct`. + /// + /// # Safety + /// + /// The provided closure may only return `false` if the `work_struct` is already in a workqueue. + /// + /// If the work item type is annotated with any lifetimes, then you must not call the function + /// pointer after any such lifetime expires. (Never calling the function pointer is okay.) + /// + /// If the work item type is not [`Send`], then the function pointer must be called on the same + /// thread as the call to `__enqueue`. + unsafe fn __enqueue(self, queue_work_on: F) -> Self::EnqueueOutput + where + F: FnOnce(*mut bindings::work_struct) -> bool; +} From patchwork Thu Jun 1 13:49:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101945 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp346637vqr; Thu, 1 Jun 2023 06:55:39 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5AEseh9kQAAOR/dXkb8zM5TOOzoD5/RQ/afJ9R0c+W5nqz7S8h3yK/wvshLLeSVOUsAKQz X-Received: by 2002:a17:90a:cc05:b0:256:69e2:7b7b with SMTP id b5-20020a17090acc0500b0025669e27b7bmr8689061pju.7.1685627739193; Thu, 01 Jun 2023 06:55:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685627739; cv=none; d=google.com; s=arc-20160816; b=s6tBHpBeRURd+ZFW+ylzqbpEteLidv2PYfWPtCAA+yogDtraIYwwULzJUAa4jkt4VV KEHjapOCssU6knMSRjnWw/UxM3vTSGbprE0LEG0acKGy+8DnbcxXPgvj8Xx4awzz3oZS XP7BtfnzpLadZ0DHt0BJeliqMoFxsjOoh/hZU4fkX86dPHy2/bdklwFHlPN/vu8FJ8eI 8loRWe5gYJp2t5KIy9n9utSwc275JbNopr9jbLB4vFpTKn4JoedjNQRFExI/P9eRmE/P Ju2tOOVM7k14dWgSaqmPwd0H6My7MfRiFimYSy1MwoNyZOwdTnIHAh0hILH0sTaAfKYD 0xoQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=CFWZiTMzRcsx84Z5SYXbngPTfzR7GjN80EhCOaRTPas=; b=vp6Fl3narkGrknazURfGqwg245K1OOhS+xjYLxdcbyhG9esfhXUFRPJE4Cr1rODChW mEXkA11z7mLtoHsy5b8f8dext43P8melF7yAc/P/tOJQ4pkCI6CfTLvjuiwrjp1pHwH8 yVNgfelJdOdFCYJpK7emcIsc/q+feA4Eku/rv++qnyX6gGjMnqPlmqDy1/w4JoL161sF VwGBnsff+bYnYeH9bus7fvFuZwhORWD1sKF78D8xJhx+qK65AOb9bAOC+7wdqqqShvw3 A3fAhWSjSrLuv2kKfcYGXRJp4TmsrhMm4aenkVUY8vg8/N08O0H1WA3m1uMcsMWGmPhg ho/g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=6U1LmEIL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id qe10-20020a17090b4f8a00b002532fb740fesi1197470pjb.91.2023.06.01.06.55.26; Thu, 01 Jun 2023 06:55:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=6U1LmEIL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233226AbjFANvT (ORCPT + 99 others); Thu, 1 Jun 2023 09:51:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49162 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233267AbjFANvR (ORCPT ); Thu, 1 Jun 2023 09:51:17 -0400 Received: from mail-ed1-x549.google.com (mail-ed1-x549.google.com [IPv6:2a00:1450:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F7D21AD for ; Thu, 1 Jun 2023 06:51:11 -0700 (PDT) Received: by mail-ed1-x549.google.com with SMTP id 4fb4d7f45d1cf-514b05895f7so783241a12.0 for ; Thu, 01 Jun 2023 06:51:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627470; x=1688219470; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=CFWZiTMzRcsx84Z5SYXbngPTfzR7GjN80EhCOaRTPas=; b=6U1LmEILAkXt1ykhx/Ehu4FX/iB1ojm/m3YZhZZkMXOJ1AUeWEH2jlJbqb665k/3Zl UyRA+zunWEjQTWb6+7BglNY3ssL/IdWy8mC00gdGNfPYWvpX92UeVIpgmBeIVWJ7dWlg zA9q4amy/WFWI5coaOYgwbUHvE17fLTDf3pxodr/okPUFMqLBlKBIn36kKRjcDOmY/tm mTIKZ8119pOSw08AkUN26fS9yvv4y6RVrmd22szoQMDHDN5qguhwAG5ZeSbKzcNoZ8tk +dVRxL08TvQCZ+aWANc8BUah0e4E0MRnbTZid/0ie+ioPBhISLnEadvuBGWRLZhe/nWc CmDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627470; x=1688219470; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CFWZiTMzRcsx84Z5SYXbngPTfzR7GjN80EhCOaRTPas=; b=gdPdXHwz+76fK41CG0nVn3AchzuExG28B0YhjqZoOOI65m7/sYd/V+CHbuE/FaHfmv vVhhnNdTq1qzU5PNoFkcMYUQ2ewwOx5xkKHcDyUMg2/NPFXw3c1pTBwMz18fMkLOnL7y weehT+k0LBvYb8UaG88nUpqqzg227fi3ikT8P3agpSyLL6BQ6dbRu3/uW3iwSGbtwOsZ CbkOe3WibQk2vuyh3Q82x6yIKnHdNoif+wIHAhuimk9WhbcHJ7e7YR/wJKRhVo/C5pYG 8PxQnv1eANA/7DOi+z+5JLdvA3GDy/v2LI6TYeFP2c0e/rvVxqZVZuG23IQ23H3hJ/DB LruA== X-Gm-Message-State: AC+VfDyfCrX4MpK0CZNSwNC4L0SMhktyjY0XkHWpEdC70rBFIdbBAXBq OTVSFjXXGYkcileIEtzMwbzjsoA/UqfaHqs= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:906:9bc3:b0:947:f975:cc09 with SMTP id de3-20020a1709069bc300b00947f975cc09mr2209092ejc.1.1685627469897; Thu, 01 Jun 2023 06:51:09 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:40 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-3-aliceryhl@google.com> Subject: [PATCH v2 2/8] rust: add offset_of! macro From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev, Wedson Almeida Filho , Martin Rodriguez Reboredo X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767508792601816669?= X-GMAIL-MSGID: =?utf-8?q?1767508792601816669?= From: Wedson Almeida Filho This macro is used to compute the offset of a field in a struct. This commit enables an unstable feature that is necessary for using the macro in a constant. However, this is not a problem as the macro will become available from the Rust standard library soon [1]. The unstable feature can be disabled again once that happens. The macro in this patch does not support sub-fields. That is, you cannot write `offset_of!(MyStruct, field.sub_field)` to get the offset of `sub_field` with `field`'s type being a struct with a field called `sub_field`. This is because `field` might be a `Box`, which means that you would be trying to compute the offset to something in an entirely different allocation. There's no easy way to fix the current macro to support subfields, but the version being added to the standard library should support it, so the limitation is temporary and not a big deal. Link: https://github.com/rust-lang/rust/issues/106655 [1] Signed-off-by: Wedson Almeida Filho Co-developed-by: Alice Ryhl Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Gary Guo Reviewed-by: Benno Lossin --- rust/kernel/lib.rs | 35 +++++++++++++++++++++++++++++++++++ scripts/Makefile.build | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index eaded02ffb01..7ea777b731e6 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -14,6 +14,7 @@ #![no_std] #![feature(allocator_api)] #![feature(coerce_unsized)] +#![feature(const_refs_to_cell)] #![feature(dispatch_from_dyn)] #![feature(new_uninit)] #![feature(receiver_trait)] @@ -98,3 +99,37 @@ fn panic(info: &core::panic::PanicInfo<'_>) -> ! { // instead of `!`. See . loop {} } + +/// Calculates the offset of a field from the beginning of the struct it belongs to. +/// +/// # Examples +/// +/// ``` +/// #[repr(C)] +/// struct Test { +/// a: u64, +/// b: u32, +/// } +/// +/// assert_eq!(kernel::offset_of!(Test, b), 8); +/// ``` +#[macro_export] +macro_rules! offset_of { + ($type:path, $field:ident) => {{ + let $type { $field: _, .. }; + let tmp = ::core::mem::MaybeUninit::<$type>::uninit(); + let outer = tmp.as_ptr(); + // To avoid warnings when nesting `unsafe` blocks. + #[allow(unused_unsafe)] + // SAFETY: The pointer is valid and aligned, just not initialised; `addr_of` ensures that + // we don't actually read from `outer` (which would be UB) nor create an intermediate + // reference. + let inner = unsafe { ::core::ptr::addr_of!((*outer).$field) } as *const u8; + // To avoid warnings when nesting `unsafe` blocks. + #[allow(unused_unsafe)] + // SAFETY: The two pointers are within the same allocation block. + unsafe { + inner.offset_from(outer as *const u8) as usize + } + }}; +} diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 78175231c969..819510694769 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -277,7 +277,7 @@ $(obj)/%.lst: $(src)/%.c FORCE # Compile Rust sources (.rs) # --------------------------------------------------------------------------- -rust_allowed_features := new_uninit +rust_allowed_features := const_refs_to_cell,new_uninit rust_common_cmd = \ RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \ From patchwork Thu Jun 1 13:49:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101958 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp367740vqr; Thu, 1 Jun 2023 07:20:55 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4jZpyrm5oey6F4hExb8iJFHYqJ0aGnndDSPqLsrwQmqRuQud5BDIlH/lFKQFno2N/JTJ7j X-Received: by 2002:a17:902:e5c2:b0:1a9:8d57:6d6c with SMTP id u2-20020a170902e5c200b001a98d576d6cmr7868332plf.24.1685629255495; Thu, 01 Jun 2023 07:20:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685629255; cv=none; d=google.com; s=arc-20160816; b=WON0GsAxwZg9LEMogVfmSW8lq2m9GQCMggdf50r97LMJYwD9KAHvEm4ew5FIxpwNWp 8ZbIIQDZMtuwCeKVHYdvMnOk9mEQESYLxDvq2U2CAqsOEgmCr7Zk0V04xmtj7ZI+Pzcb ZarttjMHanQnkqGpaeGiIkmjUNv9eJxN4C6DBrbbqc2lf351Trk/X0in7naYXEq1z6HS LheFPa+wsCpZ6l7P0AByFytobToeb8kJsBdo6XKkKBU5Qah46BC/wUk3REuPuQGQZDG5 15MjYT4i/1OALv68DAc+rO6MBItXIEsSkAaXgPWd+FGtNHdFnCAqP37+AeYJD1hPD4Xr 7kgw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=emM0vnYZP8ovSB9/0L28X7xu1W1tC2o+UTrpcckUn6I=; b=Zu0kxPJAZxT3mmGRFh+CyQf2L63tVdic7S5Nln+rgWeD9uKZTBUcAIBuEIpxKJ1AwY Nnl96fgZLl4EPXDDnT6jwnh5/ESw1lURQ0ARimRkDJszYFWpBOExX4mHsew3jE4u7mN3 R7lIzD2G6IXHmqJSJfC6RtALpsygAmsFSPTv1KNTNICSjAlaQwLHCxyMmn6Quhj+uPHP 1g9EKr3SvaVZ/G73VqY2MgF2ZX6L1cs1DbZ0nPuKmMpPUybuz9USKC90tXsqeqDKQE2z GP1iS6IVnVG8ozZb30ohox+4vEq+zhoyOZRAshW+e80b+DmXCP2cfYhG3Kjakw++9uQC tDIw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=xiQpeTAp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h11-20020a170902704b00b001b035ce0653si2733740plt.380.2023.06.01.07.20.40; Thu, 01 Jun 2023 07:20:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=xiQpeTAp; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233352AbjFANxV (ORCPT + 99 others); Thu, 1 Jun 2023 09:53:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50594 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229866AbjFANxT (ORCPT ); Thu, 1 Jun 2023 09:53:19 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00E97119 for ; Thu, 1 Jun 2023 06:53:17 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-bacd408046cso1313040276.3 for ; Thu, 01 Jun 2023 06:53:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627597; x=1688219597; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=emM0vnYZP8ovSB9/0L28X7xu1W1tC2o+UTrpcckUn6I=; b=xiQpeTApD8EOPRLGvqOEbGnwk5VdgbS481DnQDIEFxEdsz/On6iBdKRYTdwC4GSgKB ph6LBgaidNw+WGSeSHFktPPsUZz32+fyRaDVJAIFfZN/e98wVfiftPu+6Uks3ZrG/Wbm qYQSoWdlUuUSFuYtP5XYH42+XrgljkWS1ibSt+8a48D1yXNfxUsbCgVXQcRA1QlmnIjo DJdJK+53Kf/Rf7wXCzRaWFXdwIBLvTbOxI3Iofy7tLQ5FmIGaCokuy9i65leoDsK3Jb1 vHup+pJUEoS+DZOCrHTg5fJDr1NpU8/R+Ig1RUYXj7GDgRTXdO1bvBdOXfCNqJXcUIMb lzXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627597; x=1688219597; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=emM0vnYZP8ovSB9/0L28X7xu1W1tC2o+UTrpcckUn6I=; b=CY31pES92B2l8WBq3ocb1nVUa7yUGARnUfJg0s4f8jZDj3miMboTQQe/rA7znpdVfN m+OK7qHuq7oSuH+nnlN4VOyWa51ML+u689lxiPzBoqdQ+KAQyY5S97unJBRPoV8YEo6b GJ9ABsOG4e/0A6EeICY07XQNCH/tWrkGaGoV7fL2YhXEIJIe2f/9RqmNVgGmpzP4mSAg J6CbQW5u4Duc34RCnqiAPlUDjGRmE3eSa/wgZ1HpM6IVwY1l5zpSayy4Xtb994BAZbHj HIMynEXA9k8iInj6XzURw5iNjQSc0bcmlg510PzkzmDzUlcHlsY7lKEpPj3O+ERh7TwD JdbA== X-Gm-Message-State: AC+VfDxDEPKWVHQXyZoO0Nfj/DkVWBzbI3DPDrkNw0NTMmoVc7bmqE30 MvIIwd2raHcFdKqO2lagw/GjrTQtb0x+EYc= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a05:6902:a8e:b0:b1d:5061:98e3 with SMTP id cd14-20020a0569020a8e00b00b1d506198e3mr5275183ybb.6.1685627597196; Thu, 01 Jun 2023 06:53:17 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:41 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-4-aliceryhl@google.com> Subject: [PATCH v2 3/8] rust: sync: add `Arc::{from_raw, into_raw}` From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev, Wedson Almeida Filho , Martin Rodriguez Reboredo X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767510382214251499?= X-GMAIL-MSGID: =?utf-8?q?1767510382214251499?= From: Wedson Almeida Filho These methods can be used to turn an `Arc` into a raw pointer and back, in a way that preserves the metadata for fat pointers. This is done using the unstable ptr_metadata feature [1]. However, it could also be done using the unstable pointer_byte_offsets feature [2], which is likely to have a shorter path to stabilization than ptr_metadata. Link: https://github.com/rust-lang/rust/issues/81513 [1] Link: https://github.com/rust-lang/rust/issues/96283 [2] Signed-off-by: Wedson Almeida Filho Co-developed-by: Alice Ryhl Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Gary Guo Reviewed-by: Benno Lossin --- rust/kernel/lib.rs | 1 + rust/kernel/sync/arc.rs | 42 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 7ea777b731e6..ad9142928fb1 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -17,6 +17,7 @@ #![feature(const_refs_to_cell)] #![feature(dispatch_from_dyn)] #![feature(new_uninit)] +#![feature(ptr_metadata)] #![feature(receiver_trait)] #![feature(unsize)] diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index a89843cacaad..684be9f73aca 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -24,7 +24,7 @@ }; use alloc::boxed::Box; use core::{ - alloc::AllocError, + alloc::{AllocError, Layout}, fmt, marker::{PhantomData, Unsize}, mem::{ManuallyDrop, MaybeUninit}, @@ -212,6 +212,46 @@ unsafe fn from_inner(inner: NonNull>) -> Self { } } + /// Convert the [`Arc`] into a raw pointer. + /// + /// The raw pointer has ownership of the refcount that this Arc object owned. + pub fn into_raw(self) -> *const T { + let ptr = self.ptr.as_ptr(); + core::mem::forget(self); + // SAFETY: The pointer is valid. + unsafe { core::ptr::addr_of!((*ptr).data) } + } + + /// Recreates an [`Arc`] instance previously deconstructed via [`Arc::into_raw`]. + /// + /// This code relies on the `repr(C)` layout of structs as described in + /// . + /// + /// # Safety + /// + /// `ptr` must have been returned by a previous call to [`Arc::into_raw`]. Additionally, it + /// can only be called once for each previous call to [`Arc::into_raw`]. + pub unsafe fn from_raw(ptr: *const T) -> Self { + let refcount_layout = Layout::new::(); + // SAFETY: The caller guarantees that the pointer is valid. + let val_layout = unsafe { Layout::for_value(&*ptr) }; + // SAFETY: We're computing the layout of a real struct that existed when compiling this + // binary, so its layout is not so large that it can trigger arithmetic overflow. + let val_offset = unsafe { refcount_layout.extend(val_layout).unwrap_unchecked().1 }; + + // This preserves the metadata in the pointer, if any. + // + // Note that `*const T` and `*const ArcInner` have the same metadata as documented at + // . + let metadata = core::ptr::metadata(ptr as *const ArcInner); + let ptr = (ptr as *mut u8).wrapping_sub(val_offset) as *mut (); + let ptr = core::ptr::from_raw_parts_mut(ptr, metadata); + + // SAFETY: By the safety requirements we know that `ptr` came from `Arc::into_raw`, so the + // reference count held then will be owned by the new `Arc` object. + unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } + } + /// Returns an [`ArcBorrow`] from the given [`Arc`]. /// /// This is useful when the argument of a function call is an [`ArcBorrow`] (e.g., in a method From patchwork Thu Jun 1 13:49:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101947 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp348946vqr; Thu, 1 Jun 2023 07:00:02 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ6pB7YNIAffKxcZqnOUQ8ilRj+k/m6jHnb+xLaA6k3t5n+NzunEajfHq32laHlyLzsbI1ln X-Received: by 2002:a05:6358:904:b0:127:827e:d2c8 with SMTP id r4-20020a056358090400b00127827ed2c8mr6998849rwi.2.1685628002320; Thu, 01 Jun 2023 07:00:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685628002; cv=none; d=google.com; s=arc-20160816; b=dxFeb14CusvKYalicDrECw8S1N/OpxQxbT14WArnC64IdMBbQO4p+VLem+qwh4u3Ut WMmEboTO16wBuoJgwVKceIG1k5XR+bX8huIeEzpeJu1tKb5eKfTaf7s3Mpw0pUhSh4kX /QTDLx1MidJ7CKg8ak6aZuAw2cd5ktwgL7QkQDRd6avgPklk3ZUufX1M44C17clZ/vkT /LVG2sLydXsVs4kbkRSgJbLwSsPq/uF7QFffJSUmIZ2YtlWKFgNvS71hzz/VlxJUuYJh zpH2Rrv7YXd3BJ3rp04H7bqLsm1zmc1FMdfmHddHIH9eZDlC032f5eVL4pg51uENLQ5M R1IQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=kFZgiOUIu+kFD/tH5EFpQqSQN/mWPzP02CS5RCs3B9M=; b=KAhcQvN4xVnn8oMLt2e6ukCHRD4cHml/0+tEuFXvUIa/LeIiQ8YMxw/q3grMs1o52+ +yOcISpOUFGm/DM7u5ZkG6qgbG0G9wus7uv1D/CEq7eatUPQV/R9vuCeERqs8j332l8z gsFNFbpSXyumdeUduTD4SehkmrteWrLlmhEHXWkp9AkcEZ2gAFsbYWQ8JHLAzUdFV+uk TwPPuBBDTRv0XGi9X2coVd+GQIhNbCrR0KJbfs9o1S5sKNZqcgcSpuDT+j6M6YwOLMhJ mCAxoaJ3u7KRswqBqA9Jbm9Rk4v6PFsh6T89Mr2cXJcalWxMo4Wn0QZSTNHCq9aKfKeE RR9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=MkzWTGF9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id c6-20020a6566c6000000b0053fbb190cb9si464951pgw.572.2023.06.01.06.59.48; Thu, 01 Jun 2023 07:00:02 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=MkzWTGF9; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233427AbjFANyD (ORCPT + 99 others); Thu, 1 Jun 2023 09:54:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233016AbjFANyB (ORCPT ); Thu, 1 Jun 2023 09:54:01 -0400 Received: from mail-ed1-x54a.google.com (mail-ed1-x54a.google.com [IPv6:2a00:1450:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6778B13D for ; Thu, 1 Jun 2023 06:53:59 -0700 (PDT) Received: by mail-ed1-x54a.google.com with SMTP id 4fb4d7f45d1cf-514b3b99882so706683a12.2 for ; Thu, 01 Jun 2023 06:53:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627638; x=1688219638; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=kFZgiOUIu+kFD/tH5EFpQqSQN/mWPzP02CS5RCs3B9M=; b=MkzWTGF98V5rWGyl2PEut0MvVD60T25TsJG+nP3EJ0G5Xj9HN/47MO2rJK4nSC8lAD TJvZCwvsHZnHGDFiPXqerEKpexrbHyZ5jkHFur0RTDUcpye/mtH04woakV0u/oTzddFi ErxxJN1cTn+2gjmPjvFwUQd+aIbjKx6adZhQgUS1rFmnHk5ewCWxnCRVk26Do8jsKsXm kwmrZ5wO4mULuKacNSxdAF+hTBRIKHsiOx0dgijn4mDotI5LaPFPj1fzFl3IlRL5TpXy 0qtu9up5ITib15C7+Z77VR0cIS8sBssQbXFZkrc6NmoyqwmKOmd2IQqBo5uEGjolxxCB Nc2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627638; x=1688219638; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=kFZgiOUIu+kFD/tH5EFpQqSQN/mWPzP02CS5RCs3B9M=; b=gZh0+JwUIU1KaUqHYgSw6AFokJMqdfcKHBuhpP2FAX9ps1/u5PUOvyc8CdA0zTQEL8 iM/WV+XNDEdL+jCA9MCfA+K7MrxNdSAR1GgdW47kvo9+6VV5OjqcYsSv15pbUC8dP+OK 5iT3R4uY9v+44u9KYzYQTDe/W2StoA1mRm3JSZVXthJVvpS1TrLOWQQF9DpufEOwYwyL 2govK78S5HoAXvJSxmt7ISPpHvSRo0qB/J6sjigBLc24CGJK+VCUxvuJb7GxMK+1Lt7J IYDlR0jixU8PFk72E/gyiJGMlubDwlaZGWToupKtj7uvBwDyy61TmFCsKWqitZUe+Cu2 TujA== X-Gm-Message-State: AC+VfDwof9xGA7G3SV5BN80v5+7Dy0KjQgnsw2k6ej5sOttHGtVxWJis CPFZ6bN2J4ozxBEk1GXjZxilNNwg1/C4ulQ= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a50:f692:0:b0:510:b4dc:165a with SMTP id d18-20020a50f692000000b00510b4dc165amr3036075edn.5.1685627637870; Thu, 01 Jun 2023 06:53:57 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:42 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-5-aliceryhl@google.com> Subject: [PATCH v2 4/8] rust: workqueue: define built-in queues From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev, Wedson Almeida Filho , Martin Rodriguez Reboredo X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767509067910843075?= X-GMAIL-MSGID: =?utf-8?q?1767509067910843075?= From: Wedson Almeida Filho We provide these methods because it lets us access these queues from Rust without using unsafe code. These methods return `&'static Queue`. References annotated with the 'static lifetime are used when the referent will stay alive forever. That is ok for these queues because they are global variables and cannot be destroyed. Signed-off-by: Wedson Almeida Filho Co-developed-by: Alice Ryhl Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Gary Guo Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Benno Lossin --- rust/kernel/workqueue.rs | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 9c630840039b..e37820f253f6 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -105,3 +105,68 @@ unsafe fn __enqueue(self, queue_work_on: F) -> Self::EnqueueOutput where F: FnOnce(*mut bindings::work_struct) -> bool; } + +/// Returns the system work queue (`system_wq`). +/// +/// It is the one used by `schedule[_delayed]_work[_on]()`. Multi-CPU multi-threaded. There are +/// users which expect relatively short queue flush time. +/// +/// Callers shouldn't queue work items which can run for too long. +pub fn system() -> &'static Queue { + // SAFETY: `system_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_wq) } +} + +/// Returns the system high-priority work queue (`system_highpri_wq`). +/// +/// It is similar to the one returned by [`system`] but for work items which require higher +/// scheduling priority. +pub fn system_highpri() -> &'static Queue { + // SAFETY: `system_highpri_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_highpri_wq) } +} + +/// Returns the system work queue for potentially long-running work items (`system_long_wq`). +/// +/// It is similar to the one returned by [`system`] but may host long running work items. Queue +/// flushing might take relatively long. +pub fn system_long() -> &'static Queue { + // SAFETY: `system_long_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_long_wq) } +} + +/// Returns the system unbound work queue (`system_unbound_wq`). +/// +/// Workers are not bound to any specific CPU, not concurrency managed, and all queued work items +/// are executed immediately as long as `max_active` limit is not reached and resources are +/// available. +pub fn system_unbound() -> &'static Queue { + // SAFETY: `system_unbound_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_unbound_wq) } +} + +/// Returns the system freezable work queue (`system_freezable_wq`). +/// +/// It is equivalent to the one returned by [`system`] except that it's freezable. +pub fn system_freezable() -> &'static Queue { + // SAFETY: `system_freezable_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_freezable_wq) } +} + +/// Returns the system power-efficient work queue (`system_power_efficient_wq`). +/// +/// It is inclined towards saving power and is converted to "unbound" variants if the +/// `workqueue.power_efficient` kernel parameter is specified; otherwise, it is similar to the one +/// returned by [`system`]. +pub fn system_power_efficient() -> &'static Queue { + // SAFETY: `system_power_efficient_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_power_efficient_wq) } +} + +/// Returns the system freezable power-efficient work queue (`system_freezable_power_efficient_wq`). +/// +/// It is similar to the one returned by [`system_power_efficient`] except that is freezable. +pub fn system_freezable_power_efficient() -> &'static Queue { + // SAFETY: `system_freezable_power_efficient_wq` is a C global, always available. + unsafe { Queue::from_raw(bindings::system_freezable_power_efficient_wq) } +} From patchwork Thu Jun 1 13:49:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101966 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp378074vqr; Thu, 1 Jun 2023 07:35:54 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ78qij6BllbBKZYyYz9z3osoFCNewFYfwfUm6PwElA8a2rcXfnLU6UbH+St99sKIaqOc5aE X-Received: by 2002:a17:90a:e548:b0:250:9aee:563c with SMTP id ei8-20020a17090ae54800b002509aee563cmr8656095pjb.41.1685630154211; Thu, 01 Jun 2023 07:35:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685630154; cv=none; d=google.com; s=arc-20160816; b=Hj9r1MfLUMLI0+v6E4l5gFlRkRC0xT74PDq8OxliolH4D66Ldb1/6pC1igYpG4ACgV V/CCkh3931TW08FYtE9WYk+Uuwp4H7xCX+KqeHXi0VaGdOdrluZvQ9/+MYaXP13nIQUD E9Fvj3SClddTROhppKPqGHTSqYJHGXkj6CUTBudADYHuuXmdIR6vnTLUEHOz9s2ZUiD4 tsddjsNdfOqXMzYhcTQpkLYJD6IBh3eDck4O+tzKHV2fO+EsY4BFdqdUqRwSl3o+wmkV OgziScNX7jwlgZxDdgTw6iMSY/nFdIsvBrgXqn6vz+EVnn1Ff6OjRUSyEJOqIpETunEe S4Nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=8uFcGXdbIjrtd3/5CVHZnSQ6TrHuzg4doZPL2ZtyWy4=; b=bCfycfFGRY63u7PBQs+0Y0mgjN0qUf/KsZEKcSPXS1wbC8YIKSwzrClLP9YeMaVxqr OKV+4CHs02vzq0NHGEQl21/6EuCdB6vMhSXv+mbEAZWG8LFTvOvsDomq9i0JpuCfzuzq B2NCgj5YlwytkDVufz9a5qqOX197Dpl5+zO3I7LJPVd1Vu0n9lnYvaplx5QQ0I4mFNzy fqW8Q473DrwaFlLWpmRP6nwvw2A3xfpvmpLlUx0NCOlxvAq6cL00qEJk0/FNc7xgGxq5 f/sRcoKo3+DYquK2gVJwts74kwIBmTXIjnscnHTkOkpqZvbQizhyl0Df3pUh9SdqQBX+ hlAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=dxNWQhZA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id rm10-20020a17090b3eca00b002508889985fsi1247852pjb.95.2023.06.01.07.35.41; Thu, 01 Jun 2023 07:35:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=dxNWQhZA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233577AbjFANzi (ORCPT + 99 others); Thu, 1 Jun 2023 09:55:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51432 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233252AbjFANzg (ORCPT ); Thu, 1 Jun 2023 09:55:36 -0400 Received: from mail-ed1-x549.google.com (mail-ed1-x549.google.com [IPv6:2a00:1450:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C933513D for ; Thu, 1 Jun 2023 06:55:33 -0700 (PDT) Received: by mail-ed1-x549.google.com with SMTP id 4fb4d7f45d1cf-50a16ab50e6so705843a12.0 for ; Thu, 01 Jun 2023 06:55:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627732; x=1688219732; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=8uFcGXdbIjrtd3/5CVHZnSQ6TrHuzg4doZPL2ZtyWy4=; b=dxNWQhZAZ2nOkQBAkfySPOKTnAbreN9qU4AiDWVlxtii/UbqsQM/aUA9jDhRqp6JLo FwTHDqhxLsi73PzsHdmIpABgy8T/gAIsqlq530RntQCv4iiVdya5DxEVlexC+Hfaep4M OtFi+J48gNosyuyjFZYtuHgIbaFsvQZ/fuSzCR2yhPws0kdDLPyklwVfI66rVeMgLRxx kkDcX+A27gb4h+0ZLfBpAQU/wZZ4aBwNEwM175nY/aopxaAvlN3gzYRAvCUR5LE8NHYw 7FKLNgEHM2SpjGR0GqsZYve7A36AhAZsE/nWkeoTkl0TyA+pdisntr2zEZST19fayOBU 0Nxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627732; x=1688219732; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=8uFcGXdbIjrtd3/5CVHZnSQ6TrHuzg4doZPL2ZtyWy4=; b=E4p7vh+ysDjrd1/x9xygLudb5qHYyol8oB/9hKLay4/Xnf2F2CGde+OpKbvsa+WUXk oblusRopzXAUoL1Rnq/4xWp9L8N2yWWwHEMalRBGVWzruaREAu5EfP4G6uNRaNwmRq0i 3QDL4t+glyJ1x3SiLytnSGlKUkwkUGYAtDI/AVrNbmCA5Gebd5ZwHcFAWMpkE3j4rKN9 HQsVFMTcWZ53Kgq+BpULiL3cqbDi2ljooNdWSAXoR0ivf3xB26eLFeewUP89Mk3P2Ixb Zwy0BIDLzX9d8w+GPtiQ+XXF74BpmovoVJXYaP+BloqXWg6GKTpvDkn3SSMfIL1bX3CH 8Jzw== X-Gm-Message-State: AC+VfDxuMGqiaYsItQu+1eAmwNS2OIzZv8M7CbY6m7ItuU85/FeA7BiV oevr6KDlv+PtfMnbmvqUeLU6+3CXkjcqd4Y= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a50:bace:0:b0:514:8f21:5a0f with SMTP id x72-20020a50bace000000b005148f215a0fmr2787107ede.6.1685627732265; Thu, 01 Jun 2023 06:55:32 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:43 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-6-aliceryhl@google.com> Subject: [PATCH v2 5/8] rust: workqueue: add helper for defining work_struct fields From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767511324201843379?= X-GMAIL-MSGID: =?utf-8?q?1767511324201843379?= The main challenge with defining `work_struct` fields is making sure that the function pointer stored in the `work_struct` is appropriate for the work item type it is embedded in. It needs to know the offset of the `work_struct` field being used (even if there are several!) so that it can do a `container_of`, and it needs to know the type of the work item so that it can call into the right user-provided code. All of this needs to happen in a way that provides a safe API to the user, so that users of the workqueue cannot mix up the function pointers. There are three important pieces that are relevant when doing this: * The pointer type. * The work item struct. This is what the pointer points at. * The `work_struct` field. This is a field of the work item struct. This patch introduces a separate trait for each piece. The pointer type is given a `WorkItemPointer` trait, which pointer types need to implement to be usable with the workqueue. This trait will be implemented for `Arc` and `Box` in a later patch in this patchset. Implementing this trait is unsafe because this is where the `container_of` operation happens, but user-code will not need to implement it themselves. The work item struct should then implement the `WorkItem` trait. This trait is where user-code specifies what they want to happen when a work item is executed. It also specifies what the correct pointer type is. Finally, to make the work item struct know the offset of its `work_struct` field, we use a trait called `HasWork`. If a type implements this trait, then the type declares that, at the given offset, there is a field of type `Work`. The trait is marked unsafe because the OFFSET constant must be correct, but we provide an `impl_has_work!` macro that can safely implement `HasWork` on a type. The macro expands to something that only compiles if the specified field really has the type `Work`. It is used like this: ``` struct MyWorkItem { work_field: Work, } impl_has_work! { impl HasWork for MyWorkItem { self.work_field } } ``` Note that since the `Work` type is annotated with an id, you can have several `work_struct` fields by using a different id for each one. Co-developed-by: Gary Guo Signed-off-by: Gary Guo Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Benno Lossin --- rust/helpers.c | 8 ++ rust/kernel/workqueue.rs | 219 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 226 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index 81e80261d597..7f0c2fe2fbeb 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -26,6 +26,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -128,6 +129,13 @@ void rust_helper_put_task_struct(struct task_struct *t) } EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); +void rust_helper___INIT_WORK(struct work_struct *work, work_func_t func, + bool on_stack) +{ + __INIT_WORK(work, func, on_stack); +} +EXPORT_SYMBOL_GPL(rust_helper___INIT_WORK); + /* * We use `bindgen`'s `--size_t-is-usize` option to bind the C `size_t` type * as the Rust `usize` type, so we can use it in contexts where Rust diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index e37820f253f6..dbf0aab29a85 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -2,9 +2,34 @@ //! Work queues. //! +//! This file has two components: The raw work item API, and the safe work item API. +//! +//! One pattern that is used in both APIs is the `ID` const generic, which exists to allow a single +//! type to define multiple `work_struct` fields. This is done by choosing an id for each field, +//! and using that id to specify which field you wish to use. (The actual value doesn't matter, as +//! long as you use different values for different fields of the same struct.) Since these IDs are +//! generic, they are used only at compile-time, so they shouldn't exist in the final binary. +//! +//! # The raw API +//! +//! The raw API consists of the `RawWorkItem` trait, where the work item needs to provide an +//! arbitrary function that knows how to enqueue the work item. It should usually not be used +//! directly, but if you want to, you can use it without using the pieces from the safe API. +//! +//! # The safe API +//! +//! The safe API is used via the `Work` struct and `WorkItem` traits. Furthermore, it also includes +//! a trait called `WorkItemPointer`, which is usually not used directly by the user. +//! +//! * The `Work` struct is the Rust wrapper for the C `work_struct` type. +//! * The `WorkItem` trait is implemented for structs that can be enqueued to a workqueue. +//! * The `WorkItemPointer` trait is implemented for the pointer type that points at a something +//! that implements `WorkItem`. +//! //! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h) -use crate::{bindings, types::Opaque}; +use crate::{bindings, prelude::*, types::Opaque}; +use core::marker::{PhantomData, PhantomPinned}; /// A kernel work queue. /// @@ -106,6 +131,198 @@ unsafe fn __enqueue(self, queue_work_on: F) -> Self::EnqueueOutput F: FnOnce(*mut bindings::work_struct) -> bool; } +/// Defines the method that should be called directly when a work item is executed. +/// +/// Typically you would implement [`WorkItem`] instead. The `run` method on this trait will +/// usually just perform the appropriate `container_of` translation and then call into the `run` +/// method from the [`WorkItem`] trait. +/// +/// This trait is used when the `work_struct` field is defined using the [`Work`] helper. +/// +/// # Safety +/// +/// Implementers must ensure that [`__enqueue`] uses a `work_struct` initialized with the [`run`] +/// method of this trait as the function pointer. +/// +/// [`__enqueue`]: RawWorkItem::__enqueue +/// [`run`]: WorkItemPointer::run +pub unsafe trait WorkItemPointer: RawWorkItem { + /// Run this work item. + /// + /// # Safety + /// + /// The provided `work_struct` pointer must originate from a previous call to `__enqueue` where + /// the `queue_work_on` closure returned true, and the pointer must still be valid. + unsafe extern "C" fn run(ptr: *mut bindings::work_struct); +} + +/// Defines the method that should be called when this work item is executed. +/// +/// This trait is used when the `work_struct` field is defined using the [`Work`] helper. +pub trait WorkItem { + /// The pointer type that this struct is wrapped in. This will typically be `Arc` or + /// `Pin>`. + type Pointer: WorkItemPointer; + + /// The method that should be called when this work item is executed. + fn run(this: Self::Pointer); +} + +/// Links for a work item. +/// +/// This struct contains a function pointer to the `run` function from the [`WorkItemPointer`] +/// trait, and defines the linked list pointers necessary to enqueue a work item in a workqueue. +/// +/// Wraps the kernel's C `struct work_struct`. +/// +/// This is a helper type used to associate a `work_struct` with the [`WorkItem`] that uses it. +#[repr(transparent)] +pub struct Work { + work: Opaque, + _pin: PhantomPinned, + _inner: PhantomData, +} + +// SAFETY: Kernel work items are usable from any thread. +// +// We do not need to constrain `T` since the work item does not actually contain a `T`. +unsafe impl Send for Work {} +// SAFETY: Kernel work items are usable from any thread. +// +// We do not need to constrain `T` since the work item does not actually contain a `T`. +unsafe impl Sync for Work {} + +impl Work { + /// Creates a new instance of [`Work`]. + #[inline] + #[allow(clippy::new_ret_no_self)] + pub fn new() -> impl PinInit + where + T: WorkItem, + { + // SAFETY: The `WorkItemPointer` implementation promises that `run` can be used as the work + // item function. + unsafe { + kernel::init::pin_init_from_closure(move |slot| { + bindings::__INIT_WORK(Self::raw_get(slot), Some(T::Pointer::run), false); + Ok(()) + }) + } + } + + /// Get a pointer to the inner `work_struct`. + /// + /// # Safety + /// + /// The provided pointer must not be dangling and must be properly aligned. (But the memory + /// need not be initialized.) + #[inline] + pub unsafe fn raw_get(ptr: *const Self) -> *mut bindings::work_struct { + // SAFETY: The caller promises that the pointer is aligned and not dangling. + // + // A pointer cast would also be ok due to `#[repr(transparent)]`. We use `addr_of!` so that + // the compiler does not complain that the `work` field is unused. + unsafe { Opaque::raw_get(core::ptr::addr_of!((*ptr).work)) } + } +} + +/// Declares that a type has a [`Work`] field. +/// +/// # Safety +/// +/// The [`OFFSET`] constant must be the offset of a field in Self of type [`Work`]. The methods on +/// this trait must have exactly the behavior that the definitions given below have. +/// +/// [`Work`]: Work +/// [`OFFSET`]: HasWork::OFFSET +pub unsafe trait HasWork { + /// The offset of the [`Work`] field. + /// + /// [`Work`]: Work + const OFFSET: usize; + + /// Returns the offset of the [`Work`] field. + /// + /// This method exists because the [`OFFSET`] constant cannot be accessed if the type is not Sized. + /// + /// [`Work`]: Work + /// [`OFFSET`]: HasWork::OFFSET + #[inline] + fn get_work_offset(&self) -> usize { + Self::OFFSET + } + + /// Returns a pointer to the [`Work`] field. + /// + /// # Safety + /// + /// The provided pointer must point at a valid struct of type `Self`. + /// + /// [`Work`]: Work + #[inline] + unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work { + // SAFETY: The caller promises that the pointer is valid. + unsafe { (ptr as *mut u8).add(Self::OFFSET) as *mut Work } + } + + /// Returns a pointer to the struct containing the [`Work`] field. + /// + /// # Safety + /// + /// The pointer must point at a [`Work`] field in a struct of type `Self`. + /// + /// [`Work`]: Work + #[inline] + unsafe fn work_container_of(ptr: *mut Work) -> *mut Self + where + Self: Sized, + { + // SAFETY: The caller promises that the pointer points at a field of the right type in the + // right kind of struct. + unsafe { (ptr as *mut u8).sub(Self::OFFSET) as *mut Self } + } +} + +/// Used to safely implement the [`HasWork`] trait. +/// +/// # Examples +/// +/// ``` +/// use kernel::sync::Arc; +/// +/// struct MyStruct { +/// work_field: Work, +/// } +/// +/// impl_has_work! { +/// impl HasWork for MyStruct { self.work_field } +/// } +/// ``` +/// +/// [`HasWork`]: HasWork +#[macro_export] +macro_rules! impl_has_work { + ($(impl$(<$($implarg:ident),*>)? + HasWork<$work_type:ty $(, $id:tt)?> + for $self:ident $(<$($selfarg:ident),*>)? + { self.$field:ident } + )*) => {$( + // SAFETY: The implementation of `raw_get_work` only compiles if the field has the right + // type. + unsafe impl$(<$($implarg),*>)? $crate::workqueue::HasWork<$work_type $(, $id)?> for $self $(<$($selfarg),*>)? { + const OFFSET: usize = $crate::offset_of!(Self, $field) as usize; + + #[inline] + unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_type $(, $id)?> { + // SAFETY: The caller promises that the pointer is not dangling. + unsafe { + ::core::ptr::addr_of_mut!((*ptr).$field) + } + } + } + )*}; +} + /// Returns the system work queue (`system_wq`). /// /// It is the one used by `schedule[_delayed]_work[_on]()`. Multi-CPU multi-threaded. There are From patchwork Thu Jun 1 13:49:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101951 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp357174vqr; Thu, 1 Jun 2023 07:08:29 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ68i289MXS8XD7uposMFCyEw5a00qSW4RYua0PC5K37CBuQGu7e6sonot8Xd7hQ58b6MB2+ X-Received: by 2002:a05:6a20:12cc:b0:110:7edc:fb50 with SMTP id v12-20020a056a2012cc00b001107edcfb50mr8560872pzg.9.1685628509248; Thu, 01 Jun 2023 07:08:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685628509; cv=none; d=google.com; s=arc-20160816; b=K5ZqbP/qXIETyHuYohPAxY/SY9uu4JMtmd9wrbBeTpKRf91+yDCvyRjEFwUbsxNKIG WJhbJEL8NF3Yevmb7TV0ETjLkyc/vrM5VPnk7VfNsAQhN8x33P1ASCBXgr1kinKcBBXL 4DXAulPiO6n8Cr9RVEEmSAzyDCRrfWZRrhzNu/wM638Tdhe7byf0wQ7qWwTFCc2wFm9/ sGYq9tEGJbTxM17kGvDpcq+viJ7nlLQMW3CYJ8Zi9WDTxTYiSf+3Gaygs09rBS2rtgHf zENBYlAAv/DVx6xOY5TWrXvnUo3qedqb/WUIhsuE3eqKXBrPqHgD2/CEMDYG0JEf/4Bn 5AMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=TyRNG5KT1C+kxxh+8DvNZVfySdIBr+c+luuNQvW24B8=; b=SnMCdU1FoW67e7FMkcv4SnsDJ8hd47p/aooFBHJnpFWo3Ww+zvfXy0YsgU4P5TFl/9 57tjVrJ3UJCTF6JCpbISH+5wbXV3E/GXsd990GVuLyTT18VumanTP0lCU6qZsXbgQYr7 JUlj08DOGQmTdu6fSXM/N1/C66RcQalvJqp+E9sDqPeE8/LlPfQXDnTuOMrEN69Jra4Y r3tE9BnSlWyBkkyeCuwtcgBmXTnaM2IwlWUzeLKIa5Fu+kjlxdXunxD4DJPgCBEXruYo Xg/t7GZrl9VWaSFagUnW2O0QPDTo4bGkZ5PSdOlcNyMHll9ZVAqZHj10+vywa2+nDjur wMvA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=rqoKpkOt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id a63-20020a639042000000b0053b64127cddsi2937454pge.212.2023.06.01.07.07.59; Thu, 01 Jun 2023 07:08:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=rqoKpkOt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233545AbjFAN4R (ORCPT + 99 others); Thu, 1 Jun 2023 09:56:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232769AbjFAN4P (ORCPT ); Thu, 1 Jun 2023 09:56:15 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E1E3E129 for ; Thu, 1 Jun 2023 06:56:13 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-565c380565dso22593137b3.1 for ; Thu, 01 Jun 2023 06:56:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627773; x=1688219773; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=TyRNG5KT1C+kxxh+8DvNZVfySdIBr+c+luuNQvW24B8=; b=rqoKpkOtbw5E7aZUP5vKjWc3Rud11Cj869FSLBYeNDUpqqAOXnkZIPl7lj5T2v5p7s DmMa94afp5CNZFk1ywR4ew+ffsOd7nOjrFz827+LCZEp8XI49xI9Wdw9RtCEvPkuo8im TbhBhsVdo138vg3Nl4AMaccmsNOCCPZENyu59Kaii+poHD6Mc9UdWgsN3jNMxvyt2W4I y2/H0+6GzKgtGlccHAiV83rBObv6Oqk4nXU9rcSvjnEk0GniwrycnB1qvh3JpmxgcBKs vNmUwJcJLMtZRaxTJ5rpjwixRZNRXubZmOhOpkg300KRq2lF92feTXVc6m+zgHMAsqIc FyaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627773; x=1688219773; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=TyRNG5KT1C+kxxh+8DvNZVfySdIBr+c+luuNQvW24B8=; b=Av8fzN6acgq9cqPKg8w5NP7W/jPbdPu86oBTUHO74Vf3sOGtJy7tgkixDikDpMuhNS PltCeeHMTszdkiKw8feSgiPyMqffr4+y1/oVAopS5B0vXs1/OV28kc+cFtPfgUqEbNR2 64pDkwjkE9bfo8pyUeVBKYnqSWINJvzYNQPlqVt8+Cv1P5gWes6e3UAcSC3h5cvX0LIJ cGgV+HHOA3qimD6DdeANSIzV2rvNRZjoYSWA2271Nc40aHtNPEYkygV84Ggc8rPtGzl1 ySNXBMhq00xnWpQRWjAc8NHVZPri2vtNKGbxYvhy/9+01hwfwkCl+Srz94lpj9MWinE5 EYdg== X-Gm-Message-State: AC+VfDyOGNxF2hk76dJER4GeGwKikfpjLujBxaRVSYoz0jGPEv/1OVkL A35TSaYNCGXPJH44Tiv+4JXSz8Vwf49Fgd4= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a81:7813:0:b0:561:ec3e:62fd with SMTP id t19-20020a817813000000b00561ec3e62fdmr1402978ywc.5.1685627773081; Thu, 01 Jun 2023 06:56:13 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:44 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-7-aliceryhl@google.com> Subject: [PATCH v2 6/8] rust: workqueue: implement `WorkItemPointer` for pointer types From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767509600066783630?= X-GMAIL-MSGID: =?utf-8?q?1767509600066783630?= This implements the `WorkItemPointer` trait for the pointer types that you are likely to use the workqueue with. The `Arc` type is for reference counted objects, and the `Pin>` type is for objects where the caller has exclusive ownership of the object. Co-developed-by: Gary Guo Signed-off-by: Gary Guo Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Benno Lossin --- rust/kernel/workqueue.rs | 97 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index dbf0aab29a85..f06a2f036d8b 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -28,8 +28,10 @@ //! //! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h) -use crate::{bindings, prelude::*, types::Opaque}; +use crate::{bindings, prelude::*, sync::Arc, types::Opaque}; +use alloc::boxed::Box; use core::marker::{PhantomData, PhantomPinned}; +use core::pin::Pin; /// A kernel work queue. /// @@ -323,6 +325,99 @@ unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_typ )*}; } +unsafe impl WorkItemPointer for Arc +where + T: WorkItem, + T: HasWork, +{ + unsafe extern "C" fn run(ptr: *mut bindings::work_struct) { + // SAFETY: The `__enqueue` method always uses a `work_struct` stored in a `Work`. + let ptr = ptr as *mut Work; + // SAFETY: This computes the pointer that `__enqueue` got from `Arc::into_raw`. + let ptr = unsafe { T::work_container_of(ptr) }; + // SAFETY: This pointer comes from `Arc::into_raw` and we've been given back ownership. + let arc = unsafe { Arc::from_raw(ptr) }; + + T::run(arc) + } +} + +unsafe impl RawWorkItem for Arc +where + T: WorkItem, + T: HasWork, +{ + type EnqueueOutput = Result<(), Self>; + + unsafe fn __enqueue(self, queue_work_on: F) -> Self::EnqueueOutput + where + F: FnOnce(*mut bindings::work_struct) -> bool, + { + // Casting between const and mut is not a problem as long as the pointer is a raw pointer. + let ptr = Arc::into_raw(self) as *mut T; + + // SAFETY: Pointers into an `Arc` point at a valid value. + let work_ptr = unsafe { T::raw_get_work(ptr) }; + // SAFETY: `raw_get_work` returns a pointer to a valid value. + let work_ptr = unsafe { Work::raw_get(work_ptr) }; + + if queue_work_on(work_ptr) { + Ok(()) + } else { + // SAFETY: The work queue has not taken ownership of the pointer. + Err(unsafe { Arc::from_raw(ptr) }) + } + } +} + +unsafe impl WorkItemPointer for Pin> +where + T: WorkItem, + T: HasWork, +{ + unsafe extern "C" fn run(ptr: *mut bindings::work_struct) { + // SAFETY: The `__enqueue` method always uses a `work_struct` stored in a `Work`. + let ptr = ptr as *mut Work; + // SAFETY: This computes the pointer that `__enqueue` got from `Arc::into_raw`. + let ptr = unsafe { T::work_container_of(ptr) }; + // SAFETY: This pointer comes from `Arc::into_raw` and we've been given back ownership. + let boxed = unsafe { Box::from_raw(ptr) }; + // SAFETY: The box was already pinned when it was enqueued. + let pinned = unsafe { Pin::new_unchecked(boxed) }; + + T::run(pinned) + } +} + +unsafe impl RawWorkItem for Pin> +where + T: WorkItem, + T: HasWork, +{ + type EnqueueOutput = (); + + unsafe fn __enqueue(self, queue_work_on: F) -> Self::EnqueueOutput + where + F: FnOnce(*mut bindings::work_struct) -> bool, + { + // SAFETY: We're not going to move `self` or any of its fields, so its okay to temporarily + // remove the `Pin` wrapper. + let boxed = unsafe { Pin::into_inner_unchecked(self) }; + let ptr = Box::into_raw(boxed); + + // SAFETY: Pointers into a `Box` point at a valid value. + let work_ptr = unsafe { T::raw_get_work(ptr) }; + // SAFETY: `raw_get_work` returns a pointer to a valid value. + let work_ptr = unsafe { Work::raw_get(work_ptr) }; + + if !queue_work_on(work_ptr) { + // SAFETY: This method requires exclusive ownership of the box, so it cannot be in a + // workqueue. + unsafe { ::core::hint::unreachable_unchecked() } + } + } +} + /// Returns the system work queue (`system_wq`). /// /// It is the one used by `schedule[_delayed]_work[_on]()`. Multi-CPU multi-threaded. There are From patchwork Thu Jun 1 13:49:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101950 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp357155vqr; Thu, 1 Jun 2023 07:08:27 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5kYNF+cD2qoUN9voSxnWgD3vxxBxOAuYGYVmId64uM7Rwqplgt1ZzKD4OJ1x/2tNzwqaa1 X-Received: by 2002:a05:6a00:18a9:b0:64d:b0d8:a396 with SMTP id x41-20020a056a0018a900b0064db0d8a396mr8551489pfh.7.1685628507583; Thu, 01 Jun 2023 07:08:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685628507; cv=none; d=google.com; s=arc-20160816; b=zSUmvkYadZS80FHo5V26O8FzJpPt9zJLV535jdS6BFC6usUnHnA3pxHWNLKGi10o0n yNK6GgQOfHqjTYKvdzQ91PGjflNd680rBFGJBVADbQVDeb7otFBI0YJY048+4i9A/SwS Zr7tLrbfND00lOJlp24MxZ7IS9OHEIJTqCgc3w9eBmiQO0p/SHLXPGFR/E0yKfqUJkq5 eObXTr8YwcPn9KKYcFyqttetkOEQQdg+EkIG2H87pLajd7GLb8kehr4zdPMOKeUpFzRI k1IrSe1qWLgVP7vF6yT0wTtPy+pCcmKlapbV8D6bkWwK6LwLerWYAC3PkLjTOVrrf7DW MqXA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=vB1KTXT+BDPTSPss1nKfZFCllt9cnJRUrJkIndsk9bQ=; b=d2UlrlEWw0w7nGc8tO3rz77O9y7Bi95vC0ilIN3PKr89NGl1LmKJUcDE9aiZGuBHHp ew3xonjvO8OahSfPflxLr12WKj2D9BQrc5KH8xYIJPhk1jBpPHPW0k8P0hHfdn3v5A89 KXsy1wPzcY4IZEOzpUDItCk4U5omNPSeCWWUvCkIZY3t0YLAubZSMvqxfu6bS4SOQJW+ 5aPaShnt4D/MyegIEIR8Pugvt1+qUy5COxTpEurgHnWpZcdahmtEKa3bfHSab3BDYyfb iksjRJ4WzNf/A/XYcVtvJ1cSrAV89AURe091EIowCxMLu+3ecke33EPA42faRyl+Xwuc T8Jw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b="ONUw1Bi/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d25-20020a637359000000b0052c7ad564e2si441171pgn.707.2023.06.01.07.07.51; Thu, 01 Jun 2023 07:08:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b="ONUw1Bi/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233368AbjFAN4x (ORCPT + 99 others); Thu, 1 Jun 2023 09:56:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232769AbjFAN4u (ORCPT ); Thu, 1 Jun 2023 09:56:50 -0400 Received: from mail-ej1-x649.google.com (mail-ej1-x649.google.com [IPv6:2a00:1450:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5DBAEFC for ; Thu, 1 Jun 2023 06:56:49 -0700 (PDT) Received: by mail-ej1-x649.google.com with SMTP id a640c23a62f3a-96faa650a3fso64714866b.0 for ; Thu, 01 Jun 2023 06:56:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627808; x=1688219808; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=vB1KTXT+BDPTSPss1nKfZFCllt9cnJRUrJkIndsk9bQ=; b=ONUw1Bi/LF6RsZlr45Sb+TKYR/o9wrpaSOn2lrXAM6QYiczLPUguB/OtTWl2nFQb/z QHCJFovGIHfcYE7ZKxME4rHu0QrQ4t0lkAsZaKzOuoP35MgMHVzXbqZ9Js6mYq3jSxzW iQhJQID+sbpuY6rX1Kr1tInXmFVQ8bpfhl7KPdzG/3nj30erauVwt9zGGqKaupzxvtkk zJUHWqC/9bRRmif13gTcB23wiU9s0WW2SS+C2rW0b1KB96pBbzxeXvLAmsDK+Q6B9hpm WC4RIxiwCa89hBCrOaMs11hNEoZ8Mf+uzlLbeKiVPw4rmcJHNzBDHeol1J09Swzd8q5c 6l1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627808; x=1688219808; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vB1KTXT+BDPTSPss1nKfZFCllt9cnJRUrJkIndsk9bQ=; b=lo9haCHBe4Rv6oEM9rz/yWuRkLtX4NNucTR/AFkW/YrQljmNPcWujJNGDCKyMJ7x3N 8FyRvbZxSVD/PHo4QmwX8wKZ6abWlrVSwbsnGjaxidjb+QG1L0z5dj7NQ4GuMqh+SSZ5 pRUbgrr+K9Zkdmvy9vkUDoo3G7J14MN7afJSzgpeJhLZ+s2px0nP2NcxLwL/mosJV9rC UwnFBS6yZEusClaDftEJk6DMMwBD5m6CMB50QR7BQJ79IrZzJa2RcD07Wh1aB5Qw1bdm PefQhqNDuCVNzas1OcfoITXD8aT6yH1JRh2Rw5tQ1NtOF/H75muZhYu4oXQ0HGW7a1Ei OVaw== X-Gm-Message-State: AC+VfDyj08R6iOJjfqrMALln2hzWZ8npmxFn2eReu7GES+Kok4krqcWk VeqNKjRBSe8NxmfKsLY9YmroykodpqnVnlI= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:907:2cd9:b0:973:867b:399e with SMTP id hg25-20020a1709072cd900b00973867b399emr2256552ejc.4.1685627807883; Thu, 01 Jun 2023 06:56:47 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:45 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-8-aliceryhl@google.com> Subject: [PATCH v2 7/8] rust: workqueue: add `try_spawn` helper method From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PDS_OTHER_BAD_TLD, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767509597701654408?= X-GMAIL-MSGID: =?utf-8?q?1767509597701654408?= This adds a convenience method that lets you spawn a closure for execution on a workqueue. This will be the most convenient way to use workqueues, but it is fallible because it needs to allocate memory. Co-developed-by: Gary Guo Signed-off-by: Gary Guo Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Benno Lossin --- rust/kernel/workqueue.rs | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index f06a2f036d8b..c302e8b8624b 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -29,6 +29,7 @@ //! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h) use crate::{bindings, prelude::*, sync::Arc, types::Opaque}; +use alloc::alloc::AllocError; use alloc::boxed::Box; use core::marker::{PhantomData, PhantomPinned}; use core::pin::Pin; @@ -87,6 +88,44 @@ pub fn enqueue(&self, w: W) -> W::EnqueueOutput }) } } + + /// Tries to spawn the given function or closure as a work item. + /// + /// This method can fail because it allocates memory to store the work item. + pub fn try_spawn(&self, func: T) -> Result<(), AllocError> { + let init = pin_init!(ClosureWork { + work <- Work::new(), + func: Some(func), + }); + + self.enqueue(Box::pin_init(init).map_err(|_| AllocError)?); + Ok(()) + } +} + +/// A helper type used in `try_spawn`. +#[pin_data] +struct ClosureWork { + #[pin] + work: Work>, + func: Option, +} + +impl ClosureWork { + fn project(self: Pin<&mut Self>) -> &mut Option { + // SAFETY: The `func` field is not structurally pinned. + unsafe { &mut self.get_unchecked_mut().func } + } +} + +impl WorkItem for ClosureWork { + type Pointer = Pin>; + + fn run(mut this: Pin>) { + if let Some(func) = this.as_mut().project().take() { + (func)() + } + } } /// A raw work item. @@ -325,6 +364,10 @@ unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_typ )*}; } +impl_has_work! { + impl HasWork for ClosureWork { self.work } +} + unsafe impl WorkItemPointer for Arc where T: WorkItem, From patchwork Thu Jun 1 13:49:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 101957 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp366867vqr; Thu, 1 Jun 2023 07:19:43 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4CFjYFMCNpbpBPYxUg+f5aQH63uRK9qVzz75apDRUGzNPN1mKdhPL+ydFIXCWnPPogQKxJ X-Received: by 2002:a17:902:be0a:b0:1b1:a7d8:a3a1 with SMTP id r10-20020a170902be0a00b001b1a7d8a3a1mr917859pls.21.1685629183345; Thu, 01 Jun 2023 07:19:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685629183; cv=none; d=google.com; s=arc-20160816; b=ODOfjhziWjI+Y9Lb7f0TmEyjdlfckSP9RpyqjbkYqygf5jTzpEeUTpOzCDsQOCN1Td dWVg110Zk0ADNcfR3Plw0esp5sTGrM8apB5rVV+5BK2flIUxJ+HDr3AhWb2ipQq+ZWu5 CjHse7fCSDa1uSQaHN0zqEIGAOiFvSxogCsa0v0ubEfi1t6FgdjtbCO9bPEIaUT/2nSC wbgeh+Vp7Es5IUdZFmKO6FZldpC/k1a3IUjOUPBQj+rgQ2ctn7w/RZyWrMUTGaZ7IWwl Gv6PhBdEv9evmIdWFfKhjWhNXDL6Nsh7g4IddHxRZKc+Cardb62Z2yOJaDonw7kej7yH xHog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=Il50p8nZECxcQJDqUwkg/ZOtCLHgjGH7eHBvIr+OJqA=; b=qVo8SyN7kWgw4ZKZfZSJAB8Jnsw/xkDEk4LpaTvOMXQGmFOGDAVopkEyy12DzkUigA ymdwZq0qGgvGu4g4CdxB5YEcZlWUHuYDZ0Fa8F9qPIblRfhzmHNct8+oUNceBqMr4dkF rDsfhY1dXARsMuB01b457hbbAf0UqrYu7kIGZDEax8nPNwSPRBrxGI1/wgWyTR/P+vNn 7ppeFKkQPA6RaHXWZ7g3ZRcow+7jB8iTiPb0x4+Knjgh20G4Fe+8kq+DMHSFqhYV+Qw7 2Iond3d7O9Okq3Mj1w3FI4h3PNHf9xhd4jWX7/ppWveCbeCAhGa5g7hfNVmDRG7Hw7b4 Hw4w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=woEEVeXR; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h11-20020a170902704b00b001b035ce0653si2733740plt.380.2023.06.01.07.19.28; Thu, 01 Jun 2023 07:19:43 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=woEEVeXR; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233282AbjFAN5v (ORCPT + 99 others); Thu, 1 Jun 2023 09:57:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232769AbjFAN5t (ORCPT ); Thu, 1 Jun 2023 09:57:49 -0400 Received: from mail-ed1-x54a.google.com (mail-ed1-x54a.google.com [IPv6:2a00:1450:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C7D66FC for ; Thu, 1 Jun 2023 06:57:48 -0700 (PDT) Received: by mail-ed1-x54a.google.com with SMTP id 4fb4d7f45d1cf-506b21104faso684004a12.1 for ; Thu, 01 Jun 2023 06:57:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1685627867; x=1688219867; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Il50p8nZECxcQJDqUwkg/ZOtCLHgjGH7eHBvIr+OJqA=; b=woEEVeXRdIaNOBTuxaLQGdFXHzH0XEF+niu0dsO9UeJfo1436BCJtmE9PIaMuBm1Gw 2TlWaCgo7du6wZP7cPNRfr2NARZW9QeUN+Kyf/Oo6lnJMqGqm6GXcV5SZ+/8/PFjwFym 1TX75spnYLhrC7D6K6gHyZYI+3ApgUJsV3Gz/G1Oux0qwDrekdin+1Hf2uXbma6agOuy xQdsi5wTSib1B2vfRftoFo/X8JejRIQDj5V8tDbJ6tSX2QeWnIVyIZzqyr9/i/ur/5G1 aC7RuAJ9WiyhVR+6T1jXJDvmY7YeW0blKboqYpu4UoLPr3c77ZS/i6p5z0Yei5sMJm8a WcRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685627867; x=1688219867; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Il50p8nZECxcQJDqUwkg/ZOtCLHgjGH7eHBvIr+OJqA=; b=fN0qtUcnsRGtDD0TCKCaSC2M5fK6yDKvsGpDr4WUZnIeUPj3iVfXjOohoxEuJVqxcd aRiGsqy8lu4DnPqeqOXs28Z0jmtSJkuIi7NRtODjyqf+R3P4B/e2P0RIfYSUjuEFxe8M gpYvK2fPL7g2c8Ymd11JlLu/YwplOr5gDckdz2Ty4B+vvtUptnYdc81zTDVsOoY1YFTu ZfmC0VCtEWgExtnXv4ipBDemIB9He6t/t5EsnLpSNnQMI+w6BiE9l1tERHaIjZX9l4Dr yMfxEX6qSOaj4znHmIoL6Y+hTuuK4gCQdCHTZfZNDBdipwPRg/1Nc+Y+PhoCCMTp7Bqh 4juA== X-Gm-Message-State: AC+VfDzfXQgTS34JsArPPOTA0rXDU/xa6p8zxXlqaa5IibMf2xF+oDhu 1xYxocv+aOuDqDelaC8b7LcMf1R3Ax5Aduk= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a50:ab09:0:b0:50b:c88a:f7cd with SMTP id s9-20020a50ab09000000b0050bc88af7cdmr2009edc.4.1685627867420; Thu, 01 Jun 2023 06:57:47 -0700 (PDT) Date: Thu, 1 Jun 2023 13:49:46 +0000 In-Reply-To: <20230601134946.3887870-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230601134946.3887870-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog Message-ID: <20230601134946.3887870-9-aliceryhl@google.com> Subject: [PATCH v2 8/8] rust: workqueue: add examples From: Alice Ryhl To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Wedson Almeida Filho , Tejun Heo , Lai Jiangshan , Alex Gaynor , Boqun Feng , Gary Guo , " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " , Benno Lossin , Alice Ryhl , linux-kernel@vger.kernel.org, patches@lists.linux.dev X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PDS_OTHER_BAD_TLD, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767510306197739618?= X-GMAIL-MSGID: =?utf-8?q?1767510306197739618?= This adds two examples of how to use the workqueue. The first example shows how to use it when you only have one `work_struct` field, and the second example shows how to use it when you have multiple `work_struct` fields. Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Gary Guo Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Andreas Hindborg (Samsung) Reviewed-by: Benno Lossin --- rust/kernel/workqueue.rs | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index c302e8b8624b..cefcf43ff40e 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -26,6 +26,110 @@ //! * The `WorkItemPointer` trait is implemented for the pointer type that points at a something //! that implements `WorkItem`. //! +//! ## Example +//! +//! This example defines a struct that holds an integer and can be scheduled on the workqueue. When +//! the struct is executed, it will print the integer. Since there is only one `work_struct` field, +//! we do not need to specify ids for the fields. +//! +//! ``` +//! use kernel::prelude::*; +//! use kernel::sync::Arc; +//! use kernel::workqueue::{self, Work, WorkItem}; +//! +//! #[pin_data] +//! struct MyStruct { +//! value: i32, +//! #[pin] +//! work: Work, +//! } +//! +//! impl_has_work! { +//! impl HasWork for MyStruct { self.work } +//! } +//! +//! impl MyStruct { +//! fn new(value: i32) -> Result> { +//! Arc::pin_init(pin_init!(MyStruct { +//! value, +//! work <- Work::new(), +//! })) +//! } +//! } +//! +//! impl WorkItem for MyStruct { +//! type Pointer = Arc; +//! +//! fn run(this: Arc) { +//! pr_info!("The value is: {}", this.value); +//! } +//! } +//! +//! /// This method will enqueue the struct for execution on the system workqueue, where its value +//! /// will be printed. +//! fn print_later(val: Arc) { +//! let _ = workqueue::system().enqueue(val); +//! } +//! ``` +//! +//! The following example shows how multiple `work_struct` fields can be used: +//! +//! ``` +//! use kernel::prelude::*; +//! use kernel::sync::Arc; +//! use kernel::workqueue::{self, Work, WorkItem}; +//! +//! #[pin_data] +//! struct MyStruct { +//! value_1: i32, +//! value_2: i32, +//! #[pin] +//! work_1: Work, +//! #[pin] +//! work_2: Work, +//! } +//! +//! impl_has_work! { +//! impl HasWork for MyStruct { self.work_1 } +//! impl HasWork for MyStruct { self.work_2 } +//! } +//! +//! impl MyStruct { +//! fn new(value_1: i32, value_2: i32) -> Result> { +//! Arc::pin_init(pin_init!(MyStruct { +//! value_1, +//! value_2, +//! work_1 <- Work::new(), +//! work_2 <- Work::new(), +//! })) +//! } +//! } +//! +//! impl WorkItem<1> for MyStruct { +//! type Pointer = Arc; +//! +//! fn run(this: Arc) { +//! pr_info!("The value is: {}", this.value_1); +//! } +//! } +//! +//! impl WorkItem<2> for MyStruct { +//! type Pointer = Arc; +//! +//! fn run(this: Arc) { +//! pr_info!("The second value is: {}", this.value_2); +//! } +//! } +//! +//! fn print_1_later(val: Arc) { +//! let _ = workqueue::system().enqueue::, 1>(val); +//! } +//! +//! fn print_2_later(val: Arc) { +//! let _ = workqueue::system().enqueue::, 2>(val); +//! } +//! ``` +//! //! C header: [`include/linux/workqueue.h`](../../../../include/linux/workqueue.h) use crate::{bindings, prelude::*, sync::Arc, types::Opaque};