From patchwork Sat Apr 8 07:53:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81132 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp740848vqo; Sat, 8 Apr 2023 01:07:12 -0700 (PDT) X-Google-Smtp-Source: AKy350aX6ZuzvoucXmo+GjYwLJiFp09XqwBbyQH0y+XcZ0oha3KR92w251xLsH8Ggw6fRtR8+MZa X-Received: by 2002:a17:906:b197:b0:92b:846d:8928 with SMTP id w23-20020a170906b19700b0092b846d8928mr897282ejy.65.1680941232139; Sat, 08 Apr 2023 01:07:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680941232; cv=none; d=google.com; s=arc-20160816; b=km9H4T2kmCmD3iEZxD+Xkwg3uBlwQfOzedGCtYZEpzdA5cR0C4bVIMbNs1CGzZYr12 JEI32WP5nEYd71c02lapcb5bdkseVwS9rByHgqmgzplMuu7mIzyneN5/rk+r9KqJYQcw XEGGTMgOLYxMI3hT/gkp7Psx7VrYmhgrYzHIshxXBuaGpnwqKQMzzSqvypfQfzJzBoEf tvpVueJ5wVu5MBErzqiKJqYnYoAQ+OUfQz6RfGVnhVL3PRjGYafH9ghBLtBcOV9iPFtH IZHVb4f/K3YwZJi4GSurqSMPgbzTkSo3O/z2Tii1t/0xU/aFjSJCycQGOBjtAZczQcik ApNQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=8DXY5enKnxnJyRV7r86vq2fiEM2iNKd+iCSjske2KHI=; b=jPF3QRMEQKjnGPbZO2qwkiUP2XjtlGvZAd5i/OLHlaosddrnfU4Q51zB9oqIzfNdnW NPWX4t7cW+CuGZ/3c3HNiL2SR+PMX2HfCzZPxUZtITDqI+FR8ys4D1/GTGGQ66NaoNyn OpluP5+Z+lHLfHQwgpHZa31lU5oPuJntHyRb8HM17K4mN6QT6rif6Y7S4O7rwLaHwAZS Y4Bn7dhii3iYFnGcCtC4GXZGo0gD3oCHwAn9h24vnxryXGxQ0KXTKDWtyU0evkUbbxp4 CnKEkfwenuz03WPXlRL6aZvPhDNa67MUzeuTw+lFAO9VAwa4AaI5M0jsqP9lM47OmdNn K/1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=QpArfm+D; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id qw32-20020a1709066a2000b00938de018211si5255500ejc.831.2023.04.08.01.06.47; Sat, 08 Apr 2023 01:07:12 -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=@gmail.com header.s=20210112 header.b=QpArfm+D; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229802AbjDHHyA (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58888 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229510AbjDHHx5 (ORCPT ); Sat, 8 Apr 2023 03:53:57 -0400 Received: from mail-oi1-x22d.google.com (mail-oi1-x22d.google.com [IPv6:2607:f8b0:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4712B26A4; Sat, 8 Apr 2023 00:53:55 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id q27so31655633oiw.0; Sat, 08 Apr 2023 00:53:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940434; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=8DXY5enKnxnJyRV7r86vq2fiEM2iNKd+iCSjske2KHI=; b=QpArfm+D2AtseAfEe0p39Qc9A+hlCKSMdgaYUrWWmhe6qILHfP6feTEBkFhEDZKW1j ZOwdqgemZ4V/YA6c5VbWjVEzyzVuCyx2P5XKeFe232Y+vRNQADzY7RfNu5WsrOJdFRnQ BdyomMOB0g4OaNpeeqPs3Ix4bsVepv+Bi+W3l/PQB5/JhuWrd9CzYK3rq+LJUNFbOVGt MHY4TITVWIsPSD+ZC4YC71w3/zDdN92b2PZoVgci40DC8lr6FMP7D5SpaU1/b5EaaKuh SIWj4PyM04rL/OWEjl/o0RZ9QP+L64oL84oBqMeEexYYzsFulBXmoPggImafbw9mgGxm /GTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940434; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=8DXY5enKnxnJyRV7r86vq2fiEM2iNKd+iCSjske2KHI=; b=v9bq2rD27TbhoXbS/rWPs0BwozYDnSOIQ3wjwXK4aQNRmI3e9X2VL05E6+GHp5EQY4 Asw8yZNlCe6lKqlqo8G4dJ3fAxuh8v2mrfRDKMoJhIH4RC/SFJhgvA8meGE80r+5J+C1 Zya3gajxbhcqlDQh0KRW0b/qGwbFSrH8kaJk/y48/ucUuK7Ega6Q9jqZYBdyXDv3eqs9 Jj258YNPQvyh0pQdgCWGosv3e63rqxnoOeWBYt/iUrC05PFfbSwbBMrKzgRQRG9N2x9P IBKjLIRZxZmJq/ER7LE8BSMAlj1CEVq0VYZvwO9uieE/Uwf1dyPIRZxKdKuOcfWbjeOW oXqg== X-Gm-Message-State: AAQBX9cPvk/Gya7jTTt4Y3+zdfuh/ZyoEaYorMdkMQmY+jQbOHKTmPDB iHYHoWbEnD1AYUblj75aQlJQQV3+yu21OQ== X-Received: by 2002:aca:1905:0:b0:389:4a80:336f with SMTP id l5-20020aca1905000000b003894a80336fmr2042313oii.23.1680940434442; Sat, 08 Apr 2023 00:53:54 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.53.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:53:54 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v3 01/13] rust: sync: introduce `LockClassKey` Date: Sat, 8 Apr 2023 04:53:28 -0300 Message-Id: <20230408075340.25237-1-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594632989641159?= X-GMAIL-MSGID: =?utf-8?q?1762594632989641159?= From: Wedson Almeida Filho It is a wrapper around C's `lock_class_key`, which is used by the synchronisation primitives that are checked with lockdep. This is in preparation for introducing Rust abstractions for these primitives. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Co-developed-by: Boqun Feng Signed-off-by: Boqun Feng Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: Fixed a typo in comment v2 -> v3: Replaced `core` with `::core` in macro rust/kernel/sync.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 33da23e3076d..541d235ffbeb 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -5,6 +5,51 @@ //! This module contains the kernel APIs related to synchronisation that have been ported or //! wrapped for usage by Rust code in the kernel. +use crate::types::Opaque; + mod arc; pub use arc::{Arc, ArcBorrow, UniqueArc}; + +/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. +#[repr(transparent)] +pub struct LockClassKey(Opaque); + +// SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and +// provides its own synchronization. +unsafe impl Sync for LockClassKey {} + +impl LockClassKey { + /// Creates a new lock class key. + pub const fn new() -> Self { + Self(Opaque::uninit()) + } + + #[allow(dead_code)] + pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { + self.0.get() + } +} + +/// Defines a new static lock class and returns a pointer to it. +#[doc(hidden)] +#[macro_export] +macro_rules! static_lock_class { + () => {{ + static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new(); + &CLASS + }}; +} + +/// Returns the given string, if one is provided, otherwise generates one based on the source code +/// location. +#[doc(hidden)] +#[macro_export] +macro_rules! optional_name { + () => { + $crate::c_str!(::core::concat!(::core::file!(), ":", ::core::line!())) + }; + ($name:literal) => { + $crate::c_str!($name) + }; +} From patchwork Sat Apr 8 07:53:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81124 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp736149vqo; Sat, 8 Apr 2023 00:55:44 -0700 (PDT) X-Google-Smtp-Source: AKy350ad78vRle5DVuLSvuFDSSA1S8CzJDI3H6Yx9lz9y+guQmWNDJz218u6T/VoDrXN+bbVs+rV X-Received: by 2002:a17:906:842:b0:935:3028:ff58 with SMTP id f2-20020a170906084200b009353028ff58mr1711139ejd.55.1680940544607; Sat, 08 Apr 2023 00:55:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940544; cv=none; d=google.com; s=arc-20160816; b=wfnm5wU9lbsCcur5CHiVRurjlmswuZm0zNPC+vIl5XuZd2NPrFs1wJZWWXRwRgf3AU cKIJuIcoNuXYXs6OnzhNjJrxHayPCk1XcyownKbiSlmMRxl1R+vULgLzqfPIy6tV3tS0 CuSBfHzhN/idB7QPc3Nv+16KXzPX2Kvap++pGQkfsEx0JbmQv+uHRmqTYxGUnzjUusBE wlf9A+ECHUL2hE2X4N8d54FiPtE9eqesmLiB5OKLpX1l9RLe5II8ztu5wmciNZhA4UFo AFYS9Rh9LBYlROYUz/pPMiisbhVp06WfptAeYGvpn6+FZxAKW62TXtBkdyvHzk4dXC2U DJ4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Ty2c9HDR/6nIOmkOFdir3f2Vau2dO37PR6ULzCuywyo=; b=utFkkZdCIuFtB11wTGuhWv/zkTEyQPl4VbpMAsby7xlgQrYxaeb2uw8X7fCZq+6Gxd hpi54YcwFjFGWD5p/M7UeNUaXUmc+NqkY60Jm7KBGaKZ91w0DY7acSsWCeURLsIntnC3 K9BwMAe/YKLr6Dk6sSbDHaBj35jiPI23FPZZDHSwL0Wj6DYZxunfpr+sbuIMYmOheUTc w8Q0R8fMWtbn1Vak+ZzjrLDFH3EOyC+c888XY/dVeBvbX6wzRR8BgiG3XIFL1F+Ue4Id 2LnpDBx0t1WslTlGccNp6b44nmtqX/qyi4EFdzoLeCphnS77H4Zp4eKT/c0QHS+o3vVi IRCQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=mQD2FNQM; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id e27-20020a170906081b00b00931563028c0si4903808ejd.282.2023.04.08.00.55.21; Sat, 08 Apr 2023 00:55: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=@gmail.com header.s=20210112 header.b=mQD2FNQM; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229988AbjDHHyH (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229785AbjDHHyA (ORCPT ); Sat, 8 Apr 2023 03:54:00 -0400 Received: from mail-oa1-x34.google.com (mail-oa1-x34.google.com [IPv6:2001:4860:4864:20::34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0232903E; Sat, 8 Apr 2023 00:53:58 -0700 (PDT) Received: by mail-oa1-x34.google.com with SMTP id 586e51a60fabf-1842cddca49so877298fac.1; Sat, 08 Apr 2023 00:53:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940437; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ty2c9HDR/6nIOmkOFdir3f2Vau2dO37PR6ULzCuywyo=; b=mQD2FNQM14xtdowH9iz3u9KrxtWYxuVEiLHuuONTmMgyyrzvr0SECC32EA1W0hXf0A Q0aJQ9U0KyozWxckkzcvoIfVqnlAmirDs9ML1dihRP7QD44WRk7u/GaBF1R4GWaf31X3 rIpq3hGKjCh6YP6XhWpao8Or9mRlwtpbKTs2Q/t3Y8DNPYD49G4EDQQZ75U6ZRghYuCD kHchuY27fpbv4NVn47Zu98ou0tcbDmJqxmgJBLEfFoHzGNa1Fst2IBwoqcwOYgYJ7yvH zMHeEUNyQ2i8XLWjtesvoy5BIH6M6Y8/NXoFWdaI9wbEWkT7QWy8Ok01C1e7eulWLVkD v9NQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940437; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ty2c9HDR/6nIOmkOFdir3f2Vau2dO37PR6ULzCuywyo=; b=uh8L0dolSCRkMGK/NImylADgNkcLg+JBnLGAiZ8Efj2vkN8imi/754vH64rWOMljNM a901NVkcwqI4eVTnnNi5qNbWgf6OrtACT1TVZ6i9H47HQrpdVng/AhAJVI3m8zQVhraD qmis00EMN0fGyB1R5RG+96WBf6Ct40cGwakKPAAaYcHYm57ZX+nJEM1743vjgEszWtHF Tnw4WHoXQSQ2iarLthObqpB2pKyjZaQLNPGvn6XbWJ9KcL9P2h6e7L5afsVKla5i/E/L hKI3BQQCXyR2IexWj7ZQmTT/C88ZtGkcu+129sPLbHIVWg5lmPJ045q1wqN9JyuEnXKn PfyQ== X-Gm-Message-State: AAQBX9cA17/SfMzLZPnBx/tEuhC1ajs8r1gBh7U2Gaq6XdIEhVMS/E1g Fe13FvU4CW6dYhSPBh4WhpxXSNyo1xY= X-Received: by 2002:a05:6870:a793:b0:184:286b:8abc with SMTP id x19-20020a056870a79300b00184286b8abcmr850876oao.11.1680940437175; Sat, 08 Apr 2023 00:53:57 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.53.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:53:56 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v3 02/13] rust: sync: introduce `Lock` and `Guard` Date: Sat, 8 Apr 2023 04:53:29 -0300 Message-Id: <20230408075340.25237-2-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762593912934870664?= X-GMAIL-MSGID: =?utf-8?q?1762593912934870664?= From: Wedson Almeida Filho They are generic Rust implementations of a lock and a lock guard that contain code that is common to all locks. Different backends will be introduced in subsequent commits. Suggested-by: Gary Guo Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: Use new Opaque::ffi_init from Benno's series rust/kernel/sync.rs | 2 +- rust/kernel/sync/lock.rs | 162 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/lock.rs diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 541d235ffbeb..81b0998eaa18 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -8,6 +8,7 @@ use crate::types::Opaque; mod arc; +pub mod lock; pub use arc::{Arc, ArcBorrow, UniqueArc}; @@ -25,7 +26,6 @@ impl LockClassKey { Self(Opaque::uninit()) } - #[allow(dead_code)] pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key { self.0.get() } diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs new file mode 100644 index 000000000000..3fa4eefde740 --- /dev/null +++ b/rust/kernel/sync/lock.rs @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Generic kernel lock and guard. +//! +//! It contains a generic Rust lock and guard that allow for different backends (e.g., mutexes, +//! spinlocks, raw spinlocks) to be provided with minimal effort. + +use super::LockClassKey; +use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque}; +use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned}; +use macros::pin_data; + +/// The "backend" of a lock. +/// +/// It is the actual implementation of the lock, without the need to repeat patterns used in all +/// locks. +/// +/// # Safety +/// +/// - Implementers must ensure that only one thread/CPU may access the protected data once the lock +/// is owned, that is, between calls to `lock` and `unlock`. +pub unsafe trait Backend { + /// The state required by the lock. + type State; + + /// The state required to be kept between lock and unlock. + type GuardState; + + /// Initialises the lock. + /// + /// # Safety + /// + /// `ptr` must be valid for write for the duration of the call, while `name` and `key` must + /// remain valid for read indefinitely. + unsafe fn init( + ptr: *mut Self::State, + name: *const core::ffi::c_char, + key: *mut bindings::lock_class_key, + ); + + /// Acquires the lock, making the caller its owner. + /// + /// # Safety + /// + /// Callers must ensure that [`Backend::init`] has been previously called. + #[must_use] + unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState; + + /// Releases the lock, giving up its ownership. + /// + /// # Safety + /// + /// It must only be called by the current owner of the lock. + unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState); +} + +/// A mutual exclusion primitive. +/// +/// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock banckend +/// specified as the generic parameter `T`. +#[pin_data] +pub struct Lock { + /// The kernel lock object. + #[pin] + state: Opaque, + + /// Some locks are known to be self-referential (e.g., mutexes), while others are architecture + /// or config defined (e.g., spinlocks). So we conservatively require them to be pinned in case + /// some architecture uses self-references now or in the future. + #[pin] + _pin: PhantomPinned, + + /// The data protected by the lock. + data: UnsafeCell, +} + +// SAFETY: `Lock` can be transferred across thread boundaries iff the data it protects can. +unsafe impl Send for Lock {} + +// SAFETY: `Lock` serialises the interior mutability it provides, so it is `Sync` as long as the +// data it protects is `Send`. +unsafe impl Sync for Lock {} + +impl Lock { + /// Constructs a new lock initialiser. + #[allow(clippy::new_ret_no_self)] + pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pin_init!(Self { + data: UnsafeCell::new(t), + _pin: PhantomPinned, + // SAFETY: `slot` is valid while the closure is called and both `name` and `key` have + // static lifetimes so they live indefinitely. + state <- Opaque::ffi_init(|slot| unsafe { + B::init(slot, name.as_char_ptr(), key.as_ptr()) + }), + }) + } +} + +impl Lock { + /// Acquires the lock and gives the caller access to the data protected by it. + pub fn lock(&self) -> Guard<'_, T, B> { + // SAFETY: The constructor of the type calls `init`, so the existence of the object proves + // that `init` was called. + let state = unsafe { B::lock(self.state.get()) }; + // SAFETY: The lock was just acquired. + unsafe { Guard::new(self, state) } + } +} + +/// A lock guard. +/// +/// Allows mutual exclusion primitives that implement the `Backend` trait to automatically unlock +/// when a guard goes out of scope. It also provides a safe and convenient way to access the data +/// protected by the lock. +#[must_use = "the lock unlocks immediately when the guard is unused"] +pub struct Guard<'a, T: ?Sized, B: Backend> { + pub(crate) lock: &'a Lock, + pub(crate) state: B::GuardState, + _not_send: PhantomData<*mut ()>, +} + +// SAFETY: `Guard` is sync when the data protected by the lock is also sync. +unsafe impl Sync for Guard<'_, T, B> {} + +impl core::ops::Deref for Guard<'_, T, B> { + type Target = T; + + fn deref(&self) -> &Self::Target { + // SAFETY: The caller owns the lock, so it is safe to deref the protected data. + unsafe { &*self.lock.data.get() } + } +} + +impl core::ops::DerefMut for Guard<'_, T, B> { + fn deref_mut(&mut self) -> &mut Self::Target { + // SAFETY: The caller owns the lock, so it is safe to deref the protected data. + unsafe { &mut *self.lock.data.get() } + } +} + +impl Drop for Guard<'_, T, B> { + fn drop(&mut self) { + // SAFETY: The caller owns the lock, so it is safe to unlock it. + unsafe { B::unlock(self.lock.state.get(), &self.state) }; + } +} + +impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> { + /// Constructs a new immutable lock guard. + /// + /// # Safety + /// + /// The caller must ensure that it owns the lock. + pub(crate) unsafe fn new(lock: &'a Lock, state: B::GuardState) -> Self { + Self { + lock, + state, + _not_send: PhantomData, + } + } +} From patchwork Sat Apr 8 07:53:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81131 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp739744vqo; Sat, 8 Apr 2023 01:04:34 -0700 (PDT) X-Google-Smtp-Source: AKy350aBUTlVooSEkVd9EKNtJNVG3zs/kXzSljyvlsWndE0h0Isyw3fMUrI/FRsfjeZG2h8PVyAs X-Received: by 2002:a17:906:3854:b0:933:3b2e:6016 with SMTP id w20-20020a170906385400b009333b2e6016mr1843985ejc.7.1680941074218; Sat, 08 Apr 2023 01:04:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680941074; cv=none; d=google.com; s=arc-20160816; b=XLPPGHn3aZEdyVkPsDvv5UT+9IuMywtncOba1ohN0uauRUnAr7rt4QLxXSUuh4k5vR lxv6VhSqjw/P7ATrRaTGCs6rOVd4mfpTV0s4WhS6wwUVzVG9o9PT+Ik2ZABgqFgQIPs6 XMxNtF74db2NvFuV1h/LY07mNbgIDD55h+Zf5ssqRRYFyGmUeijrx1QBdPRH7jyF787Q FhsJzGWhrBkwcKnCFZfhyuB9EVw6m8X8yDrcW8EtiIG3SCrUW/izfVL6mpW95y8LUxFs oNAfO98FUWaumTOIs+JeOkZbVhDYWUaZ4nNowzrMX/C6ZW782o3+TEsOwgS5NKT34QGg B3DQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=VdK7JrX/rQUp7e2zQbiDuLx9MtRcIQVTQroy9sLX/Ho=; b=e3iZSE5Kg5307ducP7FI6EqdeC+/WWyBE9xbgrqPJTf892boXR7YtCdqy7EVbwEEuu 3VcT0NPrntiPsVR1gpf+b291AQGHSrfyjKpW7EqgviW9pBJvZdk0wBeo6DjZ0tZXua+Q 5Gpzbg8ZUQpgHj2rT6hEtzus3uBt0VTZuDCg4uVn4MK1+fYhRh/mo7N2dvWGGBqzS8SE QqJH2XjQ4LJ7eelGaViRd/KsB/9BojdQed2FQKY0tTR8EZ40OVE0l+dc3jq18ZqZxXaw kEqxe4jRJOG+khYAY2G5GTyRfOh8R1FBu1nbrlm29DX1zzzaY4Ye/wkfF89bXDN+gpXw SeSQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=P+MG41Bt; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id go8-20020a1709070d8800b00947de40ef34si5916959ejc.440.2023.04.08.01.04.10; Sat, 08 Apr 2023 01:04:34 -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=@gmail.com header.s=20210112 header.b=P+MG41Bt; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230029AbjDHHyK (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229916AbjDHHyC (ORCPT ); Sat, 8 Apr 2023 03:54:02 -0400 Received: from mail-oi1-x236.google.com (mail-oi1-x236.google.com [IPv6:2607:f8b0:4864:20::236]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85042E18D; Sat, 8 Apr 2023 00:54:01 -0700 (PDT) Received: by mail-oi1-x236.google.com with SMTP id f14so18830837oiw.10; Sat, 08 Apr 2023 00:54:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940441; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VdK7JrX/rQUp7e2zQbiDuLx9MtRcIQVTQroy9sLX/Ho=; b=P+MG41Bt1xeXQU4EkCmu4OXlVwPAqqYePd9ipkYQyF+tlD42dm9J/Oju/lEpLN7Y9S YW4v+cRNoOYiYOp+t8GhpEaFox3UPyg6W/qveFG+GdjDfEUVvTT4ZyxUzupfNuhAKgc5 BI2OSKfL6Tlf9IzOE6gNmWgFybq9zZJJSS6HjIVNLr6Cf9P7pGtC1EnD5JSgN89BFHGj j/nFioLidzT9T5He7N85T19e+Qip75i8u4vlfkj8hL5wBeVx10ZGwJG5H4mzKCiOYaer rVrSwJqCjj6yooyC2kV30Eqz7kdGl5ONgXGujfc72VJgSn46U4iTjZWBaLR4N6vCnWGX ynAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940441; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VdK7JrX/rQUp7e2zQbiDuLx9MtRcIQVTQroy9sLX/Ho=; b=7xkiH603WhyF32JSjR48QWi8hVP9c6SXtVb084McwpUAMcMjr4nDBRXiW2muPZeofy qo6R5ZDRKiZU9qzOpWKnSuPPUeXA3AmKnIEneYvBn4ESeFEANgJ9VCrl6g3eMVa9TgjQ HKhGTzdk8kxSXRAPe35Uz1wiCcvnZ+tCuCngHuAYOHXdE8xqOTTUM432j3s3qjHr6Tdy GUhl7HnDbBglIICtxJyz+bZkxRzVD+q+c/JItVx4BoUsXBsVxkc66VKnCcM59QhwiHzY YqO6/fuAJeFV6XwXNB09XOQPhTOQhUNkaKO8cMy27Mpmq3iTUEUsyZS93L/HSVZNZqu5 z+LQ== X-Gm-Message-State: AAQBX9cLa+os2wgbGgyWsTSppNgVoIfso0Jh+Jdk3q4jCvIQ20wE5Kao 840U3t9CjUJv7ul85+vRgmaD62ONEfst2g== X-Received: by 2002:a05:6808:1396:b0:386:c879:d3ae with SMTP id c22-20020a056808139600b00386c879d3aemr7582840oiw.10.1680940440748; Sat, 08 Apr 2023 00:54:00 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.53.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:00 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v3 03/13] rust: lock: introduce `Mutex` Date: Sat, 8 Apr 2023 04:53:30 -0300 Message-Id: <20230408075340.25237-3-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594467722240276?= X-GMAIL-MSGID: =?utf-8?q?1762594467722240276?= From: Wedson Almeida Filho This is the `struct mutex` lock backend and allows Rust code to use the kernel mutex idiomatically. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes rust/helpers.c | 7 ++ rust/kernel/sync.rs | 1 + rust/kernel/sync/lock.rs | 2 + rust/kernel/sync/lock/mutex.rs | 118 +++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 rust/kernel/sync/lock/mutex.rs diff --git a/rust/helpers.c b/rust/helpers.c index 09a4d93f9d62..3010a2ec26e2 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -21,6 +21,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -28,6 +29,12 @@ __noreturn void rust_helper_BUG(void) } EXPORT_SYMBOL_GPL(rust_helper_BUG); +void rust_helper_mutex_lock(struct mutex *lock) +{ + mutex_lock(lock); +} +EXPORT_SYMBOL_GPL(rust_helper_mutex_lock); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 81b0998eaa18..693f0b7f4e4f 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -11,6 +11,7 @@ mod arc; pub mod lock; pub use arc::{Arc, ArcBorrow, UniqueArc}; +pub use lock::mutex::Mutex; /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. #[repr(transparent)] diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index 3fa4eefde740..86669f771ee0 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -10,6 +10,8 @@ use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque}; use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned}; use macros::pin_data; +pub mod mutex; + /// The "backend" of a lock. /// /// It is the actual implementation of the lock, without the need to repeat patterns used in all diff --git a/rust/kernel/sync/lock/mutex.rs b/rust/kernel/sync/lock/mutex.rs new file mode 100644 index 000000000000..923472f04af4 --- /dev/null +++ b/rust/kernel/sync/lock/mutex.rs @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A kernel mutex. +//! +//! This module allows Rust code to use the kernel's `struct mutex`. + +use crate::bindings; + +/// Creates a [`Mutex`] initialiser with the given name and a newly-created lock class. +/// +/// It uses the name if one is given, otherwise it generates one based on the file name and line +/// number. +#[macro_export] +macro_rules! new_mutex { + ($inner:expr $(, $name:literal)? $(,)?) => { + $crate::sync::Mutex::new( + $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!()) + }; +} + +/// A mutual exclusion primitive. +/// +/// Exposes the kernel's [`struct mutex`]. When multiple threads attempt to lock the same mutex, +/// only one at a time is allowed to progress, the others will block (sleep) until the mutex is +/// unlocked, at which point another thread will be allowed to wake up and make progress. +/// +/// Since it may block, [`Mutex`] needs to be used with care in atomic contexts. +/// +/// Instances of [`Mutex`] need a lock class and to be pinned. The recommended way to create such +/// instances is with the [`pin_init`](crate::pin_init) and [`new_mutex`] macros. +/// +/// # Examples +/// +/// The following example shows how to declare, allocate and initialise a struct (`Example`) that +/// contains an inner struct (`Inner`) that is protected by a mutex. +/// +/// ``` +/// use kernel::{init::InPlaceInit, init::PinInit, new_mutex, pin_init, sync::Mutex}; +/// +/// struct Inner { +/// a: u32, +/// b: u32, +/// } +/// +/// #[pin_data] +/// struct Example { +/// c: u32, +/// #[pin] +/// d: Mutex, +/// } +/// +/// impl Example { +/// fn new() -> impl PinInit { +/// pin_init!(Self { +/// c: 10, +/// d <- new_mutex!(Inner { a: 20, b: 30 }), +/// }) +/// } +/// } +/// +/// // Allocate a boxed `Example`. +/// let e = Box::pin_init(Example::new())?; +/// assert_eq!(e.c, 10); +/// assert_eq!(e.d.lock().a, 20); +/// assert_eq!(e.d.lock().b, 30); +/// ``` +/// +/// The following example shows how to use interior mutability to modify the contents of a struct +/// protected by a mutex despite only having a shared reference: +/// +/// ``` +/// use kernel::sync::Mutex; +/// +/// struct Example { +/// a: u32, +/// b: u32, +/// } +/// +/// fn example(m: &Mutex) { +/// let mut guard = m.lock(); +/// guard.a += 10; +/// guard.b += 20; +/// } +/// ``` +/// +/// [`struct mutex`]: ../../../../include/linux/mutex.h +pub type Mutex = super::Lock; + +/// A kernel `struct mutex` lock backend. +pub struct MutexBackend; + +// SAFETY: The underlying kernel `struct mutex` object ensures mutual exclusion. +unsafe impl super::Backend for MutexBackend { + type State = bindings::mutex; + type GuardState = (); + + unsafe fn init( + ptr: *mut Self::State, + name: *const core::ffi::c_char, + key: *mut bindings::lock_class_key, + ) { + // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and + // `key` are valid for read indefinitely. + unsafe { bindings::__mutex_init(ptr, name, key) } + } + + unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { + // SAFETY: The safety requirements of this function ensure that `ptr` points to valid + // memory, and that it has been initialised before. + unsafe { bindings::mutex_lock(ptr) }; + } + + unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { + // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the + // caller is the owner of the mutex. + unsafe { bindings::mutex_unlock(ptr) }; + } +} From patchwork Sat Apr 8 07:53:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81125 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp736163vqo; Sat, 8 Apr 2023 00:55:49 -0700 (PDT) X-Google-Smtp-Source: AKy350a8UQe2bKds4jqQcZAqbBDST/C2G+mKrSi2UaWwgWOH+S0vtuYp3N2bLVZv1mKuGrMkZHk6 X-Received: by 2002:a17:906:4a56:b0:932:e368:fbe7 with SMTP id a22-20020a1709064a5600b00932e368fbe7mr1667864ejv.29.1680940549154; Sat, 08 Apr 2023 00:55:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940549; cv=none; d=google.com; s=arc-20160816; b=zVPikbazt+f1vzAFXOrbWtPy2esMrRSU2hY/hISfJDBfo5Aas6+jhER3Za8I8awIP4 xZPDCID7b8YbypkMrfApR/lQNtWAPLTJkG0WNqhRB6EMaSeQQrnPjuHE+6mfDqt3LOiz hIIvmToa5I09+QYt87C9RP6kpUladULzuvSmkRZS45AQb4WQa9/7F+J83zM2H/AdIest 1zddspyCLKKNXBP0/+su/Sto2pVOvSqzK2lMfN4dpvl5lEsKWBMYSDqGLil97O6O5R4l bzt8snQFbcyK8nOAFxyDTmHpWJ+Cq+bS5uVaXSr8z9IVP0rKDyt2CYCZRg0hFdeUZq4w gNhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ht+Snw7oqKAYwWbuQnCqRHObcbb/KZ3skYYXvWfrZk8=; b=L3EJIEe9Big3bN718MSq3GSSbXHTpHOkSUadezVRyQ5DAqwBo1sWcflZ57roVX1qcv Gl0f5L7i1ydUtJ2SZF3PPY26I5ljtVTMzr8h1oQbhFXzRqel3IM54/rUiw0t/prbmGww oDuTG6kn79VzVUUJh9f/PA4P2b49jDuAjqBZVZygEMZ5IB/d4JDsVeiwwEpMQf+aUzr3 UL/zO2w/IOxbZhyiVa44Qklugmyb1S7x5yw9rWeLDR9znBze2x2oZXfrW7iq7EUETnix b75/OmbQwEIBd3Kx/vJVUP6CcroKagERs+SC6TBIL0bPi2C8sHWQ1srLHqiuW3sSFy2I FSiQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=D5nB5m8H; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t24-20020a170906949800b009212a3f8496si4269533ejx.666.2023.04.08.00.55.24; Sat, 08 Apr 2023 00:55:49 -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=@gmail.com header.s=20210112 header.b=D5nB5m8H; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230007AbjDHHyM (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229960AbjDHHyG (ORCPT ); Sat, 8 Apr 2023 03:54:06 -0400 Received: from mail-oi1-x236.google.com (mail-oi1-x236.google.com [IPv6:2607:f8b0:4864:20::236]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0326EFBD; Sat, 8 Apr 2023 00:54:04 -0700 (PDT) Received: by mail-oi1-x236.google.com with SMTP id f14so18830902oiw.10; Sat, 08 Apr 2023 00:54:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940444; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ht+Snw7oqKAYwWbuQnCqRHObcbb/KZ3skYYXvWfrZk8=; b=D5nB5m8Hn67ITtdKlaB0dHuMUxSNyMOaAEpOmuO86juhbgRRRD+MV0Ot+fB9CFEamj v3NglJw1JZGFQ4oW6cHzBe9GPotPulpRlMBnEub+FEYvpjKUctc14IDvwJ6I471KOQF2 Iyer6YfRpXXesByamiBfqbv1TGrtJBKyYnM+8SUXHsjhNenIUymUrwiCwFIaZ98Wwfnv 0byZ9JHBc2oTqFuGyGBJC59LFmfVAuoHln1Br/i2HSKf2TIZxfQcTtqlxwnve7OXNA3m KTkf6b3u4OXLKMjmCTvLuCyfekFRNCL46A4y0sxWksGjVliXtbtQasRiEm/3K3f65ivI vfKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940444; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ht+Snw7oqKAYwWbuQnCqRHObcbb/KZ3skYYXvWfrZk8=; b=A39VdogPMfF1JK8ybqyynktEuQ5bV5kInFPPvN96wBZH0hRMmpOqa7XfMEcSSZ851D XSo9FkPsr7W557nWyoVqV1OrvEwOl6eV9E0xl0o4+12QmEMME/5Vr2WomgQ6IckdHpob 1v+dlMbkYnxDWml93jfjJX6ZgInYiZjBp2zaVpO9gaPlpNwZL0h1pqa/bldOTO8HJ0Rg C0MWuO/obGcYDt9E6KB0ZWDC1ifo0xm+mFUDyS7hRcl0IXpNE9TmIHUjtfIse3jKCEtH U5+ViR/jm6p362TmFOGjYBFI9KBp614+NfIxU1cut6Dft3GUESc3hyzbXyqFZRhqI/BS HMnA== X-Gm-Message-State: AAQBX9dDgkE4KTWlPLDg7e5K266iIo8TyF/jtmpQLyUy/8YahnmmO4BL EDR2FmJ6J2JugVJDqbZAykEsNtQ8azkjHg== X-Received: by 2002:aca:2304:0:b0:384:1221:9a24 with SMTP id e4-20020aca2304000000b0038412219a24mr1826021oie.27.1680940444328; Sat, 08 Apr 2023 00:54:04 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:04 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v3 04/13] locking/spinlock: introduce spin_lock_init_with_key Date: Sat, 8 Apr 2023 04:53:31 -0300 Message-Id: <20230408075340.25237-4-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762593917478323357?= X-GMAIL-MSGID: =?utf-8?q?1762593917478323357?= From: Wedson Almeida Filho Rust cannot call C macros, so it has its own macro to create a new lock class when a spin lock is initialised. This new function allows Rust code to pass the lock class it generates to the C implementation. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes include/linux/spinlock.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index be48f1cb1878..cdc92d095133 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -327,12 +327,17 @@ static __always_inline raw_spinlock_t *spinlock_check(spinlock_t *lock) #ifdef CONFIG_DEBUG_SPINLOCK +static inline void spin_lock_init_with_key(spinlock_t *lock, const char *name, + struct lock_class_key *key) +{ + __raw_spin_lock_init(spinlock_check(lock), name, key, LD_WAIT_CONFIG); +} + # define spin_lock_init(lock) \ do { \ static struct lock_class_key __key; \ \ - __raw_spin_lock_init(spinlock_check(lock), \ - #lock, &__key, LD_WAIT_CONFIG); \ + spin_lock_init_with_key(lock, #lock, &__key); \ } while (0) #else From patchwork Sat Apr 8 07:53:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81134 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp741503vqo; Sat, 8 Apr 2023 01:08:48 -0700 (PDT) X-Google-Smtp-Source: AKy350YT5kEoFONyHsVyUjwTGSmA9QR2mnjFRm3+Y9t0Rh2W74vV7lULVriGmAr3wjPw7go0unqw X-Received: by 2002:a05:6402:289:b0:4ad:1e35:771f with SMTP id l9-20020a056402028900b004ad1e35771fmr5005298edv.35.1680941327962; Sat, 08 Apr 2023 01:08:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680941327; cv=none; d=google.com; s=arc-20160816; b=pE5gQqKNYMThX2rCSH+lVMbGvohW9M1sg6TQXT44Ofwg7VZGkU3j+NeeY93NQuObI5 3LzKd1E0R/VmDuvembaKur6olZbRxhd4QhTaJo9htXDDkb/fY/ukYLXt5rklMqa9rXHt cCrsbtDxjw5LIsI2nROWCrDHi3J/5vCf0ow9dAFBAwxL1i3TSz3lSxqu9RsEug/DpqrE I9CwIWZTH92QOADjbo2yygrdn7ORqDt6uKF2y5B92MbZwojJWTSrH9aR4xea36PRqphr pUFKR91ANDa0aLkI6Y9eIojrjuqPwk9Gkh+g48/NkT7QLwpz8G25rKf2Sv9+kYU3LmBO Srbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=fCIy9oWgXj2uukTwz+wLvhTfnk8J7gqXwsBwYiH3dvY=; b=RNRAskuiFXms3EY6fKm9EEOFd+65k3bcI6LI9dG+e4STeoSamL8TLHV5KRS7hfWHtn uUOae//ZHwLqdCevvGYmeh21KnVglGeWG4FBNYc9HAfsIMHyO5P63G2RbSBFUaM51vGj yZFl77ib3LoTG5I1uIqbkbU9qCENGQZhfrBhIlGfyir+QaqpK8iIwk95pszb3Qmng+Ka 0JUIQIyVvH4+g9aC7f1IBy+0lvZQ4+rTs2E5v5tS/Rju0IyDC5JvEmHPWopzp1txIGsu vQNlU3YMGW9C+/6d/iDIWo1hoT4LnF/iAwZsX1nhQKftchWaTplA6IzVfG+7j28tC9UR q/Gw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=HbVGEVIo; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p21-20020aa7d315000000b004fd2b154c18si765523edq.500.2023.04.08.01.08.24; Sat, 08 Apr 2023 01:08:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=HbVGEVIo; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230130AbjDHHyf (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230024AbjDHHyM (ORCPT ); Sat, 8 Apr 2023 03:54:12 -0400 Received: from mail-oo1-xc32.google.com (mail-oo1-xc32.google.com [IPv6:2607:f8b0:4864:20::c32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D8FACFF0B; Sat, 8 Apr 2023 00:54:08 -0700 (PDT) Received: by mail-oo1-xc32.google.com with SMTP id s19-20020a4adb93000000b00540fa505f2dso3510443oou.7; Sat, 08 Apr 2023 00:54:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940448; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fCIy9oWgXj2uukTwz+wLvhTfnk8J7gqXwsBwYiH3dvY=; b=HbVGEVIoT0T84EpkWcmPKFN5zBz27O5/uACQftnKKGrdkvQPOxzhd3RooheEEuAv+4 XD9GCXT1LRa30jFL8xKBClRizjfsolMSAhB0ymtS/CRvx4ZRGjocS4rfTOPhD066pfMB Ik9qyZKBetG3xu5t8GceFwonWtpxjfrpaZdHA4LuJy/v/osTGKi216iw+ZZu/nJ/kbYv lM5VLYHEkRTGtk1eBLsc9hGBKZdDfagZ3RoUocJ6Bm8rZQcfmxoW3bLOcu+RpA6U6S3M OYg0Vp8pDTLeX6RBJCx4HAfttXC/4J/IGTQZMDrPfCk540tgfm3XoAPqwCS1i4EXzDBD rx4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940448; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fCIy9oWgXj2uukTwz+wLvhTfnk8J7gqXwsBwYiH3dvY=; b=ZobwMu9lMyUSqgVyWSP2VrzoQy0a3dcc250WhI4bA64sDHfAXSfug6Ww+QGt95zRiJ RYNoAj36xRekM3zVXK8HAZZKfvI8HUKsiVsY5rgDufgrQTTNsUP3iG6LJJRWivXRrP2O Cp06vAEe9E6YBG66XzRaxEyuNy1tJ1xlLXsrM9dc1OTGwLtpIS1CjFMEpYmghrfqWqDO nL8U2aLhxa0f07u+5Ui8tCuI04LL+Z9gjZwBJixYvfLhCGT/NPj8miQaqLUAvOWoCr9v CEyhLU2CjCG/+9elmaxUqQS6bWjJbvw+g4ds7IDa3I20xdT3djG5IO7GDsiv7a1Nf2Lv HYmw== X-Gm-Message-State: AAQBX9dKJRukywZObT6VlARYvX2G3g7dDE9YyL/IDB6b8KwGY6MVloHH ot1Cg2rf3h52ghkNIV0XfkcPVQn+rMKSCg== X-Received: by 2002:a4a:9613:0:b0:541:5644:3154 with SMTP id q19-20020a4a9613000000b0054156443154mr2029901ooi.8.1680940447914; Sat, 08 Apr 2023 00:54:07 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:07 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v3 05/13] rust: lock: introduce `SpinLock` Date: Sat, 8 Apr 2023 04:53:32 -0300 Message-Id: <20230408075340.25237-5-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594734036042670?= X-GMAIL-MSGID: =?utf-8?q?1762594734036042670?= From: Wedson Almeida Filho This is the `spinlock_t` lock backend and allows Rust code to use the kernel spinlock idiomatically. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes rust/helpers.c | 24 +++++++ rust/kernel/sync.rs | 2 +- rust/kernel/sync/lock.rs | 1 + rust/kernel/sync/lock/spinlock.rs | 116 ++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/lock/spinlock.rs diff --git a/rust/helpers.c b/rust/helpers.c index 3010a2ec26e2..05694e3f8f70 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -22,6 +22,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -35,6 +36,29 @@ void rust_helper_mutex_lock(struct mutex *lock) } EXPORT_SYMBOL_GPL(rust_helper_mutex_lock); +void rust_helper___spin_lock_init(spinlock_t *lock, const char *name, + struct lock_class_key *key) +{ +#ifdef CONFIG_DEBUG_SPINLOCK + spin_lock_init_with_key(lock, name, key); +#else + spin_lock_init(lock); +#endif +} +EXPORT_SYMBOL_GPL(rust_helper___spin_lock_init); + +void rust_helper_spin_lock(spinlock_t *lock) +{ + spin_lock(lock); +} +EXPORT_SYMBOL_GPL(rust_helper_spin_lock); + +void rust_helper_spin_unlock(spinlock_t *lock) +{ + spin_unlock(lock); +} +EXPORT_SYMBOL_GPL(rust_helper_spin_unlock); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 693f0b7f4e4f..c997ff7e951e 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -11,7 +11,7 @@ mod arc; pub mod lock; pub use arc::{Arc, ArcBorrow, UniqueArc}; -pub use lock::mutex::Mutex; +pub use lock::{mutex::Mutex, spinlock::SpinLock}; /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. #[repr(transparent)] diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index 86669f771ee0..df43dff5af5c 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -11,6 +11,7 @@ use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned}; use macros::pin_data; pub mod mutex; +pub mod spinlock; /// The "backend" of a lock. /// diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs new file mode 100644 index 000000000000..a52d20fc9755 --- /dev/null +++ b/rust/kernel/sync/lock/spinlock.rs @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A kernel spinlock. +//! +//! This module allows Rust code to use the kernel's `spinlock_t`. + +use crate::bindings; + +/// Creates a [`SpinLock`] initialiser with the given name and a newly-created lock class. +/// +/// It uses the name if one is given, otherwise it generates one based on the file name and line +/// number. +#[macro_export] +macro_rules! new_spinlock { + ($inner:expr $(, $name:literal)? $(,)?) => { + $crate::sync::SpinLock::new( + $inner, $crate::optional_name!($($name)?), $crate::static_lock_class!()) + }; +} + +/// A spinlock. +/// +/// Exposes the kernel's [`spinlock_t`]. When multiple CPUs attempt to lock the same spinlock, only +/// one at a time is allowed to progress, the others will block (spinning) until the spinlock is +/// unlocked, at which point another CPU will be allowed to make progress. +/// +/// Instances of [`SpinLock`] need a lock class and to be pinned. The recommended way to create such +/// instances is with the [`pin_init`](crate::pin_init) and [`new_spinlock`] macros. +/// +/// # Examples +/// +/// The following example shows how to declare, allocate and initialise a struct (`Example`) that +/// contains an inner struct (`Inner`) that is protected by a spinlock. +/// +/// ``` +/// use kernel::{init::InPlaceInit, init::PinInit, new_spinlock, pin_init, sync::SpinLock}; +/// +/// struct Inner { +/// a: u32, +/// b: u32, +/// } +/// +/// #[pin_data] +/// struct Example { +/// c: u32, +/// #[pin] +/// d: SpinLock, +/// } +/// +/// impl Example { +/// fn new() -> impl PinInit { +/// pin_init!(Self { +/// c: 10, +/// d <- new_spinlock!(Inner { a: 20, b: 30 }), +/// }) +/// } +/// } +/// +/// // Allocate a boxed `Example`. +/// let e = Box::pin_init(Example::new())?; +/// assert_eq!(e.c, 10); +/// assert_eq!(e.d.lock().a, 20); +/// assert_eq!(e.d.lock().b, 30); +/// ``` +/// +/// The following example shows how to use interior mutability to modify the contents of a struct +/// protected by a spinlock despite only having a shared reference: +/// +/// ``` +/// use kernel::sync::SpinLock; +/// +/// struct Example { +/// a: u32, +/// b: u32, +/// } +/// +/// fn example(m: &SpinLock) { +/// let mut guard = m.lock(); +/// guard.a += 10; +/// guard.b += 20; +/// } +/// ``` +/// +/// [`spinlock_t`]: ../../../../include/linux/spinlock.h +pub type SpinLock = super::Lock; + +/// A kernel `spinlock_t` lock backend. +pub struct SpinLockBackend; + +// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. +unsafe impl super::Backend for SpinLockBackend { + type State = bindings::spinlock_t; + type GuardState = (); + + unsafe fn init( + ptr: *mut Self::State, + name: *const core::ffi::c_char, + key: *mut bindings::lock_class_key, + ) { + // SAFETY: The safety requirements ensure that `ptr` is valid for writes, and `name` and + // `key` are valid for read indefinitely. + unsafe { bindings::__spin_lock_init(ptr, name, key) } + } + + unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { + // SAFETY: The safety requirements of this function ensure that `ptr` points to valid + // memory, and that it has been initialised before. + unsafe { bindings::spin_lock(ptr) } + } + + unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { + // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the + // caller is the owner of the mutex. + unsafe { bindings::spin_unlock(ptr) } + } +} From patchwork Sat Apr 8 07:53:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81126 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp736289vqo; Sat, 8 Apr 2023 00:56:12 -0700 (PDT) X-Google-Smtp-Source: AKy350YppPBh3MApFisWwdZ5NoyJPvm1mP/6V8B3tB4r2oqU6KYpgBoS3EYVhBxfHyMVVaYtyG3b X-Received: by 2002:aa7:d60c:0:b0:502:9578:38ed with SMTP id c12-20020aa7d60c000000b00502957838edmr755350edr.27.1680940572620; Sat, 08 Apr 2023 00:56:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940572; cv=none; d=google.com; s=arc-20160816; b=iGGXRRqZ/pe/Etk0rjAQIleN0mglbMAALtcmNQGssp0aOsQc/pdDrsr1zN1Gm55joO 29pkeh2UHMNq2Nqw7kbylBXFhW3DSxn1exetOxZ6D9n3l75RKmMw9og6AApM5KtkCUD/ sNDIxgvU6DteFU2O0kC9BCIxtkG0nHb0oSP47uaMy77nAgFG3ilrhug7vSMkhRQjuaVE kynXKmzSr98FQ7eJEGNwICJj2WQWK/DZ8VpqO43J5MuTBuhJs1VOBPsL9eMxyubP5cT8 qMsL8M1nl+3Qg1r+bvyYUywsa6cNcg7fqbpAIkLrzYbwU/MxiVweqyQoFwKY4oTa4mNn 0X7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=wpOoeU4Qo2xSWrP8Zd47XosmBdNzXp8ItY0SM633XWM=; b=DE/ZLdm6suo+dD1XLQ0ycBOdYVOMg9Fw2tJofi2tu/tn1FmBdZ0sdU7w57uAeAqk2V ELMDnLfWCcii1O6TVfmwCosru8qOcLME3QjQV0mBnoVQUbMbbnVb4IC/SH1J7+WYFIyK vKG7nWPO+rlPtisALM6C5toMXtvXLc98rcmoYKsRHxrQTXmbokzGsF6x53YWDRvQtFlt To6kT54eO+emUgJmxxbC3oFyuUQH2ZxmKicYsrDmFC0TDfIaEf0d+cQ/rvCjg+E/Ix2A G0LBRk2jLw3MGbWCBR5weDKtzF++BAULFdS8cL6rR66Nxzl801qSqAmucx+MH0Lh10Mc kwzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=XLHoIICN; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z1-20020a50eb41000000b004fd1ef9b95csi5099769edp.598.2023.04.08.00.55.49; Sat, 08 Apr 2023 00:56:12 -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=@gmail.com header.s=20210112 header.b=XLHoIICN; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230186AbjDHHyk (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59762 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230056AbjDHHyQ (ORCPT ); Sat, 8 Apr 2023 03:54:16 -0400 Received: from mail-oo1-xc31.google.com (mail-oo1-xc31.google.com [IPv6:2607:f8b0:4864:20::c31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0C981EF91; Sat, 8 Apr 2023 00:54:11 -0700 (PDT) Received: by mail-oo1-xc31.google.com with SMTP id g26-20020a4adc9a000000b0053b9059edd5so101132oou.3; Sat, 08 Apr 2023 00:54:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940451; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wpOoeU4Qo2xSWrP8Zd47XosmBdNzXp8ItY0SM633XWM=; b=XLHoIICN4WFwHuDBqxfKuglpmeOGb0tM/R0Hg70PpgPHdHtnZs4dWSz8OGj0GBvj+w RmXHSyGsBLFukKlZM6mC4tGYngB2/VEOVVrfQwQ/PZG0wJHWUIUOnmxLTXJZh4VgfXIo Yyvy6fBIYsGXtrdawKmHht6TDayR3g4d4zzYewKAmh3JlCuX3A2vLmD51ZkI7bZ6qBB/ vuNBDV0eo1AjVf84FlG6LoZ/hpS+cUGCxF3KLH+roU5FIOV9UnHVCVQSulDOMdWwh+9x pPzsg9DlH1NeuCgqSLRUwLaRnnUNLKQ/xwJX6SIiuK+2mKPy9A8QSm204DTuI4LaZSMQ U0TQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940451; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wpOoeU4Qo2xSWrP8Zd47XosmBdNzXp8ItY0SM633XWM=; b=LRsH13/nkR9WTA4H447eUIqurpK49UVf3ww1taBd0YL/hhdAZ0wgEmRsH7f05DNZAC Xsw+RGxlRCo26cvpA3+e0Nxt2rl7PBr9reK3tIfeLlDfggYg+l/YSx8SQMGdebGygq+d 8mD+mj/9N4SvEMOP/dKUeZ86mQa4a48Eaa3JDJS0mUyR9E/butChLlk+p+8u3yXzG+zf /6alUKwVOwYYtBeYM+18dRHpPkPuuIqCVtQ4blwDGVS4Iyi6AUlug2hbMEeAZd8zcLHf CUweiNlieRAWs9zpGZYpWO7skT0DEAhRF7EthXT5MsA9q36u1+FR672aPTbfeNHq2PO9 68bw== X-Gm-Message-State: AAQBX9fvgxtk5ZC1g7UOjA4xWXdZkVMx1XzmmlcJr00ogN8mvYdlELc0 Lc+YviD4yhYqdA1LcfMNF6L4GKw/BkQ= X-Received: by 2002:a4a:58cb:0:b0:517:a7d1:9762 with SMTP id f194-20020a4a58cb000000b00517a7d19762mr2437292oob.7.1680940450726; Sat, 08 Apr 2023 00:54:10 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:10 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v3 06/13] rust: lock: add support for `Lock::lock_irqsave` Date: Sat, 8 Apr 2023 04:53:33 -0300 Message-Id: <20230408075340.25237-6-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762593941643283365?= X-GMAIL-MSGID: =?utf-8?q?1762593941643283365?= From: Wedson Almeida Filho This allows locks like spinlocks and raw spinlocks to expose a `lock_irqsave` variant in Rust that corresponds to the C version. Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes rust/kernel/sync/lock.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index df43dff5af5c..690429561f0e 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -57,6 +57,29 @@ pub unsafe trait Backend { unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState); } +/// The "backend" of a lock that supports the irq-save variant. +/// +/// # Safety +/// +/// The same requirements wrt mutual exclusion in [`Backend`] apply for acquiring the lock via +/// [`IrqSaveBackend::lock_irqsave`]. +/// +/// Additionally, when [`IrqSaveBackend::lock_irqsave`] is used to acquire the lock, implementers +/// must disable interrupts on lock, and restore interrupt state on unlock. Implementers may use +/// [`Backend::GuardState`] to store state needed to keep track of the interrupt state. +pub unsafe trait IrqSaveBackend: Backend { + /// Acquires the lock, making the caller its owner. + /// + /// Before acquiring the lock, it disables interrupts, and returns the previous interrupt state + /// as its guard state so that the guard can restore it when it is dropped. + /// + /// # Safety + /// + /// Callers must ensure that [`Backend::init`] has been previously called. + #[must_use] + unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState; +} + /// A mutual exclusion primitive. /// /// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock banckend @@ -111,6 +134,21 @@ impl Lock { } } +impl Lock { + /// Acquires the lock and gives the caller access to the data protected by it. + /// + /// Before acquiring the lock, it disables interrupts. When the guard is dropped, the interrupt + /// state (either enabled or disabled) is restored to its state before + /// [`lock_irqsave`](Self::lock_irqsave) was called. + pub fn lock_irqsave(&self) -> Guard<'_, T, B> { + // SAFETY: The constructor of the type calls `init`, so the existence of the object proves + // that `init` was called. + let state = unsafe { B::lock_irqsave(self.state.get()) }; + // SAFETY: The lock was just acquired. + unsafe { Guard::new(self, state) } + } +} + /// A lock guard. /// /// Allows mutual exclusion primitives that implement the `Backend` trait to automatically unlock From patchwork Sat Apr 8 07:53:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81135 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp742035vqo; Sat, 8 Apr 2023 01:10:07 -0700 (PDT) X-Google-Smtp-Source: AKy350Z2FE+JcewZQo+U1j7zIPFHQubGvcA8qixRukqS2rlbvkgxGJSdjEi99XmYRTG9aodiehDk X-Received: by 2002:a17:906:551:b0:947:895a:bd82 with SMTP id k17-20020a170906055100b00947895abd82mr1580952eja.56.1680941407124; Sat, 08 Apr 2023 01:10:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680941407; cv=none; d=google.com; s=arc-20160816; b=wDIdRlU7EetY1KVZsn6/TgtNv5ztJSs49w7+0l5OnYylnz+AfAgcBPnDjiVNrUaZZ6 ClU630Qu2H0+SlVrb1EPT/D3l3k+IftQuGPlUDimmqwSqdb5xQbCvRnZFlnfcVxnETwH dcv+Mcprdxm0Yp39nnRtlA4Skyrjyt8Ry4oo4iZvk1eA3EEnT8lQagOXuV4VUUYwcGD2 bf1re8pjWwRDqVZ5YTTDMHlf3u+ywhEHay7tWuR/6Gp10dYEmPC68rXRtcsZsTSL9Ysv hpocb8KMxuqg90M5z9yEmrUfqG7sRdQUAoYbzfF2ngUf1tkOR38C8TbIjiZ4oJOfTksP V4ow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=dBxUeM8crjQUn0jyMS6RnqsghfeEHmI+/co92h1YSAk=; b=cOZ5ue1lR3VLb11NOJNl6hMd4udo8Qibv2MdTkuNfj6/WDrG+RBqa2udtCx/ufyf5n +myaoevJHJPPqSw2Netq9vTLUmUPZcZbCMQyi3VsC7NVWw12xIy+AKbHtFBUSPYl7Bzb PNXTRO1jxmnSFWRsGspFg2RgBaOyfibxIo7T7yi1wBKXH/O9lY8KbdrRt4zuYcZ0jEc3 t24KKFYmlHjv2tWQ7GIH5iREzzKCzOU6glWEGNI4oy5ErJVzsvjP0hqX6Mj+s6mIRFR3 Hemimld6mE6EF58VF0+RMzyh+Hs05I6RrM9jHCp99U4sUf7lLLfu3gOI/BStpIdEZdah dtCw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=l+eOLhyI; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ce25-20020a170906b25900b00933a21fc97esi4998237ejb.964.2023.04.08.01.09.42; Sat, 08 Apr 2023 01:10:07 -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=@gmail.com header.s=20210112 header.b=l+eOLhyI; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230116AbjDHHyw (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230002AbjDHHye (ORCPT ); Sat, 8 Apr 2023 03:54:34 -0400 Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com [IPv6:2607:f8b0:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE204FF39; Sat, 8 Apr 2023 00:54:15 -0700 (PDT) Received: by mail-oi1-x22f.google.com with SMTP id e9so367457oig.7; Sat, 08 Apr 2023 00:54:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940454; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=dBxUeM8crjQUn0jyMS6RnqsghfeEHmI+/co92h1YSAk=; b=l+eOLhyIOXbDPYc+MMNtiUiw/U72JUbsHkAopXReimehmfMU4o2ydiiZd7ufpKdK9f zZhiUB0hGWmcEJcFhNRImfT/GmX7CVEWCfgDPUpwSMoKQxOPjljK3e6VvlrwSrrfq5i9 4+hQMfEeO12aXDEDRRNzHSU4WVE/1UplKV96axp5Fvk0JyzN0N64tYtgij+P4s6vn5vT boKZF6PCb9M7if2o0T0ap1ZSF53DLBWcaOmJbsaLlMuFTihmBdqwjsY/6J5LaddKxlFK 4PTdOuIT2D4aUboHDnd/wA50h2qaX9gTy8uYOuSdDQpvDJL5XeZBRCmszXFhpRif2Zro izWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940454; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dBxUeM8crjQUn0jyMS6RnqsghfeEHmI+/co92h1YSAk=; b=VSzsxVIeIx5aibyYKeLOzSbqxII1PtQXaULT0Z2rzKD2oW7Lq2FyXo/NdinS/QujS9 2WznpOXMCw3I2KWOI1gECXIT/4Ep7lYPF2Tk+6vkW35HzkIXsyRi8MmUn7E5SawjVDDN pSfnSAVpw0Ubkh6Y2RuRro6v8geGd11NqGS6B6rpX9owAf8bDfZ9+UpSudUs9eV6jUzx CUBCKlM9ebs2r6l2P+iehOlXoHRVhYCHPkA1V1UA70E3znhC0m0T011ivDoSjLzL9HgF 62jgKzdB1rPuM4K+1hnc9wanZ9JN/QGhmYCs/nekw4dTUugs7CFNeiVsE64v8uVGPUBJ dSFw== X-Gm-Message-State: AAQBX9eb/sjMlee2hS/fOzIdxNcMw7PqoEFo3cIBLtBu9ZHWezSY6V0/ jmhFYFeMMTJIfuiyV/mnlPluCCL19v22Pg== X-Received: by 2002:a05:6808:aba:b0:38b:8d27:ff52 with SMTP id r26-20020a0568080aba00b0038b8d27ff52mr2016970oij.53.1680940454290; Sat, 08 Apr 2023 00:54:14 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:14 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v3 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Date: Sat, 8 Apr 2023 04:53:34 -0300 Message-Id: <20230408075340.25237-7-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594816680542715?= X-GMAIL-MSGID: =?utf-8?q?1762594816680542715?= From: Wedson Almeida Filho This allows Rust code to use the `lock_irqsave` variant of spinlocks. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes rust/helpers.c | 16 +++++++++++++ rust/kernel/sync/lock/spinlock.rs | 38 ++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/rust/helpers.c b/rust/helpers.c index 05694e3f8f70..e42f5b446f92 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -59,6 +59,22 @@ void rust_helper_spin_unlock(spinlock_t *lock) } EXPORT_SYMBOL_GPL(rust_helper_spin_unlock); +unsigned long rust_helper_spin_lock_irqsave(spinlock_t *lock) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + + return flags; +} +EXPORT_SYMBOL_GPL(rust_helper_spin_lock_irqsave); + +void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) +{ + spin_unlock_irqrestore(lock, flags); +} +EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs index a52d20fc9755..34dec09a97c0 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -61,6 +61,8 @@ macro_rules! new_spinlock { /// assert_eq!(e.c, 10); /// assert_eq!(e.d.lock().a, 20); /// assert_eq!(e.d.lock().b, 30); +/// assert_eq!(e.d.lock_irqsave().a, 20); +/// assert_eq!(e.d.lock_irqsave().b, 30); /// ``` /// /// The following example shows how to use interior mutability to modify the contents of a struct @@ -79,6 +81,12 @@ macro_rules! new_spinlock { /// guard.a += 10; /// guard.b += 20; /// } +/// +/// fn example2(m: &SpinLock) { +/// let mut guard = m.lock_irqsave(); +/// guard.a += 10; +/// guard.b += 20; +/// } /// ``` /// /// [`spinlock_t`]: ../../../../include/linux/spinlock.h @@ -90,7 +98,7 @@ pub struct SpinLockBackend; // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. unsafe impl super::Backend for SpinLockBackend { type State = bindings::spinlock_t; - type GuardState = (); + type GuardState = Option; unsafe fn init( ptr: *mut Self::State, @@ -105,12 +113,30 @@ unsafe impl super::Backend for SpinLockBackend { unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { // SAFETY: The safety requirements of this function ensure that `ptr` points to valid // memory, and that it has been initialised before. - unsafe { bindings::spin_lock(ptr) } + unsafe { bindings::spin_lock(ptr) }; + None } - unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { - // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the - // caller is the owner of the mutex. - unsafe { bindings::spin_unlock(ptr) } + unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState) { + match guard_state { + // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that + // the caller is the owner of the mutex. + Some(flags) => unsafe { bindings::spin_unlock_irqrestore(ptr, *flags) }, + // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that + // the caller is the owner of the mutex. + None => unsafe { bindings::spin_unlock(ptr) }, + } + } +} + +// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. We use the `irqsave` +// variant of the C lock acquisition functions to disable interrupts and retrieve the original +// interrupt state, and the `irqrestore` variant of the lock release functions to restore the state +// in `unlock` -- we use the guard context to determine which method was used to acquire the lock. +unsafe impl super::IrqSaveBackend for SpinLockBackend { + unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState { + // SAFETY: The safety requirements of this function ensure that `ptr` points to valid + // memory, and that it has been initialised before. + Some(unsafe { bindings::spin_lock_irqsave(ptr) }) } } From patchwork Sat Apr 8 07:53:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81127 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp736955vqo; Sat, 8 Apr 2023 00:58:38 -0700 (PDT) X-Google-Smtp-Source: AKy350YjWe4MBkjtoQdybs416hJCXPTe7vPsMyLc7U2ovXtmMPpdnaozM1zsY/AFw9gufRCQIqDZ X-Received: by 2002:a17:906:824f:b0:933:3cd8:a16f with SMTP id f15-20020a170906824f00b009333cd8a16fmr1627669ejx.75.1680940718427; Sat, 08 Apr 2023 00:58:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940718; cv=none; d=google.com; s=arc-20160816; b=eeRHbQlsgbOGzlMDGloRp5zEdKYWwk1adA7dqeJ8nrL+MADDNeqBE1moIMBhPVKsmv BFOjeQktX5JhJcXgbOqbfmmExlB0mKQdJLhj2auyEqaEVqQwa+W+TB3U7/6CuePFuJsM hl7EM3FFQGoKbBDwo+9YdVysfDr+vpsoY0OZD89tubwkQIQvwpjg7+7pz+9Y3nLDUVlU C/OPWB0DYsnHhR6h5OLcBXgBvINBu6zBEaLl4Lgl98scQy5zhI+TxecowyyQFjeCC6h3 mTGOuZ1gNQvMaN186NmJdu0/yyyaftsvkCjUHfzKt+WiVxVPW70xPsoFxfAq639G5S5S YbuA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=S9xdueeJy7MgLea0ONmd9MZ1VHllI6hHaQJbmcDSqvw=; b=eFuVien+ZQC6HC/Zb4vonplB+BJBdm35MqcKauB+Zeqq7AgsrtwEofy6homHedZa/x D18gtmvE7PyRweZQIt6Qn7KbZYKD82L5zahkMualjEpfEAOEOq/d5yETcqCOiJF1s1i3 1Dn+MZunj3A5RmlXe1hH9Vs5kJNtEN+jK5oq3owq4tJpoH1VqihSHjJeTXpFtxvOFVi+ 3zkk5LxqfygtG1HVW4+xJIgVowds/amvipbnAu/pdQJ5cWxEWimJZ6KyeUgiZSzjAh+K oW+imF+tf8J7EhE7T0bIvmpj39i3omrMYbZzfBzYmjQGT/YScLwhPDERnLeWbKmpFXW5 cW3w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=gJPOyjdI; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id gv3-20020a1709072bc300b00947bae8c71bsi4712730ejc.916.2023.04.08.00.58.14; Sat, 08 Apr 2023 00:58:38 -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=@gmail.com header.s=20210112 header.b=gJPOyjdI; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230064AbjDHHy6 (ORCPT + 99 others); Sat, 8 Apr 2023 03:54:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230144AbjDHHyf (ORCPT ); Sat, 8 Apr 2023 03:54:35 -0400 Received: from mail-oi1-x236.google.com (mail-oi1-x236.google.com [IPv6:2607:f8b0:4864:20::236]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7842810271; Sat, 8 Apr 2023 00:54:17 -0700 (PDT) Received: by mail-oi1-x236.google.com with SMTP id f14so18831052oiw.10; Sat, 08 Apr 2023 00:54:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=S9xdueeJy7MgLea0ONmd9MZ1VHllI6hHaQJbmcDSqvw=; b=gJPOyjdIa5tq77ALNTMPC2MFBLNhcROzoktPdDzydEf5g6t1f171CYPi/W6bF+1MJA a7NXuCM6eOUDRd0+M6o9IbTb5d1+Ssh0ZyPyZOhZTATdSu0gI96WjxXek3wDqz426r0N BEVi2tBlRqofAlJGtL2hom7owEyLzCBRWf9nXyjfmnNZggAFYy1B5ON4uCvSkTV4QcnX WiweHjRDLZsMoexiXJ0Wu81iJvxLmeSud9t01K9xmEllmRb7Z69Rfl/cDqpmlDM6L+8W +nwO42Zzn23IcAXkzJKO87F4ge9Vi62WpmBykdaxoF3gnyFjTQ9aHrxOvPWhls9kQY+7 q6kw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=S9xdueeJy7MgLea0ONmd9MZ1VHllI6hHaQJbmcDSqvw=; b=j/fOvvVHSxF8HFbZ3Rd04MOq3ocrXJceYPLzy+gJ3k3h1MyAfRh5VWKjsY+q7i0AFk 4xJERmHnZ5Wl02gZBkTyLVq5kuXwyewDYNpQHyr3N9vPjmhkOccs4qaYzs+y+FG+LgG4 O6siY+XQJZV1YOytY9Pr8raDi5o1S+5w8Dz5oyGuq+B+jh2pB2yY0ViN9a2jmtNUOfDB +VRc7B8khbbB3qQnnnWNEUcbWdJuiLPpbVoGkCMufCT8PIT+w1cocvy0H2maj0aCR/Xj sytq7pQNJolomk5xwpkrsuz/M1395mVFpOkR2DIPovtD7tSPVcBRePZT6eptXS/f3/0U V2SQ== X-Gm-Message-State: AAQBX9dI68dO8vTUccKuxKKeYpblF/N94Necvm9AD6V1Wn0/Pzb0ePcP I5YCFJPCQ3V6VllaiS56xL+a9fJ3l8o= X-Received: by 2002:a05:6808:16a7:b0:386:9af9:96db with SMTP id bb39-20020a05680816a700b003869af996dbmr2027862oib.38.1680940457034; Sat, 08 Apr 2023 00:54:17 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:16 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v3 08/13] rust: introduce `ARef` Date: Sat, 8 Apr 2023 04:53:35 -0300 Message-Id: <20230408075340.25237-8-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594094792763463?= X-GMAIL-MSGID: =?utf-8?q?1762594094792763463?= From: Wedson Almeida Filho This is an owned reference to an object that is always ref-counted. This is meant to be used in wrappers for C types that have their own ref counting functions, for example, tasks, files, inodes, dentries, etc. Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes rust/kernel/types.rs | 107 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs index 3a46ec1a00cd..73709ce1f0a1 100644 --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -6,8 +6,10 @@ use crate::init::{self, PinInit}; use alloc::boxed::Box; use core::{ cell::UnsafeCell, + marker::PhantomData, mem::MaybeUninit, ops::{Deref, DerefMut}, + ptr::NonNull, }; /// Used to transfer ownership to and from foreign (non-Rust) languages. @@ -268,6 +270,111 @@ impl Opaque { } } +/// Types that are _always_ reference counted. +/// +/// It allows such types to define their own custom ref increment and decrement functions. +/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference +/// [`ARef`]. +/// +/// This is usually implemented by wrappers to existing structures on the C side of the code. For +/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted +/// instances of a type. +/// +/// # Safety +/// +/// Implementers must ensure that increments to the reference count keep the object alive in memory +/// at least until matching decrements are performed. +/// +/// Implementers must also ensure that all instances are reference-counted. (Otherwise they +/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object +/// alive.) +pub unsafe trait AlwaysRefCounted { + /// Increments the reference count on the object. + fn inc_ref(&self); + + /// Decrements the reference count on the object. + /// + /// Frees the object when the count reaches zero. + /// + /// # Safety + /// + /// Callers must ensure that there was a previous matching increment to the reference count, + /// and that the object is no longer used after its reference count is decremented (as it may + /// result in the object being freed), unless the caller owns another increment on the refcount + /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls + /// [`AlwaysRefCounted::dec_ref`] once). + unsafe fn dec_ref(obj: NonNull); +} + +/// An owned reference to an always-reference-counted object. +/// +/// The object's reference count is automatically decremented when an instance of [`ARef`] is +/// dropped. It is also automatically incremented when a new instance is created via +/// [`ARef::clone`]. +/// +/// # Invariants +/// +/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In +/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count. +pub struct ARef { + ptr: NonNull, + _p: PhantomData, +} + +impl ARef { + /// Creates a new instance of [`ARef`]. + /// + /// It takes over an increment of the reference count on the underlying object. + /// + /// # Safety + /// + /// Callers must ensure that the reference count was incremented at least once, and that they + /// are properly relinquishing one increment. That is, if there is only one increment, callers + /// must not use the underlying object anymore -- it is only safe to do so via the newly + /// created [`ARef`]. + pub unsafe fn from_raw(ptr: NonNull) -> Self { + // INVARIANT: The safety requirements guarantee that the new instance now owns the + // increment on the refcount. + Self { + ptr, + _p: PhantomData, + } + } +} + +impl Clone for ARef { + fn clone(&self) -> Self { + self.inc_ref(); + // SAFETY: We just incremented the refcount above. + unsafe { Self::from_raw(self.ptr) } + } +} + +impl Deref for ARef { + type Target = T; + + fn deref(&self) -> &Self::Target { + // SAFETY: The type invariants guarantee that the object is valid. + unsafe { self.ptr.as_ref() } + } +} + +impl From<&T> for ARef { + fn from(b: &T) -> Self { + b.inc_ref(); + // SAFETY: We just incremented the refcount above. + unsafe { Self::from_raw(NonNull::from(b)) } + } +} + +impl Drop for ARef { + fn drop(&mut self) { + // SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to + // decrement. + unsafe { T::dec_ref(self.ptr) }; + } +} + /// A sum type that always holds either a value of type `L` or `R`. pub enum Either { /// Constructs an instance of [`Either`] containing a value of type `L`. From patchwork Sat Apr 8 07:53:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81128 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp736957vqo; Sat, 8 Apr 2023 00:58:39 -0700 (PDT) X-Google-Smtp-Source: AKy350b3uvyBO3RQjKSdxdibBnIYHhG/CdjA0ZeXiGAR7wlEOL4lUuzPKV1lXPKAAUxBqzuckbxn X-Received: by 2002:a17:906:3e4c:b0:931:6b2b:a671 with SMTP id t12-20020a1709063e4c00b009316b2ba671mr1864097eji.65.1680940719045; Sat, 08 Apr 2023 00:58:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940719; cv=none; d=google.com; s=arc-20160816; b=civH5X2ZJ0lNNFNlNdCV3JuSbDefjvwB8XnupUO2ujUXNAaG9R8YHV7DY8HajHj6zs f1hG4SyOOEiCmEN/ldcYiCZrAYKPoEpyLyACX+qWX/yLihx7xGU2MIvQWZ5YDSigdiQC YA7yHlupJ6/NKrl1tLGHAiot4L3Arr7vHpw3OUEhqSYmkrnQbomwPO3sLk30tuDw5c1i V/frTk5jS3IlTIc/5/2TVPqsyNt5o3r7nq9rG0L697chmPoFoOcRlgD0jyy7wt+Jw69b pGWU8DUgKqEreAj84wPg90KjK/F3MFFsLpUcxE/TssDMVp1hZHGX7jP+oYiAWF1KNwkU HojA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=lpFbdZW6Pxs9oGadShmf3bb76khn+lS3nRvJuJ63DD0=; b=M4qQlwpmvznQdSA1N7Ar4ANMeiEcQBfuvCxfAP50XAqD0Kw80vIgCHMy9e2ibNg0ad MOThRaQ/NRpVu3bMbK5Uh/wELO2DfFvhPJ6KYQir1gimGjoFzHcF+ZIbTH0jPdRjPMCV i52mNdrLiEzutKb6gRY6CxPTmwb86b1/ASJp2lzV4oVEi2F8pMCDlhP7Pkjkoq/BwHTX e0LiGUZFrK2RBpWmsHz76WAA2tGXz6TZCoHNZI/QbdPWhXUCr/Or674ENP/XOMey4EiA 6rICtvwzBkjhYMGtQt1EU/B11lgBJG0YF1jRRwzGQiDJ352vEMX3cNFtwEDRv+pe/D37 1/rA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=dIU1A+nM; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t7-20020aa7d707000000b004ad7203a2c6si5288146edq.230.2023.04.08.00.58.15; Sat, 08 Apr 2023 00:58:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=dIU1A+nM; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230160AbjDHHzC (ORCPT + 99 others); Sat, 8 Apr 2023 03:55:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230056AbjDHHym (ORCPT ); Sat, 8 Apr 2023 03:54:42 -0400 Received: from mail-oo1-xc31.google.com (mail-oo1-xc31.google.com [IPv6:2607:f8b0:4864:20::c31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A2A8DFF1F; Sat, 8 Apr 2023 00:54:20 -0700 (PDT) Received: by mail-oo1-xc31.google.com with SMTP id g26-20020a4adc9a000000b0053b9059edd5so101149oou.3; Sat, 08 Apr 2023 00:54:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940460; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lpFbdZW6Pxs9oGadShmf3bb76khn+lS3nRvJuJ63DD0=; b=dIU1A+nMC99Mw/TCI+3ztwstU57Nl2JuzV3JEDMAiZU0C2mRTMt1HryblDXwlVIueV Qofw33OMnSkvEB7CS+UoM1o9a2uQN7Ajp4/8Cghfxe5/c41+dpsRgWuHJWwcbEUrmX0b FcOIEUpowOsDXTOFDiK+gbbkNhe6fUsokP9LjDi1VhXeq11SqSgcZv0LiMmGaDPIbrIq oDJMWoQof0Om8rrG/sAGQO6FvSjfZZqUFxw78zNEV1jGlpHz1oCWG+tw0r6NTkkWytTU 1J7bdoyO5xZcPY95KhWSLogDNXd2FsD7e4841nkxDx6LwYtOjpTCoKV2w8kOHIhQ80AO N1Rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940460; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lpFbdZW6Pxs9oGadShmf3bb76khn+lS3nRvJuJ63DD0=; b=RnSIAhyyl9K1xOBufXiu/c2FKP0CAU+0dLxDBTSTBRC66d71ReS3S55dl5Xx+tuNTA ihsu2iGGyIU8Ir8a0/D/O5FbHELEpCmDhnqRz6xDHvr+8Oco2q5f1e4mfTXjchMsNp+G 5DczyCmEv+aA2Fx9lXDcDoYzm5XNNVte3vKuocUWi2cmB+j6jFpc13hpLtg2PG0moXdX nnyPeRygkmzoBcv0b0z+9DCpVAxcVAQPMVTAjf/rUUfb1zNzH5K5mKb4B1rnd+gJJ6mg S+bYhIDW5qy2WYAEBTwghZPo3bVCOAjjRuT9CPI6uCPPIIg6gtoLp1Zc6mG5iZoTxXDT EoCA== X-Gm-Message-State: AAQBX9fN8FEmiR7qr6ujWjs26arCcLWl0GmptdrsJuxZAzk5ozU0GuC0 1yE3q421nsY+5KoOWO5fVtjZ4M39yrc= X-Received: by 2002:a4a:d62e:0:b0:538:57d4:2d62 with SMTP id n14-20020a4ad62e000000b0053857d42d62mr2164321oon.2.1680940460231; Sat, 08 Apr 2023 00:54:20 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:20 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Ingo Molnar , Peter Zijlstra Subject: [PATCH v3 09/13] rust: add basic `Task` Date: Sat, 8 Apr 2023 04:53:36 -0300 Message-Id: <20230408075340.25237-9-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594095180008817?= X-GMAIL-MSGID: =?utf-8?q?1762594095180008817?= From: Wedson Almeida Filho It is an abstraction for C's `struct task_struct`. It implements `AlwaysRefCounted`, so the refcount of the wrapped object is managed safely on the Rust side. Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: Wrap task_struct with `Opaque` instead of `UnsafeCell` rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 19 +++++++++ rust/kernel/lib.rs | 1 + rust/kernel/task.rs | 75 +++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 rust/kernel/task.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 75d85bd6c592..03656a44a83f 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -8,6 +8,7 @@ #include #include +#include /* `bindgen` gets confused at certain things. */ const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; diff --git a/rust/helpers.c b/rust/helpers.c index e42f5b446f92..58a194042c86 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -23,6 +23,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -75,6 +76,12 @@ void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) } EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore); +int rust_helper_signal_pending(struct task_struct *t) +{ + return signal_pending(t); +} +EXPORT_SYMBOL_GPL(rust_helper_signal_pending); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); @@ -93,6 +100,18 @@ bool rust_helper_refcount_dec_and_test(refcount_t *r) } EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test); +void rust_helper_get_task_struct(struct task_struct *t) +{ + get_task_struct(t); +} +EXPORT_SYMBOL_GPL(rust_helper_get_task_struct); + +void rust_helper_put_task_struct(struct task_struct *t) +{ + put_task_struct(t); +} +EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); + /* * 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/lib.rs b/rust/kernel/lib.rs index 2d7606135ef6..ee27e10da479 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -44,6 +44,7 @@ mod static_assert; pub mod std_vendor; pub mod str; pub mod sync; +pub mod task; pub mod types; #[doc(hidden)] diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs new file mode 100644 index 000000000000..d70cad131956 --- /dev/null +++ b/rust/kernel/task.rs @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Tasks (threads and processes). +//! +//! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h). + +use crate::{bindings, types::Opaque}; +use core::ptr; + +/// Wraps the kernel's `struct task_struct`. +/// +/// # Invariants +/// +/// All instances are valid tasks created by the C portion of the kernel. +/// +/// Instances of this type are always ref-counted, that is, a call to `get_task_struct` ensures +/// that the allocation remains valid at least until the matching call to `put_task_struct`. +#[repr(transparent)] +pub struct Task(pub(crate) Opaque); + +// SAFETY: It's OK to access `Task` through references from other threads because we're either +// accessing properties that don't change (e.g., `pid`, `group_leader`) or that are properly +// synchronised by C code (e.g., `signal_pending`). +unsafe impl Sync for Task {} + +/// The type of process identifiers (PIDs). +type Pid = bindings::pid_t; + +impl Task { + /// Returns the group leader of the given task. + pub fn group_leader(&self) -> &Task { + // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always + // have a valid group_leader. + let ptr = unsafe { *ptr::addr_of!((*self.0.get()).group_leader) }; + + // SAFETY: The lifetime of the returned task reference is tied to the lifetime of `self`, + // and given that a task has a reference to its group leader, we know it must be valid for + // the lifetime of the returned task reference. + unsafe { &*ptr.cast() } + } + + /// Returns the PID of the given task. + pub fn pid(&self) -> Pid { + // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always + // have a valid pid. + unsafe { *ptr::addr_of!((*self.0.get()).pid) } + } + + /// Determines whether the given task has pending signals. + pub fn signal_pending(&self) -> bool { + // SAFETY: By the type invariant, we know that `self.0` is valid. + unsafe { bindings::signal_pending(self.0.get()) != 0 } + } + + /// Wakes up the task. + pub fn wake_up(&self) { + // SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid. + // And `wake_up_process` is safe to be called for any valid task, even if the task is + // running. + unsafe { bindings::wake_up_process(self.0.get()) }; + } +} + +// SAFETY: The type invariants guarantee that `Task` is always ref-counted. +unsafe impl crate::types::AlwaysRefCounted for Task { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference means that the refcount is nonzero. + unsafe { bindings::get_task_struct(self.0.get()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is nonzero. + unsafe { bindings::put_task_struct(obj.cast().as_ptr()) } + } +} From patchwork Sat Apr 8 07:53:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81136 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp743888vqo; Sat, 8 Apr 2023 01:15:10 -0700 (PDT) X-Google-Smtp-Source: AKy350YYVjUMnresUn5cfsFdVbr1r5SeRtfUCy+LPfA03YrNgZ4lffsm7yR0jNslgZ2yepmfRnQn X-Received: by 2002:a17:906:916:b0:946:c022:8979 with SMTP id i22-20020a170906091600b00946c0228979mr912449ejd.21.1680941710133; Sat, 08 Apr 2023 01:15:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680941710; cv=none; d=google.com; s=arc-20160816; b=TJU7hId+6Tc6ckW6opQi3EQTtce1lcgWksgorBvCHKrmg0sqmkcbtwxHKavlz2aFpN zGUJ4mSkAIGSRfolYfEX7oGdb8S52UmGGSVIW6wZeNDnEyX4amB3QvKUonavVoIFCoi5 iji1ued4cxwFECtfJXT9dbY5kT7B22zkncuKwVKj5N1jF2t8AmjxzATPicVztiqDuVs3 N37LH86zwvg6b/W7fVnAOGEKQVVEt5hxUo5rmZTVKr/BIjAphKeitewX2t58U4Z2BjlF Dhlv5cSONlZwh7F66Q1bMGe1OSAs2hCk1d9HCdemLckbKd8NffE0SoqdCsXSQGM3jGUk 2DCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=KRp/Oi/twJtl9aBTzuC+WObtxL9OqDuPbUJ1RtXTIfI=; b=JqRNjT7WUc67c156zz0sklVsnBwMP13iYEYwd4TKzWVkjPIbnnfDigAJDYUvXX+BdF q1BBMyQV2J/op6BcC6xW4MAFMDvvEBBFDTVUVFJ7laBsnMyjJcxocuA97R1C9pxjoNcC EHBhttOoV7jIt1dM/EwNInW7SwiMPdW9S/4wgD+aCgrBRLuRCpexRgKvwQDfd6TH2Dvy T6xIhLAM7AwiWB75Gk0zP3RYz+0A0oXEM/Vzmsv495Axc9gNPkUsRBP2QqeDgm8mO8dp S5iw7PNuLyCezebZYHegnIdIndsjo0QIIA5DSKHqAD6iwzlgADopm0MIGF5gS0jmvl4g uIGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=R0+rGcdc; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id kg13-20020a17090776ed00b009311eb6863dsi4616704ejc.634.2023.04.08.01.14.45; Sat, 08 Apr 2023 01:15:10 -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=@gmail.com header.s=20210112 header.b=R0+rGcdc; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230089AbjDHHzU (ORCPT + 99 others); Sat, 8 Apr 2023 03:55:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32776 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230131AbjDHHzA (ORCPT ); Sat, 8 Apr 2023 03:55:00 -0400 Received: from mail-oi1-x22d.google.com (mail-oi1-x22d.google.com [IPv6:2607:f8b0:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D916BFF0E; Sat, 8 Apr 2023 00:54:37 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id w13so21006233oik.2; Sat, 08 Apr 2023 00:54:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940463; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KRp/Oi/twJtl9aBTzuC+WObtxL9OqDuPbUJ1RtXTIfI=; b=R0+rGcdc6V1X+oez522zCJPvrVawIDxgxs86xe/wj1vfkFDC7N1DW0NXAtwgMp3+Vf RVoANubvriftXet27shk9KqP91cndUhCZpnsjDM/c33w5pemyGG8Tbwf+amF7KOlG7r0 AefeM63JNjreEDh/teGas2knHKSup6KUnX9XkRxwJTKMjvIuZkq0cp9XqvuwwpT6j6bd A1kKj7KumT8XVxZ9IyqX328eKB1PGCL9ct9317CwvwXveaCXgSP50MHirVijn4j0zDQB l4qFUmPcmViLJHRoLpZBfiIT8LXHRAk2KUzqNcgDtHIE72esLNq3zPxKfUd9h77cyFJX NPTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940463; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KRp/Oi/twJtl9aBTzuC+WObtxL9OqDuPbUJ1RtXTIfI=; b=wLG3wiogwoMTq9syr66w+S/yC+3lL7epmS9oNT3md2viZmv9/Ric4Zmwsqz6mLrORO HFN9cz2nftrfWdvBUysG0dZBr/hcxBAwpgoSm0nvMB7axR+UxcH5DtAOYn9V8B12eGXz AhMUQ2JVzqlZ6s1L3ynCIokBKG3JXr1l6goUHSbTURV5IdW/XK4OGL/PqxeMEAzO7Wmi JZEXGFEzNr6HFcb10zs9vRXKqK5HFNZcdN3ciFJ+6GtebCDA0TBPLrx/kAYrDCCKRr/J jwEq4nvycI32p91AMves0JUuwaIW6Z51ab+NRJFDkcehsCiExIQ1kRAkHT6DcB9+WWgi rEgQ== X-Gm-Message-State: AAQBX9fzhgaMQRv5KFmkU4WDBtqqSsayu9UJcK8+eGNhs2fZ5mdgjNX9 BwrYcG8eEvA/Tj9Q9mWzongyxIeThsw= X-Received: by 2002:a54:4402:0:b0:387:87cd:11c6 with SMTP id k2-20020a544402000000b0038787cd11c6mr526748oiw.59.1680940463390; Sat, 08 Apr 2023 00:54:23 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:23 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Ingo Molnar , Peter Zijlstra Subject: [PATCH v3 10/13] rust: introduce `current` Date: Sat, 8 Apr 2023 04:53:37 -0300 Message-Id: <20230408075340.25237-10-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762595134602479394?= X-GMAIL-MSGID: =?utf-8?q?1762595134602479394?= From: Wedson Almeida Filho This allows Rust code to get a reference to the current task without having to increment the refcount, but still guaranteeing memory safety. Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: Make `current` a macro to prevent it from escaping the caller v2 -> v3: - Mention `current` macro in `Task::current` - Hide implementation of `TaskRef` inside `Task::current` rust/helpers.c | 6 +++ rust/kernel/prelude.rs | 2 + rust/kernel/task.rs | 88 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index 58a194042c86..96441744030e 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -100,6 +100,12 @@ bool rust_helper_refcount_dec_and_test(refcount_t *r) } EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test); +struct task_struct *rust_helper_get_current(void) +{ + return current; +} +EXPORT_SYMBOL_GPL(rust_helper_get_current); + void rust_helper_get_task_struct(struct task_struct *t) { get_task_struct(t); diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index fcdc511d2ce8..c28587d68ebc 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -36,3 +36,5 @@ pub use super::error::{code::*, Error, Result}; pub use super::{str::CStr, ThisModule}; pub use super::init::{InPlaceInit, Init, PinInit}; + +pub use super::current; diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index d70cad131956..5269a562cb1b 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -5,7 +5,17 @@ //! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h). use crate::{bindings, types::Opaque}; -use core::ptr; +use core::{marker::PhantomData, ops::Deref, ptr}; + +/// Returns the currently running task. +#[macro_export] +macro_rules! current { + () => { + // SAFETY: Deref + addr-of below create a temporary `TaskRef` that cannot outlive the + // caller. + unsafe { &*$crate::task::Task::current() } + }; +} /// Wraps the kernel's `struct task_struct`. /// @@ -15,6 +25,42 @@ use core::ptr; /// /// Instances of this type are always ref-counted, that is, a call to `get_task_struct` ensures /// that the allocation remains valid at least until the matching call to `put_task_struct`. +/// +/// # Examples +/// +/// The following is an example of getting the PID of the current thread with zero additional cost +/// when compared to the C version: +/// +/// ``` +/// let pid = current!().pid(); +/// ``` +/// +/// Getting the PID of the current process, also zero additional cost: +/// +/// ``` +/// let pid = current!().group_leader().pid(); +/// ``` +/// +/// Getting the current task and storing it in some struct. The reference count is automatically +/// incremented when creating `State` and decremented when it is dropped: +/// +/// ``` +/// use kernel::{task::Task, types::ARef}; +/// +/// struct State { +/// creator: ARef, +/// index: u32, +/// } +/// +/// impl State { +/// fn new() -> Self { +/// Self { +/// creator: current!().into(), +/// index: 0, +/// } +/// } +/// } +/// ``` #[repr(transparent)] pub struct Task(pub(crate) Opaque); @@ -27,6 +73,46 @@ unsafe impl Sync for Task {} type Pid = bindings::pid_t; impl Task { + /// Returns a task reference for the currently executing task/thread. + /// + /// The recommended way to get the current task/thread is to use the + /// [`current`](crate::current) macro because it is safe. + /// + /// # Safety + /// + /// Callers must ensure that the returned object doesn't outlive the current task/thread. + pub unsafe fn current() -> impl Deref { + pub struct TaskRef<'a> { + task: &'a Task, + _not_send: PhantomData<*mut ()>, + } + + impl Deref for TaskRef<'_> { + type Target = Task; + + fn deref(&self) -> &Self::Target { + self.task + } + } + + impl From> for crate::types::ARef { + fn from(t: TaskRef<'_>) -> Self { + t.deref().into() + } + } + + // SAFETY: Just an FFI call with no additional safety requirements. + let ptr = unsafe { bindings::get_current() }; + + TaskRef { + // SAFETY: If the current thread is still running, the current task is valid. Given + // that `TaskRef` is not `Send`, we know it cannot be transferred to another thread + // (where it could potentially outlive the caller). + task: unsafe { &*ptr.cast() }, + _not_send: PhantomData, + } + } + /// Returns the group leader of the given task. pub fn group_leader(&self) -> &Task { // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always From patchwork Sat Apr 8 07:53:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81133 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp741135vqo; Sat, 8 Apr 2023 01:07:53 -0700 (PDT) X-Google-Smtp-Source: AKy350aCus8PYQaPjtM1x8sD+2/WDLRJ9qu1CJ++Qo4PEAMZtRQgJHH9vj+8lK7NwIJMxp5D67Ik X-Received: by 2002:a17:907:272b:b0:88d:ba89:1837 with SMTP id d11-20020a170907272b00b0088dba891837mr1529543ejl.8.1680941273261; Sat, 08 Apr 2023 01:07:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680941273; cv=none; d=google.com; s=arc-20160816; b=x8DCRfnUnLH1hDZrsPvoAxSeYENnqS2pZ2eZffp2crfYqk1zU1gXLPHPhnb2/G+qGQ PTqTS2w6Gp7pzlQyvK4LtJjhyX5UoksRhsD7CBqVYm2gRiScdIk/UdL/afqx+qI3o9gQ yBtGVCxg42mbfiHNdgyW1dRR+bogDtYaWDSPMXE79eiJDQ2dqLn0+/9sqpe2X83Bxo3g BT+Z2UgOGOMNcu/GOQxVx5cm9cgm3XDDsiSpQopcYYkM7ud7fPsD3trPg2dGIB1Raxhl b7VlWem6Eb/DBEmBpiT1aW2dNewQbMgaif0+G0RPtdJMUyS4ZzZXQCpfc8y0gLMSrKTL VeKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ar/TRSfKXBqi4OsSPUjagB6ioA9d9TG19jv5XSvWgTg=; b=Rhq25rAqKtYrRUzu6HF10jgajHdW5oWsI41xvnXChCjkhLaKeR5gzizMlu8EWf1G07 QmoUYMkGNNu2eBWTPDe8zrahP+rouU0qfmAcHeRHGff83fR5BD/ZHiBr6k2tOPBl2Q9u 2otx1vGMXCqHbh+aMa7UC6NSQapYKuTzHNJmj/2PGmxwa6aDdK+4SAdbNsTbOLeV6u1R MHhE/Sc2fJ5suFIvLAKRwHTS4vgUhhC9KVdrBaH1wzqXa+rqSLEOBfAtwZC5einwiAKI RQLWyEkT/S52OLEPrSX1Pfn92E6c8VaMYEduP5ftrV7x+lg9JTREi62++48G2/ESCkU6 ikkw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=fwg17W4i; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id kd8-20020a17090798c800b009325610fddcsi4058808ejc.501.2023.04.08.01.07.29; Sat, 08 Apr 2023 01:07:53 -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=@gmail.com header.s=20210112 header.b=fwg17W4i; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230286AbjDHHzW (ORCPT + 99 others); Sat, 8 Apr 2023 03:55:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59004 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230150AbjDHHzB (ORCPT ); Sat, 8 Apr 2023 03:55:01 -0400 Received: from mail-oo1-xc2a.google.com (mail-oo1-xc2a.google.com [IPv6:2607:f8b0:4864:20::c2a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72C7BFF1E; Sat, 8 Apr 2023 00:54:39 -0700 (PDT) Received: by mail-oo1-xc2a.google.com with SMTP id f7-20020a4ab647000000b0054101f316c7so3442244ooo.13; Sat, 08 Apr 2023 00:54:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940466; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ar/TRSfKXBqi4OsSPUjagB6ioA9d9TG19jv5XSvWgTg=; b=fwg17W4i6+q6/L6fMc/sTiXgeft5wvoFHVT8R28tG7H7n957FzEW4I4K6Jf8JLG7d5 NaKIDVFrK1DybXwtg2k0XT1ZG1L6hMlfgoJrfYP0wFVztQIndmUMH/616UdvvhSVUpnn /6GTdcfLM9f/bNz9Jt15lXVKdkEpvh5I/daYgn3CNAnduzvSNcxbzYTaOEY5VR72uxKt sXhjgK9Q/7ZQxNAPWq5a7ay0DmYzM39CfDYqNUTtkLMDRDQzCKeKjfewce6LTq07ZgfP SXlflhJIHbkKU1DTUcuNlkA0sM1kjIfVVwvMYH4eSd+Llq1UQ90AkxqkQRbWR8KhQmOY 8a8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940466; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ar/TRSfKXBqi4OsSPUjagB6ioA9d9TG19jv5XSvWgTg=; b=N7F+rbe1L87cwB3SV6pM+IxAXnEDIYy4tEa7VV9nNmVCHh0ZXNxhV3oB5aaPrBt7VR IdQHeYot5NnLlqGLYG/PgOyEfduNeoaY0VMmY8DnNq/8cI5ia+gV6k1snmjzdNQZTzPM eA/hf67NcbgfNKDD12bFNbdhG00DRfOEUA0jvhgBTozmcZOGgBFHb0oCPQcdEL/CubZJ 9C+gxx5WklRs5fkmrtO+5BSRdDbI0gT7W7h6rfXUl6JrW1bCtODcfSQ8CtCIZyODlL4a wWa5/sYAE1dZ8oKXuKGtsgbGmw9jwJl66qGRU/Qt9lm3PNiezJxhJ3uZVkFJKw/0jvu6 h4fQ== X-Gm-Message-State: AAQBX9cOLdp6XtxEclq+pmfYk1zViD5cY5trXwyogW0idgGn/VAXr0XX X1z3StP4FeP7G4kyMgZQkYCD3hGqRVY= X-Received: by 2002:a4a:4f0d:0:b0:53b:6112:3b16 with SMTP id c13-20020a4a4f0d000000b0053b61123b16mr2148567oob.9.1680940466100; Sat, 08 Apr 2023 00:54:26 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:25 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v3 11/13] rust: lock: add `Guard::do_unlocked` Date: Sat, 8 Apr 2023 04:53:38 -0300 Message-Id: <20230408075340.25237-11-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594676586648344?= X-GMAIL-MSGID: =?utf-8?q?1762594676586648344?= From: Wedson Almeida Filho It releases the lock, executes some function provided by the caller, then reacquires the lock. This is preparation for the implementation of condvars, which will sleep after between unlocking and relocking. We need an explicit `relock` method for primitives like `SpinLock` that have an irqsave variant: we use the guard state to determine if the lock was originally acquired with the regular `lock` function or `lock_irqsave`. Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: No changes v2 -> v3: No changes rust/kernel/sync/lock.rs | 25 +++++++++++++++++++++++++ rust/kernel/sync/lock/spinlock.rs | 17 +++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index 690429561f0e..a2c654ec5bd3 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -22,6 +22,9 @@ pub mod spinlock; /// /// - Implementers must ensure that only one thread/CPU may access the protected data once the lock /// is owned, that is, between calls to `lock` and `unlock`. +/// - Implementers must also ensure that `relock` uses the same locking method as the original +/// lock operation. For example, it should disable interrupts if [`IrqSaveBackend::lock_irqsave`] +/// is used. pub unsafe trait Backend { /// The state required by the lock. type State; @@ -55,6 +58,17 @@ pub unsafe trait Backend { /// /// It must only be called by the current owner of the lock. unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState); + + /// Reacquires the lock, making the caller its owner. + /// + /// # Safety + /// + /// Callers must ensure that `state` comes from a previous call to [`Backend::lock`] (or + /// variant) that has been unlocked with [`Backend::unlock`] and will be relocked now. + unsafe fn relock(ptr: *mut Self::State, guard_state: &mut Self::GuardState) { + // SAFETY: The safety requirements ensure that the lock is initialised. + *guard_state = unsafe { Self::lock(ptr) }; + } } /// The "backend" of a lock that supports the irq-save variant. @@ -164,6 +178,17 @@ pub struct Guard<'a, T: ?Sized, B: Backend> { // SAFETY: `Guard` is sync when the data protected by the lock is also sync. unsafe impl Sync for Guard<'_, T, B> {} +impl Guard<'_, T, B> { + #[allow(dead_code)] + pub(crate) fn do_unlocked(&mut self, cb: impl FnOnce()) { + // SAFETY: The caller owns the lock, so it is safe to unlock it. + unsafe { B::unlock(self.lock.state.get(), &self.state) }; + cb(); + // SAFETY: The lock was just unlocked above and is being relocked now. + unsafe { B::relock(self.lock.state.get(), &mut self.state) }; + } +} + impl core::ops::Deref for Guard<'_, T, B> { type Target = T; diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs index 34dec09a97c0..e2a2f68e6d93 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -4,6 +4,7 @@ //! //! This module allows Rust code to use the kernel's `spinlock_t`. +use super::IrqSaveBackend; use crate::bindings; /// Creates a [`SpinLock`] initialiser with the given name and a newly-created lock class. @@ -95,7 +96,8 @@ pub type SpinLock = super::Lock; /// A kernel `spinlock_t` lock backend. pub struct SpinLockBackend; -// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. +// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. `relock` uses the +// same scheme as `unlock` to figure out which locking method was used originally. unsafe impl super::Backend for SpinLockBackend { type State = bindings::spinlock_t; type GuardState = Option; @@ -127,13 +129,24 @@ unsafe impl super::Backend for SpinLockBackend { None => unsafe { bindings::spin_unlock(ptr) }, } } + + unsafe fn relock(ptr: *mut Self::State, guard_state: &mut Self::GuardState) { + let _ = match guard_state { + // SAFETY: The safety requiments of this function ensure that `ptr` has been + // initialised. + None => unsafe { Self::lock(ptr) }, + // SAFETY: The safety requiments of this function ensure that `ptr` has been + // initialised. + Some(_) => unsafe { Self::lock_irqsave(ptr) }, + }; + } } // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. We use the `irqsave` // variant of the C lock acquisition functions to disable interrupts and retrieve the original // interrupt state, and the `irqrestore` variant of the lock release functions to restore the state // in `unlock` -- we use the guard context to determine which method was used to acquire the lock. -unsafe impl super::IrqSaveBackend for SpinLockBackend { +unsafe impl IrqSaveBackend for SpinLockBackend { unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState { // SAFETY: The safety requirements of this function ensure that `ptr` points to valid // memory, and that it has been initialised before. From patchwork Sat Apr 8 07:53:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81130 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp738297vqo; Sat, 8 Apr 2023 01:01:44 -0700 (PDT) X-Google-Smtp-Source: AKy350b+vn3+B5rRuIasnEtN40N0e6IRJXVH9oRPNRpf+d9LRvDfar37zVcyEM89ptj6xnaJMsGg X-Received: by 2002:a17:906:a891:b0:92f:e40d:1489 with SMTP id ha17-20020a170906a89100b0092fe40d1489mr1823298ejb.61.1680940904073; Sat, 08 Apr 2023 01:01:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940904; cv=none; d=google.com; s=arc-20160816; b=EJmrQwA6xQGJUpdqvu/ImLndP1ttj99axbdsa1UYS3S75sJOpi8hfqjR38zcQvTf2m NqVGp0kEOMlJajty/pOpHtDnLSrNSWgdCpOA1pNPV7IL2lCfURpa2e+g/ucJBBWojKQ/ tq7ZCH4Dy85e14qyziEaAj3p2GMiaPaGiYhKw8SKjLJmYoYlK2XBd1skmn0rNA+odCQU xgT1Dt4VS+LEbAT4zAINgS6LqtqI40XYkkNzumrFRqsbNyGjvy5oQTK8fpfem/th88Pi xiNgCJbl3DJAIyPofGMub4b7ngffO0UMgdWCRV0ow6WcVZ0bFJ2X3cIUEQt+Q1yu4/Bp ptfg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=SnSCuSd2GDwIObMZY9AnCzoNvpOGG9vzBuYvI79rp0M=; b=NBWv/rlU8jbK32J+GvzvLF/uhvwCNIaiyXICQ2chCjGK9PDJTKEzhIIUyVVBKBNMjc 5EfkxmFWDZorya9ru1wi5fkbtuBssL1GpAMXjlFWOqecD1Mi2j5/ZAd9an2FDIuoNZWi ix2iW80AgRkQNFwYZkLRnA1o74ULkCmBTnqu6OvRn2aQYW7EPAlFQbA8YhKv+SuLJ2AV GsvK7+f0Q/ov/32T9bVh+SmkhH8omtGracVgODtqWhuxQwu1/xTPUi/RPoht7TnmpO4X qMHeB/2xnELucUo3PudISVvtRLrdqC14590+GzKWprC+FpnieJlTLZOlJfF/fxKVb4hd shSg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="MK/2j344"; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t24-20020a170906949800b009212a3f8496si4269533ejx.666.2023.04.08.01.01.19; Sat, 08 Apr 2023 01:01: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=@gmail.com header.s=20210112 header.b="MK/2j344"; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229871AbjDHHz1 (ORCPT + 99 others); Sat, 8 Apr 2023 03:55:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60720 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230211AbjDHHzE (ORCPT ); Sat, 8 Apr 2023 03:55:04 -0400 Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com [IPv6:2607:f8b0:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19D05FF07; Sat, 8 Apr 2023 00:54:40 -0700 (PDT) Received: by mail-oi1-x22f.google.com with SMTP id w19so402335oiv.13; Sat, 08 Apr 2023 00:54:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940469; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SnSCuSd2GDwIObMZY9AnCzoNvpOGG9vzBuYvI79rp0M=; b=MK/2j344qMj13ANxSzPNK12+eQ/5CsqbseP3MDQEaGz8chUqKeXXY4OhkMnz62bNZJ at6Tk8ff3ubUC2SddJlys22XFzceNFnjx2fOpZ22hwvM7MvktVCMOuyCZClgWKUnDlPL K/VVBZmdj8BiB3ty6VwGqx9QlVc71YWPavRd0JR7jHfpobdaSeaaa00rZ/C0LDzlsoUX wkPP/wmcBCYJu9hd7Jxo7RY1bDkU0p9rCdKqoRxyOmC3nvqP6rRT7w2irpWwuTyPJDye Gm4511sd3JIfb//tbYlSHYLFaguCDpq0vYuOufPo5UtwXgA0F13Zl6EYJyjzlsqvIP0b M9Xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940469; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SnSCuSd2GDwIObMZY9AnCzoNvpOGG9vzBuYvI79rp0M=; b=wfW0nRXfPt5yppbTN+wKEPe2N2GSL9fjTndsDJ2TLU4IGzSx8aCXS7NgE+kbQRS23o TG3YbcqKXrYv1T4TYtFSZFLeMKTtjTnC603D7y3DjwLLYYUmyGRfsgrvQyUYE+/J6fOr fXc5aNP5QhhJfIpLHQEp+1YtYjMnxlXvS78LjIPrlZ7/wSVlXmlkGoLvirrzD5/yPmj7 t5xJK8BRh/GJKWioDg0nNkSy+RKiytyyj9uy5ijhgZWnxHadI0MlO83ztwzShkZZVo2J I0nNVbQYAfif0H0snDxk+8sam3jyuLu67jRGbTDvxz6mRqhVCQE1rpR6+zihSb/+CmEa aTzA== X-Gm-Message-State: AAQBX9dkVpxTr/5pRrsTONwebOOoBiD8suvMHyV2oP2CbDRmcyKbcvcL FOr9HpYM6FARfvXyRGK1XMSug0LrGfM= X-Received: by 2002:aca:2110:0:b0:386:94a8:f9af with SMTP id 16-20020aca2110000000b0038694a8f9afmr1823701oiz.52.1680940469675; Sat, 08 Apr 2023 00:54:29 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:29 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v3 12/13] rust: sync: introduce `CondVar` Date: Sat, 8 Apr 2023 04:53:39 -0300 Message-Id: <20230408075340.25237-12-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594289383315351?= X-GMAIL-MSGID: =?utf-8?q?1762594289383315351?= From: Wedson Almeida Filho This is the traditional condition variable or monitor synchronisation primitive. It is implemented with C's `wait_queue_head_t`. It allows users to release a lock and go to sleep while guaranteeing that notifications won't be missed. This is achieved by enqueuing a wait entry before releasing the lock. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: Use the new `current` macro v2 -> v3: Use new Opaque::ffi_init from Benno's series rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 7 ++ rust/kernel/sync.rs | 2 + rust/kernel/sync/condvar.rs | 174 ++++++++++++++++++++++++++++++++ rust/kernel/sync/lock.rs | 1 - 5 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/condvar.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 03656a44a83f..50e7a76d5455 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -8,6 +8,7 @@ #include #include +#include #include /* `bindgen` gets confused at certain things. */ diff --git a/rust/helpers.c b/rust/helpers.c index 96441744030e..8ff2559c1572 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -24,6 +24,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -76,6 +77,12 @@ void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) } EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore); +void rust_helper_init_wait(struct wait_queue_entry *wq_entry) +{ + init_wait(wq_entry); +} +EXPORT_SYMBOL_GPL(rust_helper_init_wait); + int rust_helper_signal_pending(struct task_struct *t) { return signal_pending(t); diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index c997ff7e951e..431402180aa8 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -8,9 +8,11 @@ use crate::types::Opaque; mod arc; +mod condvar; pub mod lock; pub use arc::{Arc, ArcBorrow, UniqueArc}; +pub use condvar::CondVar; pub use lock::{mutex::Mutex, spinlock::SpinLock}; /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs new file mode 100644 index 000000000000..ef882e2af746 --- /dev/null +++ b/rust/kernel/sync/condvar.rs @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A condition variable. +//! +//! This module allows Rust code to use the kernel's [`struct wait_queue_head`] as a condition +//! variable. + +use super::{lock::Backend, lock::Guard, LockClassKey}; +use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque}; +use core::marker::PhantomPinned; +use macros::pin_data; + +/// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class. +#[macro_export] +macro_rules! new_condvar { + ($($name:literal)?) => { + $crate::sync::CondVar::new($crate::optional_name!($($name)?), $crate::static_lock_class!()) + }; +} + +/// A conditional variable. +/// +/// Exposes the kernel's [`struct wait_queue_head`] as a condition variable. It allows the caller to +/// atomically release the given lock and go to sleep. It reacquires the lock when it wakes up. And +/// it wakes up when notified by another thread (via [`CondVar::notify_one`] or +/// [`CondVar::notify_all`]) or because the thread received a signal. It may also wake up +/// spuriously. +/// +/// Instances of [`CondVar`] need a lock class and to be pinned. The recommended way to create such +/// instances is with the [`pin_init`](crate::pin_init) and [`new_condvar`] macros. +/// +/// # Examples +/// +/// The following is an example of using a condvar with a mutex: +/// +/// ``` +/// use kernel::sync::{CondVar, Mutex}; +/// use kernel::{new_condvar, new_mutex}; +/// +/// #[pin_data] +/// pub struct Example { +/// #[pin] +/// value: Mutex, +/// +/// #[pin] +/// value_changed: CondVar, +/// } +/// +/// /// Waits for `e.value` to become `v`. +/// fn wait_for_vaue(e: &Example, v: u32) { +/// let mut guard = e.value.lock(); +/// while *guard != v { +/// e.value_changed.wait_uninterruptible(&mut guard); +/// } +/// } +/// +/// /// Increments `e.value` and notifies all potential waiters. +/// fn increment(e: &Example) { +/// *e.value.lock() += 1; +/// e.value_changed.notify_all(); +/// } +/// +/// /// Allocates a new boxed `Example`. +/// fn new_example() -> Result>> { +/// Box::pin_init(pin_init!(Example { +/// value <- new_mutex!(0), +/// value_changed <- new_condvar!(), +/// })) +/// } +/// ``` +/// +/// [`struct wait_queue_head`]: ../../../include/linux/wait.h +#[pin_data] +pub struct CondVar { + #[pin] + pub(crate) wait_list: Opaque, + + /// A condvar needs to be pinned because it contains a [`struct list_head`] that is + /// self-referential, so it cannot be safely moved once it is initialised. + #[pin] + _pin: PhantomPinned, +} + +// SAFETY: `CondVar` only uses a `struct wait_queue_head`, which is safe to use on any thread. +#[allow(clippy::non_send_fields_in_send_ty)] +unsafe impl Send for CondVar {} + +// SAFETY: `CondVar` only uses a `struct wait_queue_head`, which is safe to use on multiple threads +// concurrently. +unsafe impl Sync for CondVar {} + +impl CondVar { + /// Constructs a new condvar initialiser. + #[allow(clippy::new_ret_no_self)] + pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pin_init!(Self { + _pin: PhantomPinned, + // SAFETY: `slot` is valid while the closure is called and both `name` and `key` have + // static lifetimes so they live indefinitely. + wait_list <- Opaque::ffi_init(|slot| unsafe { + bindings::__init_waitqueue_head(slot, name.as_char_ptr(), key.as_ptr()) + }), + }) + } + + fn wait_internal(&self, wait_state: u32, guard: &mut Guard<'_, T, B>) { + let wait = Opaque::::uninit(); + + // SAFETY: `wait` points to valid memory. + unsafe { bindings::init_wait(wait.get()) }; + + // SAFETY: Both `wait` and `wait_list` point to valid memory. + unsafe { + bindings::prepare_to_wait_exclusive(self.wait_list.get(), wait.get(), wait_state as _) + }; + + // SAFETY: No arguments, switches to another thread. + guard.do_unlocked(|| unsafe { bindings::schedule() }); + + // SAFETY: Both `wait` and `wait_list` point to valid memory. + unsafe { bindings::finish_wait(self.wait_list.get(), wait.get()) }; + } + + /// Releases the lock and waits for a notification in interruptible mode. + /// + /// Atomically releases the given lock (whose ownership is proven by the guard) and puts the + /// thread to sleep, reacquiring the lock on wake up. It wakes up when notified by + /// [`CondVar::notify_one`] or [`CondVar::notify_all`], or when the thread receives a signal. + /// It may also wake up spuriously. + /// + /// Returns whether there is a signal pending. + #[must_use = "wait returns if a signal is pending, so the caller must check the return value"] + pub fn wait(&self, guard: &mut Guard<'_, T, B>) -> bool { + self.wait_internal(bindings::TASK_INTERRUPTIBLE, guard); + crate::current!().signal_pending() + } + + /// Releases the lock and waits for a notification in uninterruptible mode. + /// + /// Similar to [`CondVar::wait`], except that the wait is not interruptible. That is, the + /// thread won't wake up due to signals. It may, however, wake up supirously. + pub fn wait_uninterruptible(&self, guard: &mut Guard<'_, T, B>) { + self.wait_internal(bindings::TASK_UNINTERRUPTIBLE, guard) + } + + /// Calls the kernel function to notify the appropriate number of threads with the given flags. + fn notify(&self, count: i32, flags: u32) { + // SAFETY: `wait_list` points to valid memory. + unsafe { + bindings::__wake_up( + self.wait_list.get(), + bindings::TASK_NORMAL, + count, + flags as _, + ) + }; + } + + /// Wakes a single waiter up, if any. + /// + /// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost + /// completely (as opposed to automatically waking up the next waiter). + pub fn notify_one(&self) { + self.notify(1, 0); + } + + /// Wakes all waiters up, if any. + /// + /// This is not 'sticky' in the sense that if no thread is waiting, the notification is lost + /// completely (as opposed to automatically waking up the next waiter). + pub fn notify_all(&self) { + self.notify(0, 0); + } +} diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index a2c654ec5bd3..c365bc909dff 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -179,7 +179,6 @@ pub struct Guard<'a, T: ?Sized, B: Backend> { unsafe impl Sync for Guard<'_, T, B> {} impl Guard<'_, T, B> { - #[allow(dead_code)] pub(crate) fn do_unlocked(&mut self, cb: impl FnOnce()) { // SAFETY: The caller owns the lock, so it is safe to unlock it. unsafe { B::unlock(self.lock.state.get(), &self.state) }; From patchwork Sat Apr 8 07:53:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 81129 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp736963vqo; Sat, 8 Apr 2023 00:58:40 -0700 (PDT) X-Google-Smtp-Source: AKy350YKC6F0/JtyES+dAYvWzsjTZCPtp4V+yJvx3uemhZOSws64u2bC2ui9IdYPz/XseygRrVrc X-Received: by 2002:aa7:d846:0:b0:4fa:c7c9:62ea with SMTP id f6-20020aa7d846000000b004fac7c962eamr4712722eds.11.1680940720523; Sat, 08 Apr 2023 00:58:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680940720; cv=none; d=google.com; s=arc-20160816; b=UInysH9T5jI+mgZrJ5mx7y/7WFaidlyz09KBVc8hcU0WALtNPma7nWdMiu34qO2fkE kt4fhX3Fuyo6KjSFNV73ggM/ROOD6ZY9HlQkl9omr1ml+6nETZBqy8kS08qgoLU4UQoB w8kbrMQC7L1abCKp5aBSCvsTMaAnNSwlwi+na6KA76oMRvJBT0FshVEyk8KXfQD4qBbJ cnNIUln1xlszNBcMcGNAsfm68xMnZjK8MlLPTBb075a0asnfpFW3UdNRq5A0cJB6zi1J eGTDmicwN6JBWykcRo5fC/q9tQYm5aTo00MN4vQFjxG9bMhc52q52NgPYod3SsW7C75R 5VOQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=w7f1ZJtQ7GVMBkDWdLfo+KU/tSEuvyaRTAOcNqcasmo=; b=Jt+RkhHF/3TIWsRyjRYDeI1SRrgoy1s+mRHgTvI8MOFYgI4Yo/9PcAyYWllL3nJYu+ 7KLdFPdh+Qk7CmqdG2PIi74nB94DQp7YPce2McwF3WspApyUtTrltu90kiaf/UO0hKHo LCQVcNEMLhPOMOuYGkO421yJigu1PIQKXQYIzLXFVuVoKw/JGSAlBSqHLYg/lGXdKzxk qQOPu4TfMX9tYcBUA8BxMWgL0DQ+FxApZzKPiLm1K0XxmIspnhCaKWR2SwXbht5ktrn4 f1CJ6vBeTKazj7OrplJLJ7ayOvBCz/K0F98fv5wKZ9CtuXTSMhA6gnjGgE9DgvihaUsF JcHw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=AHns2xsd; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s6-20020a056402164600b004af60cc2a8csi3836460edx.486.2023.04.08.00.58.16; Sat, 08 Apr 2023 00:58:40 -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=@gmail.com header.s=20210112 header.b=AHns2xsd; 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=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230324AbjDHHzY (ORCPT + 99 others); Sat, 8 Apr 2023 03:55:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229924AbjDHHzE (ORCPT ); Sat, 8 Apr 2023 03:55:04 -0400 Received: from mail-oo1-xc2c.google.com (mail-oo1-xc2c.google.com [IPv6:2607:f8b0:4864:20::c2c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76321FF19; Sat, 8 Apr 2023 00:54:40 -0700 (PDT) Received: by mail-oo1-xc2c.google.com with SMTP id f7-20020a4ab647000000b0054101f316c7so3442260ooo.13; Sat, 08 Apr 2023 00:54:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680940472; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=w7f1ZJtQ7GVMBkDWdLfo+KU/tSEuvyaRTAOcNqcasmo=; b=AHns2xsd72x2hzUF8tVoMr+YvL6brrpf82BA2x+ZNUu1iZKDGBC/cON1n5EL89JQBX ojJ1NLxsgtjEUMkWUOGJh4Tmfi7MjSbOzSdRjoX+cFe5LGz2qNRBdcAvNyYAwr5MICTI Ll0PKzZO6ioZcpDFvqwV6mQSGT2KbN+N6r3VW6HFbDvFZYfF3VQyMvRRtTazxbTCGKd1 XnbKY4yqbEhcP8Wzp9wojyyVPt228OVOEgWptOrBZ5hfrbyJKonDaiARRcTt1mHobiFi l/TOojBi0NHOLARSdWm7xC9xkbn2LN1wgKqj3hHnyQrKQdCIS7a5gbLPAESw7+NYoSLy j+TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680940472; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=w7f1ZJtQ7GVMBkDWdLfo+KU/tSEuvyaRTAOcNqcasmo=; b=egaUS/r+zvSrd3GgecHPNUgYezkHRafbLCmDO/YWaW6H/amZJuUspS1T4ZkeRYbGG7 vF5dhPK0uNmZmY5h5aNhCCeNQzSSmBmXx99Pk+pMQcG7BH7P7NEIyELAQbCzwkU+uKbH NyolvoTNk7zHyjfLqlaEQW+cfSRX97qta48A3NdUhLm2sHxXZomIvJW4j8pOMscqEs8U /LntpEbrtXzSd6IaGrGPeHtHijI+AL+02d4xqqaHIXrK5jmRJTxzDOvJO2RmMwEWQXzG utleblJx5xZmb2aECdHcnohEeKq86SZk2i0kOSBpM0Bp0W8bHWBnFePlWmYy0vEccvro syxw== X-Gm-Message-State: AAQBX9fku461Fz5sF17/45c5D7+n5DZx3ys+EHZm4mlQda57XCBL0Ktz N5WhHlqcEo3gmLNgV6UYQ+5FfShSowY= X-Received: by 2002:a4a:8963:0:b0:537:f9d4:a44c with SMTP id g32-20020a4a8963000000b00537f9d4a44cmr508363ooi.5.1680940472423; Sat, 08 Apr 2023 00:54:32 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id o6-20020a4a9586000000b0051ffe0fe11bsm2435175ooi.6.2023.04.08.00.54.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 00:54:32 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v3 13/13] rust: sync: introduce `LockedBy` Date: Sat, 8 Apr 2023 04:53:40 -0300 Message-Id: <20230408075340.25237-13-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230408075340.25237-1-wedsonaf@gmail.com> References: <20230408075340.25237-1-wedsonaf@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762594096971449710?= X-GMAIL-MSGID: =?utf-8?q?1762594096971449710?= From: Wedson Almeida Filho This allows us to have data protected by a lock despite not being wrapped by it. Access is granted by providing evidence that the lock is held by the caller. Signed-off-by: Wedson Almeida Filho Reviewed-by: Martin Rodriguez Reboredo --- v1 -> v2: Added build_assert to rule out zero-sized types v2 -> v3: Improve comments around panics and support for ZSTs rust/kernel/sync.rs | 2 + rust/kernel/sync/lock.rs | 2 +- rust/kernel/sync/locked_by.rs | 147 ++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/locked_by.rs diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 431402180aa8..d219ee518eff 100644 --- a/rust/kernel/sync.rs +++ b/rust/kernel/sync.rs @@ -10,10 +10,12 @@ use crate::types::Opaque; mod arc; mod condvar; pub mod lock; +mod locked_by; pub use arc::{Arc, ArcBorrow, UniqueArc}; pub use condvar::CondVar; pub use lock::{mutex::Mutex, spinlock::SpinLock}; +pub use locked_by::LockedBy; /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`. #[repr(transparent)] diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs index c365bc909dff..84d8d7d01aaa 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -111,7 +111,7 @@ pub struct Lock { _pin: PhantomPinned, /// The data protected by the lock. - data: UnsafeCell, + pub(crate) data: UnsafeCell, } // SAFETY: `Lock` can be transferred across thread boundaries iff the data it protects can. diff --git a/rust/kernel/sync/locked_by.rs b/rust/kernel/sync/locked_by.rs new file mode 100644 index 000000000000..ab0ecb013f54 --- /dev/null +++ b/rust/kernel/sync/locked_by.rs @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A wrapper for data protected by a lock that does not wrap it. + +use super::{lock::Backend, lock::Lock}; +use core::{cell::UnsafeCell, ptr}; + +/// Allows access to some data to be serialised by a lock that does not wrap it. +/// +/// In most cases, data protected by a lock is wrapped by the appropriate lock type, e.g., +/// [`super::Mutex`] or [`super::SpinLock`]. [`LockedBy`] is meant for cases when this is not +/// possible. For example, if a container has a lock and some data in the contained elements needs +/// to be protected by the same lock. +/// +/// [`LockedBy`] wraps the data in lieu of another locking primitive, and only allows access to it +/// when the caller shows evidence that the 'external' lock is locked. It panics if the evidence +/// refers to the wrong instance of the lock. +/// +/// # Examples +/// +/// The following is an example for illustrative purposes: `InnerDirectory::bytes_used` is an +/// aggregate of all `InnerFile::bytes_used` and must be kept consistent; so we wrap `InnerFile` in +/// a `LockedBy` so that it shares a lock with `InnerDirectory`. This allows us to enforce at +/// compile-time that access to `InnerFile` is only granted when an `InnerDirectory` is also +/// locked; we enforce at run time that the right `InnerDirectory` is locked. +/// +/// ``` +/// use kernel::sync::{LockedBy, Mutex}; +/// +/// struct InnerFile { +/// bytes_used: u64, +/// } +/// +/// struct File { +/// _ino: u32, +/// inner: LockedBy, +/// } +/// +/// struct InnerDirectory { +/// /// The sum of the bytes used by all files. +/// bytes_used: u64, +/// _files: Vec, +/// } +/// +/// struct Directory { +/// _ino: u32, +/// inner: Mutex, +/// } +/// +/// /// Prints `bytes_used` from both the directory and file. +/// fn print_bytes_used(dir: &Directory, file: &File) { +/// let guard = dir.inner.lock(); +/// let inner_file = file.inner.access(&guard); +/// pr_info!("{} {}", guard.bytes_used, inner_file.bytes_used); +/// } +/// +/// /// Increments `bytes_used` for both the directory and file. +/// fn inc_bytes_used(dir: &Directory, file: &File) { +/// let mut guard = dir.inner.lock(); +/// guard.bytes_used += 10; +/// +/// let file_inner = file.inner.access_mut(&mut guard); +/// file_inner.bytes_used += 10; +/// } +/// +/// /// Creates a new file. +/// fn new_file(ino: u32, dir: &Directory) -> File { +/// File { +/// _ino: ino, +/// inner: LockedBy::new(&dir.inner, InnerFile { bytes_used: 0 }), +/// } +/// } +/// ``` +pub struct LockedBy { + owner: *const U, + data: UnsafeCell, +} + +// SAFETY: `LockedBy` can be transferred across thread boundaries iff the data it protects can. +unsafe impl Send for LockedBy {} + +// SAFETY: `LockedBy` serialises the interior mutability it provides, so it is `Sync` as long as the +// data it protects is `Send`. +unsafe impl Sync for LockedBy {} + +impl LockedBy { + /// Constructs a new instance of [`LockedBy`]. + /// + /// It stores a raw pointer to the owner that is never dereferenced. It is only used to ensure + /// that the right owner is being used to access the protected data. If the owner is freed, the + /// data becomes inaccessible; if another instance of the owner is allocated *on the same + /// memory location*, the data becomes accessible again: none of this affects memory safety + /// because in any case at most one thread (or CPU) can access the protected data at a time. + pub fn new(owner: &Lock, data: T) -> Self { + Self { + owner: owner.data.get(), + data: UnsafeCell::new(data), + } + } +} + +impl LockedBy { + /// Returns a reference to the protected data when the caller provides evidence (via a + /// reference) that the owner is locked. + /// + /// `U` cannot be a zero-sized type (ZST) because there are ways to get an `&U` that matches + /// the data protected by the lock without actually holding it. + /// + /// # Panics + /// + /// Panics if `owner` is different from the data protected by the lock used in + /// [`new`](LockedBy::new). + pub fn access<'a>(&'a self, owner: &'a U) -> &'a T { + // Detect the usage of SZTs, which are supported, at compile time. + crate::build_assert!(core::mem::size_of::() > 0); + if !ptr::eq(owner, self.owner) { + panic!("mismatched owners"); + } + + // SAFETY: `owner` is evidence that the owner is locked. + unsafe { &*self.data.get() } + } + + /// Returns a mutable reference to the protected data when the caller provides evidence (via a + /// mutable owner) that the owner is locked mutably. + /// + /// `U` cannot be a zero-sized type (ZST) because there are ways to get an `&mut U` that + /// matches the data protected by the lock without actually holding it. + /// + /// Showing a mutable reference to the owner is sufficient because we know no other references + /// can exist to it. + /// + /// # Panics + /// + /// Panics if `owner` is different from the data protected by the lock used in + /// [`new`](LockedBy::new). + pub fn access_mut<'a>(&'a self, owner: &'a mut U) -> &'a mut T { + // Detect the usage of SZTs, which are supported, at compile time. + crate::build_assert!(core::mem::size_of::() > 0); + if !ptr::eq(owner, self.owner) { + panic!("mismatched owners"); + } + + // SAFETY: `owner` is evidence that there is only one reference to the owner. + unsafe { &mut *self.data.get() } + } +}