From patchwork Tue Jul 11 09:32:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118382 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp354876vqm; Tue, 11 Jul 2023 02:42:38 -0700 (PDT) X-Google-Smtp-Source: APBJJlGMgoxpkBLpcQXgHiHSfuzhuGPFyq67px3A9XVGcsFIedCdJhM+Q79mVLWqd/+FGQd/oJxE X-Received: by 2002:a17:902:d2cd:b0:1b5:49fc:e336 with SMTP id n13-20020a170902d2cd00b001b549fce336mr14328798plc.42.1689068557981; Tue, 11 Jul 2023 02:42:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689068557; cv=none; d=google.com; s=arc-20160816; b=ZjtGQH9Ds54AlKcnMcbr4k/FdsX3GUmgT5XIAmLVvEmjOLPwFl+7bi9ga0oyO0Ugl6 AAy39DkzKXk3WW4XNlEz0B5duemvlhyWc9GhzYvmMtZ9Vx75CxhWqj2Jw0RLTZhFYJpZ O+2OyJKr9HjqcWXnt+G5fLjoViIGhiIi6vKDhp79lMT/mfCPdpoYmHwYIC4VRoiC2VlK 19bDUUzvO5vyjiXaouATXrKUSEklvwgvfXQb7LcoacM1/zjTnovrg49FwnWjsLxhxAcS xgJd5f6l9JjvQW5oH5fq5E+5E7K9UygT2r/zotwlJ2E4N660dJn2H4XNj26FR/lijYLD xWXA== 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=tpNSgka6HOUQbghNI4iad00TiEGE4hqZSL3kST/OC3w=; fh=OkxFdJx997RC+dFeEKc2tk94Mjc3yq9/JE22ZQAtwLI=; b=mJiJ5RBSiSJUlcC1CMAJ7cq5qINpm2WY+RaQowRZDGlWb1Qgh8ERpkckCvvw2rZmJ2 kfyFkrGjAoLLAJFiqHlIj45kiLQ0vWzr3ekxNaKUjyrCUZnii8UDNR90Rxp+P5QFIihs 8Uf65VP/CeEgVI12KGYyd0EFH1xHKyN3CRO6JY0RMO8NuPthG5YB2JDXh3J2yGM3BBxf CtUtZjo0N0YLuSMmx8iNHQ5Q97D2DkXohyVd8Mzv5ufLTAz8tfzp2FpzRD6IqYwTJRGy pwnJcWfg6stH4EI3ML867Wg0YtOMuhFmLYFg4eYS8IRGaU2Ym4Dr6Zn+B2iYBV9NUYxH Yj3w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=Ti91ZX6M; 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 ko4-20020a17090307c400b001ac84f87b0fsi1271623plb.339.2023.07.11.02.42.25; Tue, 11 Jul 2023 02:42:37 -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=Ti91ZX6M; 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 S229724AbjGKJgb (ORCPT + 99 others); Tue, 11 Jul 2023 05:36:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56534 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229939AbjGKJg1 (ORCPT ); Tue, 11 Jul 2023 05:36:27 -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 DD083100 for ; Tue, 11 Jul 2023 02:36:25 -0700 (PDT) Received: by mail-ej1-x649.google.com with SMTP id a640c23a62f3a-993d500699fso252842766b.1 for ; Tue, 11 Jul 2023 02:36:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068184; x=1691660184; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=tpNSgka6HOUQbghNI4iad00TiEGE4hqZSL3kST/OC3w=; b=Ti91ZX6MJ0NfZLQYe73Us+V/cCtLmivVf32T6Xf2KspuQN/HTcSSA9g2lebAH2TQhN M917g/IJ0yYA7BsuE+fY6jib84ff2BbHeYYHdD7GCus1Tood8iq9pudMXIAGApmDtGd4 opZTY0ahW5qJWmjOk9a1uReY5/8HIlRkuYvOrXDOGLvxRlc5ETES8cHD8upbUCEwyrcV cmQJcqZwgLshmeP2cWEXLeRyZ6F8E1+DqwshQI+h7PS6PaokWygqwzkipVev6NfY6ooi xIzWgbc1lDZuygb5OF4iCT/R0P81bIE5xWiiPhwHzB8T3R1bNjKNR5n/xG+vnkTxNVEt 5QkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068184; x=1691660184; 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=tpNSgka6HOUQbghNI4iad00TiEGE4hqZSL3kST/OC3w=; b=AbRQW/+/fYcJSFB8vOSHnKgmPQ0/r1ao7t/bdoM1cVd2ThV87VkCV+W5Tcd+rlA7O6 Rogb1GLjc7+w0PpFBRZ1VQcRk0xY5QAr24apJakj2f/AxyX2g2A9GPxJzi2108+QEuRo YD1XR1/nwoHXcIxJ2+LarcFXr+/ufxh7NhgAwKEZnzDbn7OyIG22EIKcSN73YEK+9RQt C53LIoXSGtN748RTlrbtdcjhBkbsp8yO4sMe7YwCVF6FmVKFurtTHnWshZNA94C8W0qf O+vKcaIQ8Lsy02dzfj6GSoz8lsjx6fM3LtlAI2p54rC0r80m5bz8YfMTLRqU0KNMECSy Ay6w== X-Gm-Message-State: ABy/qLb4cmHKOLei3HiVtcggYCTjEwAoCLkBhho5om3Yc29BLyCF62sb lapHzDSJL7Go4Z8McVt3eTlLQU2C4Hprcm4= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:907:763a:b0:98e:2b63:9f78 with SMTP id jy26-20020a170907763a00b0098e2b639f78mr48893ejc.0.1689068183762; Tue, 11 Jul 2023 02:36:23 -0700 (PDT) Date: Tue, 11 Jul 2023 09:32:55 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-2-aliceryhl@google.com> Subject: [PATCH v3 1/9] rust: add offset_of! macro From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771116752113058085 X-GMAIL-MSGID: 1771116752113058085 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 --- v2 -> v3: * Add comment as suggested in https://lore.kernel.org/rust-for-linux/875y862lr7.fsf@metaspace.dk/ * Added Reviewed-by from Gary and Benno. rust/kernel/lib.rs | 37 +++++++++++++++++++++++++++++++++++++ scripts/Makefile.build | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 85b261209977..788914fd935f 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)] @@ -97,3 +98,39 @@ 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) => {{ + // Statically ensure that the type has a field of the given name. This ensures that no + // deref coercion is happening. + 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 Tue Jul 11 09:32:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118386 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp355362vqm; Tue, 11 Jul 2023 02:44:03 -0700 (PDT) X-Google-Smtp-Source: APBJJlGqA2jq3AibuNrwtGP3D83W7T3z8FViSUslLSG8H/lZzJ4HqMkGfBX6qqUTiL/Q0FtP4w4I X-Received: by 2002:a17:902:ecc8:b0:1b6:b1f3:add5 with SMTP id a8-20020a170902ecc800b001b6b1f3add5mr15850103plh.27.1689068642835; Tue, 11 Jul 2023 02:44:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689068642; cv=none; d=google.com; s=arc-20160816; b=MD2wiH/j6kGKfUoBCFVuKRizoVToJR4zru6evFLsMl1++5qZWjFFYoXkrqJTxClDj6 RKH0isLVLKoIRkHdr7QWoHBe8X1nloKx7BxzAN4JjrWHtrrWs0N7EPqPRzZeXRu0ov2J hT0zMvrMtB2OSF5Z+hUE4b8ptFEKg08+3msJRSnOWRlnNo3uQhkQ114mMMtFemK8LtMA J+OiAhFTdpNH4SZxYDstBXk7yN9ujdka1HRWu5RA3aupYieimzRbfUHU2SdIstBrWMqQ M8vrmEBQHL3vVcqhhYYjB4mm+JWDhIPm6Z46tYBC8V9Jq0gGOlTQrxzvPdcJ3nVjP+9B J2yw== 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=MBgmP0PJ2iUxFozvmmmYwZcxD6aJZ5z3cAsE+Xf1as4=; fh=URF4Q4zskhqJjwRQzg6p8D72NyX6O7SQz64piqYRpA8=; b=bGgDUSAKpyXeWKFpVBNVypdlIRp6crOhj5UtRt8vPaHuKRtYCSXsQzBAt+8ujxZ3gb n0XcqPdCHJjjt+HtdbYdsyihSS9U0ZVDeDdXqlIBouXA6CYyroGr75iwHZ+3zRZ6sFXN mafEhhWFqnh9ZChcT8tIpQnZ3sbYkBzkdwFUsze+Y/MyTxrLRWyupiw7AUkyYX0mP+9B h5F8M/6kA46xQ0ZWvG14TqyzqtXcbyyTdMwLj7wTiG01QOzJ+bwddbow03OPnFbfTRfZ hHuZxh5jiYEd3MBWPJjDi2qRWWZNJ2NFHPw/AzAATLFrcw17mcXmS7ZjBvhKg4ESoE0u YtAQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=ZW2z8hOF; 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 i6-20020a170902c94600b001b8a70d4129si1310566pla.467.2023.07.11.02.43.50; Tue, 11 Jul 2023 02:44: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=ZW2z8hOF; 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 S230266AbjGKJjN (ORCPT + 99 others); Tue, 11 Jul 2023 05:39:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59296 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230254AbjGKJjJ (ORCPT ); Tue, 11 Jul 2023 05:39:09 -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 EBE3610D4 for ; Tue, 11 Jul 2023 02:38:37 -0700 (PDT) Received: by mail-ed1-x54a.google.com with SMTP id 4fb4d7f45d1cf-518676b6d09so3259222a12.1 for ; Tue, 11 Jul 2023 02:38:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068316; x=1691660316; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=MBgmP0PJ2iUxFozvmmmYwZcxD6aJZ5z3cAsE+Xf1as4=; b=ZW2z8hOF1WRo80QrafK0JkXI57zkP9C7rM4fPyaa1AxBIiYredVLSA46iO2WpKHuUc +geNJaQzzi4cADrIqii2oBP5uLE/koheH+H1dMZyW8g5P9DFudIKPnlIzlwxlbWP54xt x6BbXLcZAVMRHMd+S6GmIEOg64evUP91Wj0dubwkkXgIVikM48pkRssOCeOwdeiI6bvT Jd1XfA7QMJ5YTREszwAJD9SPurKXk6nAfSemFpFTVlt9+TveOlmzcZxNfHAc1HQzr5pc s+HBC/OZwUOw33LF1YhiwJbMowsX/6i0a4QjDkKySJUXnHVTvlV6uJVuyzYybavzJcs7 a3wg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068316; x=1691660316; 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=MBgmP0PJ2iUxFozvmmmYwZcxD6aJZ5z3cAsE+Xf1as4=; b=Rs1hvq14Vnk2xKLr17AcXhkkYICSblx1mbotHjE6gIK5uHuPGWswvnYPygbmEOT0yL sHjKQl5k0ZVZM4u8UNxAKBK6g9sBkQylKsPzmXUoMFLXssJennCmBUy1aSudMMZzMn7V wR6I73hqqviVU4lRpBA07Ystf9Nph3oCjMGyRTiM3Rws7uLg/Ys3TBt1F66ALzmga2WF 3h/T1z+K0y6B6MtTxWQ9OvsMtBl/TUfkoxK+ua5+UcEw0PUOwrKKvvib+TiAhMUUjliT HPUwHnVMybEuZeEhDTXCgnxkVSrD68fnAARJOw7acNoR3g8mThTSbD9cq/9NUSrIo2E7 YBlQ== X-Gm-Message-State: ABy/qLYLY5Kdw+xn/Y2lsS70yZSiHBKJDKYAczsFlKsAaYbcUakKGpWz D/GYFYFJiLnucaTnlgDUnsB3iZlFPR1GJyw= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:907:a047:b0:98e:4e80:f0e3 with SMTP id gz7-20020a170907a04700b0098e4e80f0e3mr50726ejc.9.1689068316182; Tue, 11 Jul 2023 02:38:36 -0700 (PDT) Date: Tue, 11 Jul 2023 09:32:56 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-3-aliceryhl@google.com> Subject: [PATCH v3 2/9] rust: sync: add `Arc::{from_raw, into_raw}` From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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 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_BLOCKED,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: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1771116841715217277 X-GMAIL-MSGID: 1771116841715217277 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: Gary Guo Reviewed-by: Martin Rodriguez Reboredo Reviewed-by: Benno Lossin --- v2 -> v3: * Use `transmute_copy` to convert metadata. * Use `add` instead of `wrapping_add`. * Dropped Reviewed-by from Martin and Benno due to changes. rust/kernel/lib.rs | 1 + rust/kernel/sync/arc.rs | 49 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 788914fd935f..6963d11092c4 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..4046b534e53b 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -24,13 +24,13 @@ }; use alloc::boxed::Box; use core::{ - alloc::AllocError, + alloc::{AllocError, Layout}, fmt, marker::{PhantomData, Unsize}, mem::{ManuallyDrop, MaybeUninit}, ops::{Deref, DerefMut}, pin::Pin, - ptr::NonNull, + ptr::{NonNull, Pointee}, }; use macros::pin_data; @@ -212,6 +212,51 @@ 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 = Layout::for_value(unsafe { &*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 }; + + let metadata: ::Metadata = core::ptr::metadata(ptr); + // SAFETY: The metadata of `T` and `ArcInner` is the same because `ArcInner` is a struct + // with `T` as its last field. + // + // This is documented at: + // . + let metadata: as Pointee>::Metadata = + unsafe { core::mem::transmute_copy(&metadata) }; + // SAFETY: The pointer is in-bounds of an allocation both before and after offsetting the + // pointer, since it originates from a previous call to `Arc::into_raw` and is still valid. + let ptr = unsafe { (ptr as *mut u8).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 Tue Jul 11 09:32:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118392 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp360857vqm; Tue, 11 Jul 2023 02:58:52 -0700 (PDT) X-Google-Smtp-Source: APBJJlFHq+h3MR2qjDnNfFupOt3DUYvTqRWKBdu3iOyAj36cyN4Te1yvCFtrgCGfcLIruwaodq+A X-Received: by 2002:a17:903:32c9:b0:1b8:9598:6508 with SMTP id i9-20020a17090332c900b001b895986508mr19196134plr.18.1689069532127; Tue, 11 Jul 2023 02:58:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689069532; cv=none; d=google.com; s=arc-20160816; b=uu2BVF6bWYkvLLBUJwOWCOM2mT3fUVCcZeswt9bk0BMJKJmGohB5ahcsD8tT+Bf4jO 6aB0HDJ7xcSjgs3j9lhq1Kqn1BZ276d9/PME8WBa4GCoQr2h3K3RD3weoav2GQEpsr5h bJjrbtjXjD6YEAl8DZ28HV7MNDNYL4Jf72inw34DV44wS+paKAFWWWUA3rglPDHYKNU9 9cWsrXEZUxqIgGvqZTZgIVX9E/ss4JVPs0J/45B9u6HHrhcv1EON15W2y7EFmziw9Ysi wpulVBZuNEusRp5NZ62BXUn5rm+XBWmVPQMAkwedGHQm3sIBWuN/WMBnWawA8q2fi67k W0Ew== 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=v6WKBzYvERNDuknj+tWtM9bgJ0GurLsMS9RlnUyPmrc=; fh=URF4Q4zskhqJjwRQzg6p8D72NyX6O7SQz64piqYRpA8=; b=rc/w6KblADbq9UQC7HNxF38fVMq9sQwuIRIvEMST9a+re6leJrKZb8btVEw9DVK0Jn e70fncp6KA2R2T0izZQKy+p3lmMIXk1fBoGZy08Jg8uCEebXJv2XDQ+nynGlLoWsy3m4 JUS1XIF/6XYJ6OMCPloE/xlmhEU21DHM1WIeBTb9nqjhLNuGviRB1vu09ciFSn+LIgOD dSBE+QW+51Yej+L3ZmPdnTm4n7Ykjw8kBejQwyRZJdGESIkz6UW17QQF4usKN1thLVbQ vkknVyOLrCV2Stm46ifKGM6iCdqHzjYxsueR3e1fOOWbvXI3O/NovCwfAV+9OYBszyQt lH+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=EpcSNWvY; 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 t18-20020a170902d29200b001b01276a0bcsi1309431plc.51.2023.07.11.02.58.38; Tue, 11 Jul 2023 02:58:52 -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=EpcSNWvY; 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 S230155AbjGKJkx (ORCPT + 99 others); Tue, 11 Jul 2023 05:40:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59776 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229626AbjGKJk3 (ORCPT ); Tue, 11 Jul 2023 05:40:29 -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 B44C810E3 for ; Tue, 11 Jul 2023 02:40:21 -0700 (PDT) Received: by mail-ej1-x649.google.com with SMTP id a640c23a62f3a-992e6840901so661125066b.0 for ; Tue, 11 Jul 2023 02:40:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068420; x=1691660420; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=v6WKBzYvERNDuknj+tWtM9bgJ0GurLsMS9RlnUyPmrc=; b=EpcSNWvY8BCvobBorJKTq6sFdxH+VChpySoX1MC6xQdxotL6dpArX2aHBbt8VwonAw 5U4nkKAdAsXsBjRDjn6EJ/x8bsMuu1doFFJvH1xZRhMq2Oiz20TKlliU+WA6sROLYe+w UndpaFiDN9F35Dagtj3aF/edBjBBMAKbbZkhFlBWv4Kaj53V2N4T/s7wsTWL4v90UKNE oozF7LlHEEr/6kgi4O2vKtbfvhppt5Arfmrca6t5//9RahqDBJW7JnxkqhX2YB6vYrKZ uy6eDDQmJHIAJuEuULa55PMfNx33dz8BOSoG7musUOFxBivEQpP0x6mWwB6qBCUpYUrH zU+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068420; x=1691660420; 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=v6WKBzYvERNDuknj+tWtM9bgJ0GurLsMS9RlnUyPmrc=; b=Nj249I/mSsPnEjKv159CF5b0t9TSLvxAx9gJFzLH2Tli7g10TzvNZik9+nN8T/kbqL CpvG+z6sDkOWIEjrcfnedeDOrwRCZPDdabHkIzf9QPNjdasZqxfik4SPaF1CMtXbu2nz 1Bh934CWgNluMgL3NLHj8QCFUVaNrerc8KaC5Rh7fgmKXb12gpmKxVV5WrD7GWuDmxoT 3YeQ11EsuYZTOzRKGSrPWfkXlp0gAUeuQNMrg5Itb1W41kE2he0EWXTcHrzVn6pvtO35 wXIBoNhd4WaPTT3kccrAPVp9PKI1zkrzzTGag8B5TlVcBfswQwH3XZT7C9GO5lMymNZC pPGQ== X-Gm-Message-State: ABy/qLbFnoDf3qY2HA8UCsfRU6hDI8t8Gjs4q8ftir83fDHb7uWQDWGM ZE00sN4aUrsnPMXi0rsQpzmf3mQrKLWvn54= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:906:9f26:b0:98e:46da:bfec with SMTP id fy38-20020a1709069f2600b0098e46dabfecmr101085ejc.1.1689068420362; Tue, 11 Jul 2023 02:40:20 -0700 (PDT) Date: Tue, 11 Jul 2023 09:32:57 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-4-aliceryhl@google.com> Subject: [PATCH 3/9] workqueue: introduce `__INIT_WORK_WITH_KEY` From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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 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_BLOCKED,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: INBOX X-GMAIL-THRID: 1771117773566590626 X-GMAIL-MSGID: 1771117773566590626 From: Wedson Almeida Filho A Rust helper (introduced in a later patch) needs to call `__INIT_WORK` with a passed key, rather than define one in place. In order to do that, this moves the initialization code from the `__INIT_WORK` macro into a new `__INIT_WORK_WITH_KEY` macro which takes the key as an extra parameter. Co-developed-by: Alex Gaynor Signed-off-by: Alex Gaynor Signed-off-by: Wedson Almeida Filho Co-developed-by: Miguel Ojeda Signed-off-by: Miguel Ojeda Acked-by: Tejun Heo Signed-off-by: Alice Ryhl Reviewed-by: Martin Rodriguez Reboredo --- Taken from [1]. Wedson's email updated at Wedson's request. Tejun's Acked-by taken from [2]. [1]: https://lore.kernel.org/rust-for-linux/20220802015052.10452-7-ojeda@kernel.org/ [2]: https://lore.kernel.org/rust-for-linux/Yvq3IfK4+C94AeE2@slm.duckdns.org/ include/linux/workqueue.h | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 3992c994787f..c91a84a4723d 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -221,24 +221,31 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } * to generate better code. */ #ifdef CONFIG_LOCKDEP +#define __INIT_WORK_WITH_KEY(_work, _func, _onstack, _key) \ + do { \ + __init_work((_work), _onstack); \ + (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ + lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, _key, 0); \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->func = (_func); \ + } while (0) + #define __INIT_WORK(_work, _func, _onstack) \ do { \ static struct lock_class_key __key; \ - \ - __init_work((_work), _onstack); \ - (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ - lockdep_init_map(&(_work)->lockdep_map, "(work_completion)"#_work, &__key, 0); \ - INIT_LIST_HEAD(&(_work)->entry); \ - (_work)->func = (_func); \ + __INIT_WORK_WITH_KEY(_work, _func, _onstack, &__key); \ } while (0) #else +#define __INIT_WORK_WITH_KEY(_work, _func, _onstack, _key) \ + do { \ + __init_work((_work), _onstack); \ + (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ + INIT_LIST_HEAD(&(_work)->entry); \ + (_work)->func = (_func); \ + } while (0) + #define __INIT_WORK(_work, _func, _onstack) \ - do { \ - __init_work((_work), _onstack); \ - (_work)->data = (atomic_long_t) WORK_DATA_INIT(); \ - INIT_LIST_HEAD(&(_work)->entry); \ - (_work)->func = (_func); \ - } while (0) + __INIT_WORK_WITH_KEY(_work, _func, _onstack, NULL) #endif #define INIT_WORK(_work, _func) \ From patchwork Tue Jul 11 09:32:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118393 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp361065vqm; Tue, 11 Jul 2023 02:59:28 -0700 (PDT) X-Google-Smtp-Source: APBJJlEi7iNjSbVI60qnSK4ViYB27r5dahl8pPLNbDj3vgcWOZ1G4Fyg8sW1C4o8fvBdrjyJqni2 X-Received: by 2002:a17:902:e88b:b0:1b7:f64b:378a with SMTP id w11-20020a170902e88b00b001b7f64b378amr13882929plg.16.1689069567815; Tue, 11 Jul 2023 02:59:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689069567; cv=none; d=google.com; s=arc-20160816; b=UCnoUUNAB0mMTyxhUNNcEcH005yFbzrL4+MUZiV0SFTGRNHlYy5Q1SMewrRzfJBt3K 0+q8Ta3mBVDMYTD4j+E73/6HMjuXTKJjZioCGyNNlxSU4CYSDYVuD2zVIqogCwPaJKFD /t8HLOMT/TASRuZHpBNO0EPi8G+RuV16Kli8HWSaK1UOsY6E0aCxUcR8nrtpqp3tOLhP VjMHhU1jsqocxbaqayLammX2asBn6y6byVo3+Om7MiK7TRHrKoQAFqRmGCDjCE09Pfxa pfgKMvG3AQ1R7e0KPOwbeFeACBZk1O8IdR9cXD9VDUai7ZR8xq/TIPi+OFad3DU75poS aZIw== 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=f7HLpFtiTSWw0ZxSifV85XuGL1lfgvJblX5DGQd7aZg=; fh=EaQNN7e7jDQTL4fpVTP1jQtHjs+FHUI5BbJS9LqOq2c=; b=gY82ubqA+iyPxk58GvZtnCCEX5+e4AzpWo26+bCTbtf47A9bdeSZsDoMRqazSOBlNo F2Vk55mCpEe0g7BZrdaut+7x90l/H+HmhzxG1ozjk/Qd3YZKJuar94Qjd0b8G4fPWMT8 +t9nRyqwnV1dg233QyCtpTv8CvOFU0RYNAQZv3AIyeIn+ej6T5FwqRs5Qc94Gh3tWCwG Q3v6r0rCo3uoe6hD9zGTOmO46jyX1NnY+49unjAqqJixhF3ANKGVh49To108GRthpA3+ BN9SRdVnkrSdLzQxukuiwB0NPyog0sp1XSCyGmZN/O6O6XyVyTeGsCtlR0xmUA+/Ri/M PgYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=rn6KFEzf; 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 k12-20020a170902694c00b001b8079085a1si1264655plt.380.2023.07.11.02.59.14; Tue, 11 Jul 2023 02:59: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=rn6KFEzf; 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 S230345AbjGKJmm (ORCPT + 99 others); Tue, 11 Jul 2023 05:42:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230397AbjGKJmh (ORCPT ); Tue, 11 Jul 2023 05:42:37 -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 CBDD7A8 for ; Tue, 11 Jul 2023 02:42:26 -0700 (PDT) Received: by mail-ej1-x649.google.com with SMTP id a640c23a62f3a-993d41cbc31so269033366b.1 for ; Tue, 11 Jul 2023 02:42:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068545; x=1691660545; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=f7HLpFtiTSWw0ZxSifV85XuGL1lfgvJblX5DGQd7aZg=; b=rn6KFEzfYPUPKzeY5cQR9Bk5tjkbVHfgCbbsmC9+vaf9B/2jTg/G+kxUDkEVhnnUKY 6ituUWa6qX4KfIU1hTNSnYfZLeUIMvi/qwGapwmTAdLAEO9MWnWyBcvCuBZ0Vw6rwM0t 2BpB27CEsT5oMh7hw/6OR/Da6YVFpyX2u3kMJ5BDquicAt/R+GyU1zds1crLxR/rS5CK jQrtdS1LcVEe/fuKqGhI5Ol27ZA/T4yb0HGT0B9XgMhFKuLj4CzwYT64EU0T1tGX5Qiu g5X20m+QQGmoj65d15hRUfrxcvF6pgg3a6kmqDIN9hrb9mPU82LU8N7OjiChZgfYdiUB 6FLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068545; x=1691660545; 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=f7HLpFtiTSWw0ZxSifV85XuGL1lfgvJblX5DGQd7aZg=; b=Z5i+ghJODtyBiJU5B7Zx6ezPM9Dckab5nr3e6QGM/GNCfMvnDhkDtVRno873ppJM2Q eutKJJ0EqlMAC95ktWwXnbJZFW49ixKQF5TnmkYvdTeLe6107HCZrUtStkt459zvibCc 200KDz4dMPuaKgMitRS61g35xGu61fV29nzvhJQ5DNM2uMJeU0+2o0phzJcO/vdYxofC Vsgx/pnAtuIYRYT/O1RoMD6gc9BDiTMxEuJR/ahGqihSzJk9wL8hSnpJbJu+MmgxJj0i JwAm9MG/cBeUNFBSuoD8CHh34QitmlKUHomXTwzKHDC1zVTfYBBcUy4MuwzkI1hJVqBS oEHA== X-Gm-Message-State: ABy/qLYCAlhOCvkO2/IhcxWssfWk5EAh64SSzosgiT2r9K5R+E/yfONG 82O98b184llcRAnA1nsEgzUJ9SV0T0W4B3U= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a17:906:9be6:b0:98e:413a:477b with SMTP id de38-20020a1709069be600b0098e413a477bmr55880ejc.10.1689068545276; Tue, 11 Jul 2023 02:42:25 -0700 (PDT) Date: Tue, 11 Jul 2023 09:32:58 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-5-aliceryhl@google.com> Subject: [PATCH v3 4/9] rust: workqueue: add low-level workqueue bindings From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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, Martin Rodriguez Reboredo , Andreas Hindborg 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771117811134040092 X-GMAIL-MSGID: 1771117811134040092 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 Reviewed-by: Boqun Feng --- v2 -> v3: * Update documentation to say "guarantees section". * Add Reviewed-by from Martin, Andreas, Benno. rust/bindings/bindings_helper.h | 1 + rust/kernel/lib.rs | 1 + rust/kernel/workqueue.rs | 108 ++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 rust/kernel/workqueue.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 3e601ce2548d..4e1c0938c8cb 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -11,6 +11,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 6963d11092c4..6d63f4f6bb8a 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -45,6 +45,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..060d26dfcc7d --- /dev/null +++ b/rust/kernel/workqueue.rs @@ -0,0 +1,108 @@ +// 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 guarantees section of 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 Tue Jul 11 09:32:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118390 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp360537vqm; Tue, 11 Jul 2023 02:57:57 -0700 (PDT) X-Google-Smtp-Source: APBJJlHn9yMdtc4rk1Vxy2FmEnIKdpZy8T9IUsb5t0uHTlCIvv737R11xrOiUbWFwhhWLJieOKMq X-Received: by 2002:a05:6a20:7295:b0:12f:405d:c4d0 with SMTP id o21-20020a056a20729500b0012f405dc4d0mr18391819pzk.54.1689069477519; Tue, 11 Jul 2023 02:57:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689069477; cv=none; d=google.com; s=arc-20160816; b=rZT4gFBqzkeBJ8eRDO55Yhc0I78nAaSjKhFoV6261eLVBAdbYxoAMB4LsE0ZE1VlC0 ZnlJcZdY4c/xfgpSh1y1BhJ9c5ZOz0q5cAN2TIilnUly0UspHOkfu9fQzKoq4zVvH+kn TfmTA2niYMibl4ngILp+6sI+hX0OnnhEmiX6bHMbRnZvv7I18i70YuGdjF2LBdTiVI7i U1UDA9dW3hUXPNjLt35UCNwI9OOTjZsSSaPlBKqhZLO68QcMySrmhgj8yA6zF8RbZ7xW SJt/lTwpPQoMAgNcELY36vfMpm2+9LtquDrTpQTYDLaZEikZ5yKqq6sJwnYgiXDeG3Jq ZHkA== 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=DnWC54SA5C43dBWBZ5WUeTUepGdecHVPir9nVhbTPfs=; fh=RTCrXH9699vIEM4/Tym8/jfVap2P7UN8kMcB+AdrNPs=; b=pz1cEKzg1wiKStgWeRqzXufdxTRKCF5u2YDsCCQ9g/1oDdrxES19p9JiahUzDDHmTE ZWhXmONwrPEdJf6aD9uZyneOSypxXMVGjcEHB1G5cxUcBH4ZoiozogAux4XKVrmeyMpk N2+BW1XJSxGUWUKyMtHf5YtKeZEEj6Vo0MIW60VKca+zlLtuw9ISAOCRpfl6/b1MfA6y 9nPi3/sQB8O2AxqXkSYFa4fezXrdDL4GOdfaMKFfGxnY0n12qNuuIPUn9qNBX7uLN4h3 tRBOKxbSTzzm5+FKI+7Kw8LA4+cN9cxKK5ut4zYqC1FSp3Lahsy9cX2lAULtn+HahsLa DKiw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b="pFt/A5hE"; 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 e2-20020a17090301c200b001b9e2ce5723si1393200plh.495.2023.07.11.02.57.44; Tue, 11 Jul 2023 02:57:57 -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="pFt/A5hE"; 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 S231192AbjGKJoi (ORCPT + 99 others); Tue, 11 Jul 2023 05:44:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35390 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231154AbjGKJog (ORCPT ); Tue, 11 Jul 2023 05:44:36 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8C8FE56 for ; Tue, 11 Jul 2023 02:44:32 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-5706641dda9so58536287b3.3 for ; Tue, 11 Jul 2023 02:44:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068672; x=1691660672; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=DnWC54SA5C43dBWBZ5WUeTUepGdecHVPir9nVhbTPfs=; b=pFt/A5hE+tHwPhG/vQTUr4kvstBbCWSzSLnioI5Xu66+C+AWhzML21sFWR8XVStzeF 0wRGxUkDMyyBLV3icf4r6VX2vGeeR4uCecxUxYvJ9zfs42pnWCSIGAAkxhpoeMJWP4oR Th52jB4y46IhDAv6CAQOCUzz6GVjHy+3AUSezWpl2nAhSHYYRPh3Y8DWkr0X97j9CcqX fbw9l15c8mpBVTeboeZOYwWazNhqnOvLa7kV1+K2XEhnjt+g3d7g7/jiuFcqxVyFT1m8 T3Kc/xEiMt+wWCJGIJHLzWCKBxLAWqHOyDSTuXKA6hOOtxaUKLZDHbBhcJmmdT55KEjn KW4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068672; x=1691660672; 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=DnWC54SA5C43dBWBZ5WUeTUepGdecHVPir9nVhbTPfs=; b=iRci+tJJeoq4a3iF7iuxixXIHOrdBpoyyTcfyWlY7hAXfg47earEh7EciOn9bae125 QpZ9En6MvWePToqrJ5TtE6cfpWkFJxA/kqDe7olto6NzkxZO60oTU89qs+wyxo1/GXKM Gzez483YR2NS4EnpgcPGGAgIXsNSCZFl9eBpVBl6da0AjRj/LGxcMrwfLNyuxEetIUJX yKPf9TnrnEzgAf9ylDBvlIgKja8i8J3TCc0JHQqhUCzwKF0tP30HaAPopk0bGFVR44Oc DNY412QkqSTACCU+b/5WFD+OpTRPG9oJFMPyQLuiDo29dsewfY56u7x5LI83jspv6eEL 74Lw== X-Gm-Message-State: ABy/qLbBxp+kdku3neAyRYufI+wlWzEviKxKXVNoCIRaH+7i8mwp6trI 8u/hm18vsRoe/DINbfaHQKNZvncut7VR/2w= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a81:4312:0:b0:579:fa4c:1f25 with SMTP id q18-20020a814312000000b00579fa4c1f25mr126504ywa.7.1689068671975; Tue, 11 Jul 2023 02:44:31 -0700 (PDT) Date: Tue, 11 Jul 2023 09:32:59 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-6-aliceryhl@google.com> Subject: [PATCH v3 5/9] rust: workqueue: define built-in queues From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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 , Andreas Hindborg 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771117716405552895 X-GMAIL-MSGID: 1771117716405552895 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 --- v2 -> v3: * Explain what a freezable workqueue is. * Add Reviewed-by from Gary, Andreas, Benno. rust/kernel/workqueue.rs | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 060d26dfcc7d..cad039dfc5a9 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -106,3 +106,74 @@ 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. +/// +/// A freezable workqueue participates in the freeze phase of the system suspend operations. Work +/// items on the workqueue are drained and no new work item starts execution until thawed. +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. +/// +/// A freezable workqueue participates in the freeze phase of the system suspend operations. Work +/// items on the workqueue are drained and no new work item starts execution until thawed. +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 Tue Jul 11 09:33:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118389 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp359923vqm; Tue, 11 Jul 2023 02:56:14 -0700 (PDT) X-Google-Smtp-Source: APBJJlFlszpA5X9rPV5ydy4KjoETcuqJbcADXFjXP9RA6JdJEPjTOC77IT1pE1wqj1sJ2CD1d2gW X-Received: by 2002:aa7:88cf:0:b0:681:d247:8987 with SMTP id k15-20020aa788cf000000b00681d2478987mr13871221pff.17.1689069373712; Tue, 11 Jul 2023 02:56:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689069373; cv=none; d=google.com; s=arc-20160816; b=vMfKp0CIm4fDXIr4xdcGeV6Iz8q0sMntbJaWXWP2O/yumB1DNeGI4ijxy7SMcXana5 8kgcluox8aCgU9GIcOxESnbxRQS5aHdGrv74cSyxTnrp9Ruwovs2NwchO5/0x9rdherG Q22/iEFBc6gfqOWAmhm7dC/OYMmEIc5TWkOt6+Qy/vcUJsUDgvKAfoAYqEx4ZkrC7pcA r9Vt2otaguJ3dA7voUEx1pWvMdGc0/vhLdDPhl7FFu0SHS9MhRVddlcsd04rjzatNnlQ R4jh4/lZjXM1yR6QYTUBdLf3qBTe2Ad5/AlUouedfFRFIDLTURJNPOKKppFXyyz4P/fp gZjw== 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=byeQRg9wMfh8yysYKRK6+a5IcPGEEJ19WpkHoNK4TKk=; fh=8bRVPoWV2y6u+yovbjGSsaCGdR9LEB/+l+yZT2RVbhs=; b=TH00R9768lWbQ/DCt2KnhmfCjBcP9DMVGWbSN/2oAO7xisONaE68tzVPJbGhI5XDA7 tQGQOlk068xJLiSiRbs99EM9dv0wsY6DNS2/oTFa87vd2zV+3OQPA0wQZD+26cm2FKLZ atIhH9LVqo+CEkuoPA2gfuGDJ92JNzZ9euJvub2vF0djMu9FvWpDd7uF+XIAVMepVHcv 8BU9L3z2V3DXLOZsRochbu1u2t6pc6SoV9V1ay7R27SBN0059l4tq8WVKotRQEd7S0CS 28KUnILrCt8XXAOhkFQqMCO+lh2K+vtnrRaYUiz0dp4NbnEHBmZFCCqZI2Xd9dAq9KMu a5Wg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=7SJiwh3N; 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 y9-20020a056a001c8900b00682ad3475e4si1218275pfw.209.2023.07.11.02.56.00; Tue, 11 Jul 2023 02:56:13 -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=7SJiwh3N; 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 S231694AbjGKJrT (ORCPT + 99 others); Tue, 11 Jul 2023 05:47:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231510AbjGKJrK (ORCPT ); Tue, 11 Jul 2023 05:47:10 -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 2A2F2A4 for ; Tue, 11 Jul 2023 02:47:03 -0700 (PDT) Received: by mail-ed1-x549.google.com with SMTP id 4fb4d7f45d1cf-51836731bfbso2966769a12.3 for ; Tue, 11 Jul 2023 02:47:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068821; x=1691660821; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=byeQRg9wMfh8yysYKRK6+a5IcPGEEJ19WpkHoNK4TKk=; b=7SJiwh3Nwsx+fRHer0AymGXM84gSsAdDhbqu3yy0DnA+CbreWmaAfUaZw13Ma5rVS5 QagEEGMILZsXeLezA9BFbZN3t9aXRlxgp4TvXsSOhE3SOBeVrrpEXWI+t2SJ3qdary1V 0x333up/a0MSVrMjRjGcQlHBu3ZYc61UW61NXOXU6iNIpUSgoVfRPXCnMmWot2awhpNB 3PtPFHwMR+uShJ+Whp0M0M/x+JXu68f6HBel3IeFxsQFiOh/7pwm+jbrOoqIQMCaT7Uv ctU1+hsRU5sCBkgazOzp9h43+1TNhEXTch5uHVVuTmTaOspP50HbP45XJVsueCc0XcQL 9R8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068821; x=1691660821; 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=byeQRg9wMfh8yysYKRK6+a5IcPGEEJ19WpkHoNK4TKk=; b=S1PBPMy0AtsPa+djHOdIidmH3g74Z1Slb3QUDTxG2pnEk1/dmobV4AAxtzGu1bMNt1 vP9O26kOMbZiTlSj0Fy01pqdoVM4Rc8gYCmmphNyKFjzzDT5NnonjGSGtN3Lv7EJ9/4X kWQY81WVnt23Ks9pmNmBaXrrauYIZpOccZl0cmbPeojKKpjhpZ7oZmhOwufLR/YdLjwt wKoFaqYI91Khzn7RpJ9MSLM2WD/6J+2b+rwicMZozo6DIiFxdozxdV4eTV5O3wsBP5Nl YouWj5yc6C3mI2lE3JcFedQ7zs9Q98u0cuzSQQrIFcK26QyKTBF4sYOjp/2FY808Bvcu p8Xg== X-Gm-Message-State: ABy/qLZ79lmYmkzp89yN4n0FSDBW5Jyhkpy66BV2oAft7Endyx0IeCY3 kpOZV0qGrRhAt/5NJAnQRdPBMuyIJEc+juU= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a50:c353:0:b0:51e:162f:d616 with SMTP id q19-20020a50c353000000b0051e162fd616mr83019edb.8.1689068821303; Tue, 11 Jul 2023 02:47:01 -0700 (PDT) Date: Tue, 11 Jul 2023 09:33:00 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-7-aliceryhl@google.com> Subject: [PATCH v3 6/9] rust: workqueue: add helper for defining work_struct fields From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771117607399908655 X-GMAIL-MSGID: 1771117607399908655 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 --- v2 -> v3: * Use __INIT_WORK_WITH_KEY instead of __INIT_WORK. * Expand documentation for WorkItemPointer. * Expand documentation for HasWork. * Removed PhantomPinned from Work. This depends on [1] for correctness. * Dropped Reviewed-by annotations due to changes. [1]: https://lore.kernel.org/all/20230630150216.109789-1-benno.lossin@proton.me/ rust/helpers.c | 8 ++ rust/kernel/workqueue.rs | 240 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 247 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index bb594da56137..f7a04a266f46 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -27,6 +27,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -135,6 +136,13 @@ void rust_helper_put_task_struct(struct task_struct *t) } EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); +void rust_helper___INIT_WORK_WITH_KEY(struct work_struct *work, work_func_t func, + bool on_stack, struct lock_class_key *key) +{ + __INIT_WORK_WITH_KEY(work, func, on_stack, key); +} +EXPORT_SYMBOL_GPL(rust_helper___INIT_WORK_WITH_KEY); + /* * 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 cad039dfc5a9..a7c972bda0ed 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::*, sync::LockClassKey, types::Opaque}; +use core::marker::PhantomData; /// A kernel work queue. /// @@ -107,6 +132,219 @@ 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. +/// +/// This trait is implemented by `Pin>` and `Arc`, and is mainly intended to be +/// implemented for smart pointer types. For your own structs, 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, + _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(key: &'static LockClassKey) -> 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| { + let slot = Self::raw_get(slot); + bindings::__INIT_WORK_WITH_KEY(slot, Some(T::Pointer::run), false, key.as_ptr()); + 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. +/// +/// The intended way of using this trait is via the [`impl_has_work!`] macro. You can use the macro +/// like this: +/// +/// ```no_run +/// use kernel::prelude::*; +/// use kernel::workqueue::Work; +/// +/// 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. +/// +/// # 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 +/// [`impl_has_work!`]: crate::impl_has_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 Tue Jul 11 09:33:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118397 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp363910vqm; Tue, 11 Jul 2023 03:04:03 -0700 (PDT) X-Google-Smtp-Source: APBJJlEnBJyokfQEHAkE+QITFshTLi0JlDHwQzZJH+c2ApkijtNPP2IDvdC8tc1/ymTEkPPZL+xV X-Received: by 2002:a17:902:ee91:b0:1ac:a28e:4b29 with SMTP id a17-20020a170902ee9100b001aca28e4b29mr1364571pld.26.1689069843166; Tue, 11 Jul 2023 03:04:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689069843; cv=none; d=google.com; s=arc-20160816; b=VCQ1xkTBP/+n6tgiswsVUYXCsY7ML885OpdoxpuiFWnyL8HI2V6qnDFPv0a7cP6AXw JIo3SWuN+J1tR8ryFBoZQNVBBdfxHm2Bx+8UyzKB9/3xWz/gJeAUp8pAVmrPcU2ngWF5 vojj7+zViTDYYC0tt296MBEfmvhF2wPpc8i1tgRYpCi0cCAYNfCjdMXuWf/jjOCI95HE pwScjM2rRyJltps/pfJsMXli1BFgp8WeNuDlBbgX4bGRiCQaxKfUi9V3yg6TAi54LXmD J46Gx2DHJVWUKU3SovDfPmiLu5MZ0ledFJWjbMnF50g1WpvmZ1A3+wrLmKSU6YJsaBJy /eZg== 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=/EqMekonA8uGHFD/lDqj3wOWtQfGKVNTfQouXEykc8E=; fh=EaQNN7e7jDQTL4fpVTP1jQtHjs+FHUI5BbJS9LqOq2c=; b=y0Q0ONc2Q5y9ZtkQNpzuF/q7fg6qpIKn7RQQx2mNyqG8YAN7Q46gbKVk9w+cB3JzNt +hEM9aJ0Bya0pPB21YNdmMXSEF6cHAMdlJTm8gYP2e74jKuGHRprtuMSQZ41iKhTzCoK KaQlffsufR8kWOXx1wlFVboOM+jC0uK1xrgVQmZGYbd21vC8JHm2KeEknoi+sY0J9908 iLDcO3JJtZQvysT1S/vmcSy7sRWAEP8HhtMzluELVh1eKcRlYuHqXp5ZYGS/Kc/UgI3O 0sjyCSWvqtA9xoOING/NrGRCwTPvuqXe3r0JROzN9b80k2N3+gAHD3V0hVvMIUPj1HFF Pj5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=IhDUOhT0; 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 j13-20020a170902da8d00b0019c354055d0si1364640plx.304.2023.07.11.03.03.50; Tue, 11 Jul 2023 03:04:03 -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=IhDUOhT0; 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 S231661AbjGKJtg (ORCPT + 99 others); Tue, 11 Jul 2023 05:49:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231558AbjGKJtc (ORCPT ); Tue, 11 Jul 2023 05:49:32 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C83EA9 for ; Tue, 11 Jul 2023 02:49:31 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-c4e77129acfso6680126276.3 for ; Tue, 11 Jul 2023 02:49:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689068970; x=1691660970; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/EqMekonA8uGHFD/lDqj3wOWtQfGKVNTfQouXEykc8E=; b=IhDUOhT0+DvvMgAAceahZcV7aUb3Zv9bWU0qe0g6pEouMuHOgruEFQzK3tcCGz0fY0 dNS22UXL6tq2hBKNniRASmkbPF+d7fQXIRahB/BzW81ZQx4nJ09+2qAuZc7MquRblvcu B16dRYK5dohuej1KyH+5cySONL8YFRLl1Q4FqpPX0X8h3AiNYRFM0VgPDnlAdkr4qpm/ aO71pzpqHLppLt/f+32LBAs2DjfHYu5qKmdBH+7BtfMChJq6jooxLy9I1mphNkfG77LK IxnqMigeSRhV5KTLFgtb17TR6635l4Rc3+dg1lFsZhZiQHhaTjpgXH3XCCbgqJ6YFuCn pqOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689068970; x=1691660970; 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=/EqMekonA8uGHFD/lDqj3wOWtQfGKVNTfQouXEykc8E=; b=UM18nGpiVTkr8x3Hp02mkyUeP39xNULE7vfEbDQZrs7ZD29cvQYGMq22V1kvJ+RZkL oFA9D8CYtFyWHxDhC+jJOIOo7ynXcPkUKUgIDeRxi2jkMFUyuHz3KFiUfu2jff//mUZE MrswG0/Mwf/Wlk8abWLbp3omhx2bxfmtjYprlQlLqvPBu/+8HGxshxWZqAlCOdT0X30W dRdywX7pacnFp1yQR2JVJEgc7ej3/dssrFROHrUErDxxgUQ/Rd+X+knIvqVYdxQMLNEZ Rqw4HLv56dQRG0S7nor6Iw/pCAZT7wVk1BNwzpOFeBZMQTuURSPrQusauJp/VxjwWjSK mz8A== X-Gm-Message-State: ABy/qLagypgRP2Lpt8WMzX+Dju+Wme6inJjNnZVhI6Omj+FbvYYYCc6z swlDKpMrgUDHll2EBJlXN8jXUmH1y+1eFBE= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a25:cd09:0:b0:c6c:6122:5b69 with SMTP id d9-20020a25cd09000000b00c6c61225b69mr107979ybf.8.1689068970724; Tue, 11 Jul 2023 02:49:30 -0700 (PDT) Date: Tue, 11 Jul 2023 09:33:01 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-8-aliceryhl@google.com> Subject: [PATCH v3 7/9] rust: workqueue: implement `WorkItemPointer` for pointer types From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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, Martin Rodriguez Reboredo , Andreas Hindborg 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE, URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771118099686273116 X-GMAIL-MSGID: 1771118099686273116 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 --- v2 -> v3: * Use `cast_mut` to cast pointer in `impl RawWorkItem for Arc` * Add Reviewed-by from Martin, Andreas, Benno. 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 a7c972bda0ed..e760040762bd 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::*, sync::LockClassKey, types::Opaque}; +use crate::{bindings, prelude::*, sync::Arc, sync::LockClassKey, types::Opaque}; +use alloc::boxed::Box; use core::marker::PhantomData; +use core::pin::Pin; /// A kernel work queue. /// @@ -345,6 +347,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).cast_mut(); + + // 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 Tue Jul 11 09:33:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118408 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp374332vqm; Tue, 11 Jul 2023 03:25:44 -0700 (PDT) X-Google-Smtp-Source: APBJJlG4o7C+Sp4fQCY9xnPhWJ0rk22Hfj5GlQ7iwr5KGrJnWWkJ2vkR9cyzfLtga037fSb5JzDz X-Received: by 2002:a17:906:2781:b0:992:5cda:69f1 with SMTP id j1-20020a170906278100b009925cda69f1mr14979441ejc.61.1689071144417; Tue, 11 Jul 2023 03:25:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689071144; cv=none; d=google.com; s=arc-20160816; b=p1A7ygGz6wNzvU8mEsLG7SU21jpg910qYYcvhE9zJZAv0uMXqK5WuUkiIT8lZOmpQu zew1Vfj2JhGetrMFivD7ohKivu+sHKWNIac5jtn3+SeMoWdfPycYOzAkMAefk1O2B2vG N3ryXFrksVMt/Z10WmCQwbG3/QrIDj+OU8vnJTEy0aEAw2xbCmBoHMuFkr+D8OIJolx4 1ieXiXUg4J2oofQVSF/LQGEZCw2rqfdnCNXsY2vDPqcTdwhK+4rXQH0Hn7T7qCID3LfM lnEe95j7LrdfnsWIZj7rBCtS1UBe3bjiONepv+s4ShAvlP0Of41bja+K2s7pX6mO6iw7 aJzQ== 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=zbG7B9nIgqjfOv4qsNLCa5ebcFdm5P+XcawO//zctYU=; fh=EaQNN7e7jDQTL4fpVTP1jQtHjs+FHUI5BbJS9LqOq2c=; b=zCqapkgrgbIJJXIwWszTJhSrj9jz8nMwHO3wb20ViR35/NZ7O7wIJHDcHOOyb8xiLV ir5XEhRsBRmtX83jL5JxOn+hmlXOCDtqa564QRsqjK/SCICD24ZCYE141W+IRScEmijP j5LDTeQNNzs6o6rqcEq6t0JmC3hZWvkGpoq9GVvFdEhjEKZZR+K3BXhlyOiQKstCox3x Fd9pLGnAL8GzyJoLxme5iks/Zv+WiTQLFArgAYsLsn6asEOljSQn/4JwDDYbgVGBoXvF zZx0G6JteQwzVMQOL2gILBcaP/fZSA9aG5YtKGC/ChhJEXh/pE6N/mYCD/ji6zpxfxoU T7zQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b="7Xc/ddVU"; 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 op19-20020a170906bcf300b00993a9a951f9si1894187ejb.28.2023.07.11.03.25.21; Tue, 11 Jul 2023 03:25:44 -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="7Xc/ddVU"; 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 S231653AbjGKJvq (ORCPT + 99 others); Tue, 11 Jul 2023 05:51:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231439AbjGKJvo (ORCPT ); Tue, 11 Jul 2023 05:51:44 -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 599ADA9 for ; Tue, 11 Jul 2023 02:51:42 -0700 (PDT) Received: by mail-ed1-x54a.google.com with SMTP id 4fb4d7f45d1cf-51e2497eeefso3588521a12.3 for ; Tue, 11 Jul 2023 02:51:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689069101; x=1691661101; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=zbG7B9nIgqjfOv4qsNLCa5ebcFdm5P+XcawO//zctYU=; b=7Xc/ddVUS0wM3GZO2B4AprynVg9zdVzLcyIeszTINkZEhMbnLLiUtLRsb31FPVbX+v reQxDAqLJm+3phY6MBudaf4zuQd3YTfi3efTF+dNuZZPIMi/HvDNP4c9t15xV+K4FS8g bPzRHP1jHv7jqqPKvzwHsdoUsaCbRef/eh2j0FzqjsqyDcUO58KAGbPPrzd6DCPoqkZq L96g8upUP6Gt22M0M29/DcrWSC4naOOb1Png3Bexwc5Jat8/ZKWqUtvKMqIktDrjeDB7 3pMGuxOJDNc9X/dC13LsiOoPu86DyMohr6aEJhuJwhn+ud67Cv5yGn7RgjgL3hmjY1NS dCVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689069101; x=1691661101; 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=zbG7B9nIgqjfOv4qsNLCa5ebcFdm5P+XcawO//zctYU=; b=EJ/BvM2c0tFHhCxjtpIgK4LzRdX795klQTbAAF9IKloekHPJP/8hxYnNqSkoJZyMIo j/oHMb1zIP38Ct+f0AXtCCt76Z5/0qDLjJeuCLjmHkFLXjjTsvLRRJD2LA2uZDFN4er2 wVuwVJVAEI3lFL/chvB+rUCzENmVXPFEwZ2XY5KbaBpHs26WdlPvJybInwx52W0c38tA Pup754vW6G7VE7O5v5gSjvWx5wO63bvP4cN2ZGl4I+PWMkzkizMi8jtrtLa6ts99PczH eTLxrIBS73OkyGb0pTFFITlxku7vy4tHsYQ9Sw4IikgFs+q7i9z7nhHkjFlGJfdJeNVZ RrCA== X-Gm-Message-State: ABy/qLb4Z6okQWxy7QgdJZcsKgSJxztBs/HZ4VSjkM3jSnOAG/DH+9qy AH5ttYuUqo6kg2r5YLFbGdq8n9+Eiud5NSs= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a50:cd0f:0:b0:51b:e4c5:547c with SMTP id z15-20020a50cd0f000000b0051be4c5547cmr79456edi.4.1689069100681; Tue, 11 Jul 2023 02:51:40 -0700 (PDT) Date: Tue, 11 Jul 2023 09:33:02 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-9-aliceryhl@google.com> Subject: [PATCH v3 8/9] rust: workqueue: add `try_spawn` helper method From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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, Martin Rodriguez Reboredo , Andreas Hindborg 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_PDS_OTHER_BAD_TLD, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771119464186036046 X-GMAIL-MSGID: 1771119464186036046 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 --- v2 -> v3: * Use a LockClassKey when constructing `ClosureWork`. * Add Reviewed-by from Martin, Andreas, Benno. rust/kernel/workqueue.rs | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index e760040762bd..3a3a8b52bfd9 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, sync::LockClassKey, types::Opaque}; +use alloc::alloc::AllocError; use alloc::boxed::Box; use core::marker::PhantomData; 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(kernel::static_lock_class!()), + 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. @@ -347,6 +386,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 Tue Jul 11 09:33:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alice Ryhl X-Patchwork-Id: 118410 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a6b2:0:b0:3e4:2afc:c1 with SMTP id c18csp374886vqm; Tue, 11 Jul 2023 03:27:00 -0700 (PDT) X-Google-Smtp-Source: APBJJlFc9CxiMI7jciHLdrSRjm1IQCzoLUO6ia3BEMir7v5VuKJJl1hMB4tqXj6BLwHn3lLC0nkM X-Received: by 2002:aa7:c60c:0:b0:51d:e498:201 with SMTP id h12-20020aa7c60c000000b0051de4980201mr13741773edq.27.1689071220572; Tue, 11 Jul 2023 03:27:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689071220; cv=none; d=google.com; s=arc-20160816; b=UCptKUEtmQSxLvJwlyQrpCDIpGCa4BBbJcF0ZcbDQKmZEGwOLYH0g6eSIKVeKstaQu 6w0mOSp82ZwOCVPi3DmgiZRxdlWxjdEj+UARtyeuES7AfxXqdTeVFtGKYhGH0ifF1x6e oWQsalaRhMU4WJscncJCcjbjJf20fT6LFVCU8dMr0g879vX+L0muicVt/0MWypR6ounw zbnQ1hJVRp9rV1ngIid8TIPwK9EpdLKNEGz7L1IUobfjw0c5jGlrnxJR85q5Zj8mrpoc rdPT4CfLEm1glunvLPQG98VzNO4ZRJFyLoBaLr64h2RSfhRVV//9NREClEaQUUmvKfuK HDvw== 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=WVqEtgaoR84mlWb1xo2bD1CrEq4VPJW4ZXsIrXT2SxY=; fh=EaQNN7e7jDQTL4fpVTP1jQtHjs+FHUI5BbJS9LqOq2c=; b=zLUlq07QNoMm3tFAoXDhCrnnIRSoxHt4/GuG7RoX+IdFC1DdleyeQUxNNe00mQM0Un BhY12v9qUZ4VL9nF44pVXahbSUwWx2ZM98JTS3l/gtfjktNMDXFv4P7xcifhu5Z1BGio 6g7IbqlDXitXAMqgysqdZxkGH2AcLUoNZEXvU3avbd+G69njZmwlz+ipVntja9b9D7zn Kto8G4JEccyXuJiDkoJB/nU2lms4e3vC2E5VPyamGQ3X2Qg4Kcpv80lkW2yiIgURoKJi SPQ98ryh87SsYDujl2wkoyC4ui1b1SXXHUdavFyFR7q0L2pFwCW44i9eUYDJdgK+W+tK mZoA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20221208 header.b=JiS7r4oS; 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 v10-20020aa7d64a000000b0051e472983d1si1638187edr.524.2023.07.11.03.26.37; Tue, 11 Jul 2023 03:27:00 -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=JiS7r4oS; 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 S230021AbjGKJ4x (ORCPT + 99 others); Tue, 11 Jul 2023 05:56:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229890AbjGKJ4t (ORCPT ); Tue, 11 Jul 2023 05:56:49 -0400 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4667A1 for ; Tue, 11 Jul 2023 02:56:48 -0700 (PDT) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-5707177ff8aso61162887b3.2 for ; Tue, 11 Jul 2023 02:56:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20221208; t=1689069408; x=1691661408; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=WVqEtgaoR84mlWb1xo2bD1CrEq4VPJW4ZXsIrXT2SxY=; b=JiS7r4oSjpoYeZAQokPiDZbRIRNXbzoWPZL7NF+5rzbH6mH2Rcy5+beBc9ND3C54Cz Aus5Cg913qXuDxwKJCGdRWmHr05KJU0rJAHeg88AZD7kauK/bKXdTeDKY4hHqsiAXQQL giwWgikoRtreQUO/DBn4FxwrAoqmcTXpHQalZUi4p2Udagcl0C2V8fzJ4YAZqbRHjs39 J4t57iEQpS8/MHp0zwe9jwefzUlWJejQ8XzKTLzsg3oq45gSz8Ajf7nQvIF4XLItT28/ qIgL6zZDPEwioH0kLhbOCQCI7+NjZMZFYtDBdbaMW78mZpZzOwkCwthKHdajV8J2epzt 5zxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1689069408; x=1691661408; 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=WVqEtgaoR84mlWb1xo2bD1CrEq4VPJW4ZXsIrXT2SxY=; b=dE808fUW3KNq1mRx1MIHhP0KnUoc6AIUEb/XO4mSOJw0XM0EZFYgEMNKbJscV20UpW m2aw6/mgdYGH43ZwpT5byV2OK2EH7PmbtvrfNMi8s30kT9wv7KRehkL+Jzn3mSAztsPG UOHFdcyD1hMVBWC86GyPi+7V43Hw7BznCx+Ii/XIHTA1V1AufvNjruw37TVAdJyD5Qws Pu/VwQuqv7pRbt9O+wtKf3E6IlNkV/uN46lvSa5wvJGsn2QtYR0/sAIzHvv6JfUc5BQq GGW3eatd2Id6xWVSi5AaccUUkynJQRO8O8eKwfbHb7q9dKWw3Ax4tM2dDnC0CE8xorvX iRCw== X-Gm-Message-State: ABy/qLY4wnmtodj8AxEGqVAf6WwjTNCLImAgw6cQr5f1ots6j35fyiur sYrHJ9B2SEK1UWBzUnHSLsENsFhjSjAOVQQ= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:31:98fb:c0a8:6c8]) (user=aliceryhl job=sendgmr) by 2002:a81:764f:0:b0:57a:141f:b4f5 with SMTP id j15-20020a81764f000000b0057a141fb4f5mr139132ywk.7.1689069408101; Tue, 11 Jul 2023 02:56:48 -0700 (PDT) Date: Tue, 11 Jul 2023 09:33:03 +0000 In-Reply-To: <20230711093303.1433770-1-aliceryhl@google.com> Mime-Version: 1.0 References: <20230711093303.1433770-1-aliceryhl@google.com> X-Mailer: git-send-email 2.41.0.255.g8b1d071c50-goog Message-ID: <20230711093303.1433770-10-aliceryhl@google.com> Subject: [PATCH v3 9/9] rust: workqueue: add examples From: Alice Ryhl To: rust-for-linux@vger.kernel.org, Tejun Heo , Miguel Ojeda Cc: Lai Jiangshan , Wedson Almeida Filho , 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, Martin Rodriguez Reboredo , Andreas Hindborg 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_BLOCKED,SPF_HELO_NONE,SPF_PASS,T_PDS_OTHER_BAD_TLD, T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED,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: INBOX X-GMAIL-THRID: 1771119544196411884 X-GMAIL-MSGID: 1771119544196411884 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: Benno Lossin --- v2 -> v3: * Use LockClassKey in constructors in examples. * Add Reviewed-by from Martin, Gary, Andreas, Benno. rust/kernel/workqueue.rs | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index 3a3a8b52bfd9..482d3eeae7d8 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(kernel::static_lock_class!()), +//! })) +//! } +//! } +//! +//! 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(kernel::static_lock_class!()), +//! work_2 <- Work::new(kernel::static_lock_class!()), +//! })) +//! } +//! } +//! +//! 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, sync::LockClassKey, types::Opaque};