Message ID | 20230517203119.3160435-1-aliceryhl@google.com |
---|---|
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp36685vqo; Wed, 17 May 2023 13:33:12 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4YeJ+7digGI5LBJIfI6prhymMV4OGbzyjaLfXGEr+072y09b42Whm7O9yHKy+vTCIyBhN3 X-Received: by 2002:a17:902:8a8d:b0:1ac:750e:33ef with SMTP id p13-20020a1709028a8d00b001ac750e33efmr165830plo.3.1684355591730; Wed, 17 May 2023 13:33:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684355591; cv=none; d=google.com; s=arc-20160816; b=la5Tqg2tR8NAnYUpzw85MZz6bFlBO/iJu7/AuhoNSIYjFWD1hE2dHDyc5Y1MYQf1ed 1uco+Erk67EcCxar5S7bfsRQNOgRkVh8ZGAGlxtjAg7GKwdksP4OQBBz3IAp0wYzydXo gKW347/X84JIVRT08PTWq4A2jZlRzE8ezSqHQvLRFQH/WngqVFXqfUdQnAx3fimcyHx1 xakSSj2/UxKLXItm8yeH/UOrPb4CkVOLEcLoso8/09P/KGns3UYe+n55syJBXvGhiErV VJWPFkEwxWMWwvQsW4tJDuvrBbyOMKuvNZj6lLxp2sG8JxdKYslwobPohCO3j3F9KzcS I9lg== 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:mime-version:date :dkim-signature; bh=lH+GB88mGkyXoacAsII55I8gutXKBDvKTQDFdPjI6tA=; b=sAzrbfh59zll2sKG8K9bAtkJ5lQ7/mGpMQCO4g9bHEvQ2CtcuUBxp9lTgsvBknpT+6 MljD74ulIS151YKVgnTIFJlhcdSnYoqRb+GZNcPtv6GkT2V5s9h1uovU1fMYSDUKyxKA N3GGYtJQFm8chtqpxnaRXuNgt8cU4DoRyK9U9MpnMsDpdAtnqR8Z9Z1Jtmk+SN6gG2qr lVS9JnmwvkpUMnKULb0JY+sh6Mt1N2fJxhgy/nagfWpKZblCkY8b+41BHRdTy9WhcgeY 2qdV2wA59jtdxmtrDtmMVT5XpffSBhC48ovBifPthsJXK0e70Xj0qyutidGsyPpdXpWd CStg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=iA2BlPMq; 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 lg13-20020a170902fb8d00b0019e2eb49236si19686027plb.229.2023.05.17.13.32.59; Wed, 17 May 2023 13:33:11 -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=iA2BlPMq; 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 S229775AbjEQUbh (ORCPT <rfc822;abdi.embedded@gmail.com> + 99 others); Wed, 17 May 2023 16:31:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229506AbjEQUba (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 17 May 2023 16:31:30 -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 0EDB47AA9 for <linux-kernel@vger.kernel.org>; Wed, 17 May 2023 13:31:23 -0700 (PDT) Received: by mail-ed1-x54a.google.com with SMTP id 4fb4d7f45d1cf-50ddef368e4so1347720a12.0 for <linux-kernel@vger.kernel.org>; Wed, 17 May 2023 13:31:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1684355481; x=1686947481; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date:message-id:reply-to; bh=lH+GB88mGkyXoacAsII55I8gutXKBDvKTQDFdPjI6tA=; b=iA2BlPMqXXvqmmp3XPbvS7PLetJ5ETCu6u7dP0UxkrlowV8oa2J3RE2PCj8b/Qpxxu U6IF3gWzURzAG9NFlWH1u/zSdMyiL08wwcLJNrZKdYlzpVAGnlv8ndQrnJlPcD0SVME/ VChEVvPcEWnniohJDXcaCGfRWgicgKyXck88tVTYfzygqlSwkdfZCNMonNMrQ7tNjjhj UTWPo7cs+3zWxknZ6ZtvRw8SC/fAIjuZiS54vc6APSnRpga9SKVmAhj+d0coqTkc5OLj jXpU2I+e18A0d2/tTlASL7C9q0TrS9/sPTOMfsyPdttoIoKk1xl/KgkWH67RraMnNaNS LDFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684355481; x=1686947481; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=lH+GB88mGkyXoacAsII55I8gutXKBDvKTQDFdPjI6tA=; b=E4CTlSm/dHp+QG1Og1zn281ODBkGRmg4kTHNianeXmvmwanfnjGfEZRJOMOFX6GhRI JVw7TGQ44+mwLdMor3PGjV5FttUBS7n54qwAwFShpfXxH2qTJZS4dj/46Kx9VM8WIT92 DHB8z72Xn3B2buQ1sFe/kD2rv9a15O2TAS+FM1NGOkrOobkKqf3hCW2qqgG1UyUpWXrQ ANQPvevgXzGr8BSAyf/pWtiCW/yTXp5H8HHafOvVz+lhSaX3Luu2UdusfQcSva8S0oD/ CpDZeIQeBfqlJWKSaEqEN5UZC4oL+ofthw1O0qe8a9EYTpViByRhGxpl452S323RtDsp 2G7g== X-Gm-Message-State: AC+VfDxlosy/CRXz0o2UkUxWxZk4tmR/7+h7SEnyn8FtN6LWXEVPhkwz x8tv0nnb6j5jhG26NBrCRqGVWI5a7oM88w0= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a50:8d1b:0:b0:504:7684:a23c with SMTP id s27-20020a508d1b000000b005047684a23cmr1511969eds.8.1684355481334; Wed, 17 May 2023 13:31:21 -0700 (PDT) Date: Wed, 17 May 2023 20:31:12 +0000 Mime-Version: 1.0 X-Mailer: git-send-email 2.40.1.606.ga4b1b128d6-goog Message-ID: <20230517203119.3160435-1-aliceryhl@google.com> Subject: [PATCH v1 0/7] Bindings for the workqueue From: Alice Ryhl <aliceryhl@google.com> To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda <ojeda@kernel.org>, Wedson Almeida Filho <wedsonaf@gmail.com>, Tejun Heo <tj@kernel.org>, Lai Jiangshan <jiangshanlai@gmail.com>, Alex Gaynor <alex.gaynor@gmail.com>, Boqun Feng <boqun.feng@gmail.com>, Gary Guo <gary@garyguo.net>, " =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= " <bjorn3_gh@protonmail.com>, Benno Lossin <benno.lossin@proton.me>, Alice Ryhl <aliceryhl@google.com>, linux-kernel@vger.kernel.org, patches@lists.linux.dev Content-Type: text/plain; charset="UTF-8" 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,URIBL_BLOCKED, 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766174849165483663?= X-GMAIL-MSGID: =?utf-8?q?1766174849165483663?= |
Series |
Bindings for the workqueue
|
|
Message
Alice Ryhl
May 17, 2023, 8:31 p.m. UTC
This patchset contains bindings for the kernel workqueue. One of the primary goals behind the design used in this patch is that we must support embedding the `work_struct` as a field in user-provided types, because this allows you to submit things to the workqueue without having to allocate, making the submission infallible. If we didn't have to support this, then the patch would be much simpler. One of the main things that make it complicated is that we must ensure that the function pointer in the `work_struct` is compatible with the struct it is contained within. This patch could be significantly simplified if we already had the field projection bindings. However, we have decided to upstream the current version that does not depend on field projection first - the PR that introduces field projections will then include a commit that simplifies the workqueue implementation. (In particular, it would simplify the 5th patch in this series.) The first version of the workqueue bindings was written by Wedson, but I have rewritten much of it so that it uses the pin-init infrastructure and can be used with containers other than `Arc`. Alice Ryhl (4): rust: workqueue: add low-level workqueue bindings rust: workqueue: add helper for defining work_struct fields rust: workqueue: add safe API to workqueue rust: workqueue: add `try_spawn` helper method Wedson Almeida Filho (3): rust: add offset_of! macro rust: sync: add `Arc::{from_raw, into_raw}` rust: workqueue: define built-in queues rust/helpers.c | 8 + rust/kernel/lib.rs | 37 ++ rust/kernel/sync/arc.rs | 44 +++ rust/kernel/workqueue.rs | 715 +++++++++++++++++++++++++++++++++++++++ scripts/Makefile.build | 2 +- 5 files changed, 805 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/workqueue.rs base-commit: ac9a78681b921877518763ba0e89202254349d1b
Comments
Hello, Alice. On Wed, May 17, 2023 at 08:31:12PM +0000, Alice Ryhl wrote: > This patchset contains bindings for the kernel workqueue. > > One of the primary goals behind the design used in this patch is that we > must support embedding the `work_struct` as a field in user-provided > types, because this allows you to submit things to the workqueue without > having to allocate, making the submission infallible. If we didn't have > to support this, then the patch would be much simpler. One of the main > things that make it complicated is that we must ensure that the function > pointer in the `work_struct` is compatible with the struct it is > contained within. > > This patch could be significantly simplified if we already had the field > projection bindings. However, we have decided to upstream the current > version that does not depend on field projection first - the PR that > introduces field projections will then include a commit that simplifies > the workqueue implementation. (In particular, it would simplify the 5th > patch in this series.) > > The first version of the workqueue bindings was written by Wedson, but > I have rewritten much of it so that it uses the pin-init infrastructure > and can be used with containers other than `Arc`. I tried to read the patches but am too dumb to understand much. Any chance you can provide some examples so that I can at least imagine how workqueue would be used from rust side? Thanks.
On Wed, 17 May 2023 11:48:19 -1000, Tejun Heo wrote: > I tried to read the patches but am too dumb to understand much. The patch is more complicated than I would have liked, unfortunately. However, as I mentioned in the cover letter, simplifications should be on their way. Luckily, using the workqueue bindings is simpler than the bindings themselves. > Any chance you can provide some examples so that I can at least > imagine how workqueue would be used from rust side? Yes, of course! The simplest way to use the workqueue is to use the `try_spawn` method introduced by the last patch in the series. With this function, you just pass a function pointer to the `try_spawn` method, and it schedules the function for execution. Unfortunately this allocates memory, making it a fallible operation. To avoid allocation memory, we do something else. As an example, we can look at the Rust binder driver that I am currently working on. Here is how it will be used in the binder driver: First, the `Process` struct will be given a `work_struct` field: #[pin_data] pub(crate) struct Process { // Work node for deferred work item. #[pin] defer_work: Work<Arc<Process>>, // Other fields follow... } Here, we use the type `Work<Arc<Process>>` for our field. This type is the Rust wrapper for `work_struct`. The generic parameter to `Work` should be the pointer type used to access `Process`, and in this case it is `Arc<Process>`. The pointer type `Arc` is used for reference counting, and its a pointer type that owns a ref-count to the inner value. (So e.g., it decrements the ref-cout when the arc goes out of scope.) Arc is an abbreviation of "atomic reference count". This means that while it is enqueued in the workqueue, the workqueue owns a ref-count to the process. Next, binder will use the `impl_has_work!` macro to declare that it wants to use `defer_work` as its `work_struct` field. That looks like this: kernel::impl_has_work! { impl HasWork<Arc<Process>> for Process { self.defer_work } } To define the code that should run when the work item is executed on the workqueue, binder does the following: impl workqueue::ArcWorkItem for Process { fn run(self: Arc<Process>) { // this runs when the work item is executed } } Finally to schedule it to the system workqueue, it does the following: let _ = workqueue::system().enqueue(process); Here, the `enqueue` call is fallible, since it might fail if the process has already been enqueued to a work queue. However, binder just uses `let _ =` to ignore the failure, since it doesn't need to do anything special in that case. I hope that helps, and let me know if you have any further questions. Alice
Alice Ryhl <aliceryhl@google.com> writes: > On Wed, 17 May 2023 11:48:19 -1000, Tejun Heo wrote: >> I tried to read the patches but am too dumb to understand much. > > The patch is more complicated than I would have liked, unfortunately. > However, as I mentioned in the cover letter, simplifications should be > on their way. > > Luckily, using the workqueue bindings is simpler than the bindings > themselves. > >> Any chance you can provide some examples so that I can at least >> imagine how workqueue would be used from rust side? > > Yes, of course! If you have bandwidth for it, it would be awesome to see some examples in the series as well (for /samples/rust). BR Andreas > > The simplest way to use the workqueue is to use the `try_spawn` method > introduced by the last patch in the series. With this function, you just > pass a function pointer to the `try_spawn` method, and it schedules the > function for execution. Unfortunately this allocates memory, making it > a fallible operation. > > To avoid allocation memory, we do something else. As an example, we can > look at the Rust binder driver that I am currently working on. Here is > how it will be used in the binder driver: First, the `Process` struct > will be given a `work_struct` field: > > #[pin_data] > pub(crate) struct Process { > // Work node for deferred work item. > #[pin] > defer_work: Work<Arc<Process>>, > > // Other fields follow... > } > > Here, we use the type `Work<Arc<Process>>` for our field. This type is > the Rust wrapper for `work_struct`. The generic parameter to `Work` > should be the pointer type used to access `Process`, and in this case it > is `Arc<Process>`. The pointer type `Arc` is used for reference > counting, and its a pointer type that owns a ref-count to the inner > value. (So e.g., it decrements the ref-cout when the arc goes out of > scope.) Arc is an abbreviation of "atomic reference count". This means > that while it is enqueued in the workqueue, the workqueue owns a > ref-count to the process. > > Next, binder will use the `impl_has_work!` macro to declare that it > wants to use `defer_work` as its `work_struct` field. That looks like > this: > > kernel::impl_has_work! { > impl HasWork<Arc<Process>> for Process { self.defer_work } > } > > To define the code that should run when the work item is executed on the > workqueue, binder does the following: > > impl workqueue::ArcWorkItem for Process { > fn run(self: Arc<Process>) { > // this runs when the work item is executed > } > } > > Finally to schedule it to the system workqueue, it does the following: > > let _ = workqueue::system().enqueue(process); > > Here, the `enqueue` call is fallible, since it might fail if the process > has already been enqueued to a work queue. However, binder just uses > `let _ =` to ignore the failure, since it doesn't need to do anything > special in that case. > > I hope that helps, and let me know if you have any further questions. > > Alice
Alice Ryhl <aliceryhl@google.com> writes: > This patchset contains bindings for the kernel workqueue. > > One of the primary goals behind the design used in this patch is that we > must support embedding the `work_struct` as a field in user-provided > types, because this allows you to submit things to the workqueue without > having to allocate, making the submission infallible. If we didn't have > to support this, then the patch would be much simpler. One of the main > things that make it complicated is that we must ensure that the function > pointer in the `work_struct` is compatible with the struct it is > contained within. > > This patch could be significantly simplified if we already had the field > projection bindings. However, we have decided to upstream the current > version that does not depend on field projection first - the PR that > introduces field projections will then include a commit that simplifies > the workqueue implementation. (In particular, it would simplify the 5th > patch in this series.) > > The first version of the workqueue bindings was written by Wedson, but > I have rewritten much of it so that it uses the pin-init infrastructure > and can be used with containers other than `Arc`. > > Alice Ryhl (4): > rust: workqueue: add low-level workqueue bindings > rust: workqueue: add helper for defining work_struct fields > rust: workqueue: add safe API to workqueue > rust: workqueue: add `try_spawn` helper method > > Wedson Almeida Filho (3): > rust: add offset_of! macro > rust: sync: add `Arc::{from_raw, into_raw}` > rust: workqueue: define built-in queues > > rust/helpers.c | 8 + > rust/kernel/lib.rs | 37 ++ > rust/kernel/sync/arc.rs | 44 +++ > rust/kernel/workqueue.rs | 715 +++++++++++++++++++++++++++++++++++++++ > scripts/Makefile.build | 2 +- > 5 files changed, 805 insertions(+), 1 deletion(-) > create mode 100644 rust/kernel/workqueue.rs > > > base-commit: ac9a78681b921877518763ba0e89202254349d1b This does not compile for me. Could you link dependencies to be applied first? Best regards, Andreas
Andreas Hindborg <nmi@metaspace.dk> writes: > This does not compile for me. Could you link dependencies to be applied > first? I messed up something related to the patch for specifying error type on `Result` [1]. This patch doesn't _need_ to depend on that though, so the next version of this patchset should compile without it. Alice [1]: https://lore.kernel.org/all/20230502124015.356001-1-aliceryhl@google.com/