From patchwork Tue Apr 11 05:45: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: 81734 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349583vqo; Mon, 10 Apr 2023 22:48:06 -0700 (PDT) X-Google-Smtp-Source: AKy350Yrctl1HQ60zyGD8SF1Ob3aS0F3/V85eJPRVye5pSI3uSmhcQN/yuND8OXvxRigDviZjHhK X-Received: by 2002:a05:6402:4d:b0:504:adc2:80da with SMTP id f13-20020a056402004d00b00504adc280damr1096222edu.18.1681192085959; Mon, 10 Apr 2023 22:48:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192085; cv=none; d=google.com; s=arc-20160816; b=Q5MHIIoGuF6lRHc6sTUmTFZWSvFyTKn9UtELthQRBKhFKdsbxAvg5bEcbhlsB3XLWY x/AM+5eK7PsVSAsDDuVZqIh5oq8dkahD6oHuZ0dFEDWLCfhM9khStEGDCqi2gsOtG+Yr EJlbXfqNulASkcmgEu1uqHBdfkaBxsyh6X82zSC4hkFd/OUYzHWM0XAXBiFZVXMsygnk 5xUxQT4ngK1epQGfVbxxtLJ5/e5jvdQqO9+itCuA//dUB++mO9hAc0ZbPBKPwQUdTUFe Z0oVRRhd1oMv9uO0m7QPwa+0CohUMAllU/BhPBgqK6+t6TcPFGY2Z86gBki5HiK8d/S6 DIRg== 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=1ypxcwM7jmy4EIpQHDDPh+AsNB2yPLBLHEq+9dLke6s=; b=WTokzHZGl5gAqnRg+e/K3y/T82Ov2Fd63/MoYtqEefvEvVGnrvvHklWVWfnCnkidY3 xW+TGUh2IaDA9d9WtliwmVwH7dd0Ptj/wcASydNUp7hK85uWwKMjJGOqTgTCTtHwO505 ErD0jrirLS8EyoIfoIOuRn7QyJGDv/bxHfCjss4VRWkIb7VczVLD1Dz3R1FYAuzpJiwp L/djvgUKJwtQWnSA2PiLKvX5OmwM4+aWtJ6iyDbLLltbBTkT8x2RzYZGWVeW06JSeg6a CPUE0o+2OoEcoe+BHUYu13HGDVd9RtGZK82XfO3XY9BkVnlgb/cW1LviUQysxgyl6TwS 2r+A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=bf0q5ppt; 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 ca23-20020aa7cd77000000b004c698b5018esi157379edb.347.2023.04.10.22.47.42; Mon, 10 Apr 2023 22:48:05 -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=bf0q5ppt; 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 S230053AbjDKFqB (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55698 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229775AbjDKFqA (ORCPT ); Tue, 11 Apr 2023 01:46:00 -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 83186C1; Mon, 10 Apr 2023 22:45:58 -0700 (PDT) Received: by mail-oi1-x236.google.com with SMTP id bh10so4800966oib.1; Mon, 10 Apr 2023 22:45:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191957; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=1ypxcwM7jmy4EIpQHDDPh+AsNB2yPLBLHEq+9dLke6s=; b=bf0q5pptumpcxLxrOW546KbU4uBFR3fSYOT3zZ+OPRaAKucJvPTTIiDnQ2On/1P2b5 q/l1Sz0fmZj75+UjF+oyuYKRCzcCbTYUIqAsxydmXZgsYVR1wdcVVtZGxbO2DEgmOFcL OI/bM55VumEXQw8P96QEGUQeZ1Q+Y5zNefGZL1vYUXKcVF6gdra3/kKDUbmsgJ/m0+ha pN+Q46fMjMhm5qgZ5JsPWvfFdAdZZ1V4zJ+14NchpzKkKsJsrLHy7VvfPf3aFqafJ75o fgSJ+vrjGwnrOdKTI91sA+CAHVaxQrv11XbwEkJQZqGF9H8YPgUl0r5tt8TeBF/4OUip ScvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191957; 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=1ypxcwM7jmy4EIpQHDDPh+AsNB2yPLBLHEq+9dLke6s=; b=FmRRQ+RPWqj8IVUjKvVxBv1eaHdPZZw1fU/7ZALeeAK/UrlzYpI1FTVkspDXCrwRWh BNk2V7u5nQTgIAzV1a49kUxj6TGvG9SwYpXZ4FNj6vGaIgYDuEH+hONxF507M6UZ5ZU7 ri9XA/O/zrs/TiFxTNu6YzysukhfWtzcG55KWb7UUsM0KR+TkylQ0PnMyzgXH9aOCleB aZB68lubn9SAfRPouAjqARJJl9S9xd8p/e3fDbcmp0d6EUf0/AId1E2yoNAOY0FPuG9F ZDovPj0JpXwRePEOit4Zx7CJJd/ep0nnL3YkqyK8tr8LSjTixLazfcIZ0BZRN9nnDHnZ 8BjA== X-Gm-Message-State: AAQBX9eidutPy+UeEHo7f9D40rI7NfmovRQLTKUVVAKGzU7Of7jCL4HW hRc1kP8nxhg7sPh7oJP8E1/xdGOBSLHNDQ== X-Received: by 2002:a05:6808:2904:b0:38b:bceb:4047 with SMTP id ev4-20020a056808290400b0038bbceb4047mr2652094oib.45.1681191957535; Mon, 10 Apr 2023 22:45:57 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.45.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:45:57 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 01/13] rust: sync: introduce `LockClassKey` Date: Tue, 11 Apr 2023 02:45:31 -0300 Message-Id: <20230411054543.21278-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?1762857672613784890?= X-GMAIL-MSGID: =?utf-8?q?1762857672613784890?= 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 Reviewed-by: Martin Rodriguez Reboredo Co-developed-by: Boqun Feng Signed-off-by: Boqun Feng Signed-off-by: Wedson Almeida Filho Reviewed-by: Gary Guo Reviewed-by: Benno Lossin --- v1 -> v2: Fixed a typo in comment v2 -> v3: Replaced `core` with `::core` in macro v3 -> v4: - Rebased on top of rust-next now that all dependencies are applied rust/kernel/sync.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) base-commit: 2d0dec625d872a41632a68fce2e69453ed87df91 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 Tue Apr 11 05:45: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: 81742 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2351618vqo; Mon, 10 Apr 2023 22:54:58 -0700 (PDT) X-Google-Smtp-Source: AKy350aB1+N7c8RdXo/3Q/VwZ2e1qffGeMXWp3QKpto3apr9SvPz2BS1sUYR4FYKZQordkpW5kSh X-Received: by 2002:a05:6402:2053:b0:504:aff4:cc17 with SMTP id bc19-20020a056402205300b00504aff4cc17mr1217229edb.11.1681192498189; Mon, 10 Apr 2023 22:54:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192498; cv=none; d=google.com; s=arc-20160816; b=l8yoV70XweMastnqHbwGQXcXXsS/vJ8kkEcOVFzCj0nYWDHr7UOWKHO0lOUU7G7Otl KWL0OB+Yl9/iL8ZTFTZhVLZzFLeFtmNWV09UHXJUAy01FqUkPWvJQMmDOitSuMtqkc61 Q6rOxEHQwWMfxCqmJpLNmVZV7WUVJ1Y3YruUyqONQcGXaGtA+1jtrZiHYcs4ZlCV9VDW 26P9onmrBMv52ofB3Ba+eOmBnZqZT/Vc1paVbyco1qZxv/zIp2M+V0XXiKWzxOYT7PH9 WAeqegWVBO++Sj6cYOoU6id9e1WJanf8a91DOEvan7wgZpCA2xvORrlCWBVJWe0wkLzA 0eLw== 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=o8+XEPg91zVw8lsPU7tB81XapT1ATQXK+ygjS31ezwI=; b=mEU9XS57+PW4dVjVVVfcssYvhaG/R+Ka0NdYs84bBX9ciDN/jiUstocU1witOXZOg4 FB4BMaQiMxOPDr3gIRUzAqLz/ybQe2++hwncYnepDQNVesfJZcWU3kyVD6RNLjlStviF SSiUd95PeJmJ29tPjV0tXIz31gYOQ+qww/WNktS6/GVUdFJKPC9PVd/6NIFLyg0o8KvK e3+lgTrSCerGsP7PJRQEedDCxjZX67y2R2MsXu3PICjJDKQoN46fatTvJ9XjWQ0qcXF0 iYuh53VMvSen6NbUo9m2+qxz2M6qtZycz8DJqFcR39eZ6wTT7lcSTFQFVTVt/8NxdSz1 pmpg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=HiI60g+T; 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 vv11-20020a170907a68b00b0092c848d8805si10751585ejc.217.2023.04.10.22.54.33; Mon, 10 Apr 2023 22:54:58 -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=HiI60g+T; 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 S230014AbjDKFqF (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55722 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229775AbjDKFqC (ORCPT ); Tue, 11 Apr 2023 01:46: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 05A50C1; Mon, 10 Apr 2023 22:46:01 -0700 (PDT) Received: by mail-oi1-x236.google.com with SMTP id bh10so4801020oib.1; Mon, 10 Apr 2023 22:46:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191960; 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=o8+XEPg91zVw8lsPU7tB81XapT1ATQXK+ygjS31ezwI=; b=HiI60g+TR7h+Zk491FJ4+7OI5HacUOvConv8u+tLNyBDwI8sAaFdGRbZHHFjDAl59/ bzcZnPC8oPNhN0WLK2m/FoCSOjHUXvOOPQLqCuMzeKnM/hLSBtdhkvF+U2ztnKtnRiG4 YAlRW3wJFD19edadU9aDF3E3PGn+ICAjDciAi5U1hJg08xD6r/cobj/bzEQ6JS43tMUD WKwIqo9lC71qIdd4WUV+QSuy9YhdCNSAKR64CSlG/U78Kj0w4NjATXVUQL+LtNOxnonP pzYbenIusDdITw2e+M06XOOutaEox0yb/s/e73gVHHJXic+rULbsfYNpHCaWT5GoNYQF CIzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191960; 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=o8+XEPg91zVw8lsPU7tB81XapT1ATQXK+ygjS31ezwI=; b=CuVcu891OMiqp7fMluBJukg5MjgVzXd60QObkLNaf6G4PVOR9fmHFNQx5799DpQjvJ ilk2w3WZXMlIZbgQ3ws/ItPcj6GdccNQ/aG7ZlDoNEBh5ZlS2peDFZC3FmSSDU2Ka/gE P/NDUGJ3xw4T/k8ZrJDatdqzwKh4mCfXfxYaASsS9ULLh8Lve76s8SdAaIYOV8sRkAPE EXWY2fH49vKn7a4LA+0VAbjEMSJ4waJgz0APEWjJLM2XKcsQwh4BtJ69RPX8ONIL5/47 AA8h8mTGNrtNcJdVqN6PYIdGrJ5dXiKnF+k6cUI3qDDYS2w893Ny7hCW+C0FXUcBFkYb SX1g== X-Gm-Message-State: AAQBX9e91cAINyKt7kytrqkUSdiRTW1pZl0N3rh8BTcBIMVXIok8JbCz xiAWR3TlC4hsEjAZ0gUGDuAqr299Wsc= X-Received: by 2002:a05:6808:3087:b0:389:791e:1401 with SMTP id bl7-20020a056808308700b00389791e1401mr7300695oib.7.1681191960655; Mon, 10 Apr 2023 22:46:00 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.45.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46: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 , Martin Rodriguez Reboredo Subject: [PATCH v4 02/13] rust: sync: introduce `Lock` and `Guard` Date: Tue, 11 Apr 2023 02:45:32 -0300 Message-Id: <20230411054543.21278-2-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762858104514038254?= X-GMAIL-MSGID: =?utf-8?q?1762858104514038254?= 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. Reviewed-by: Martin Rodriguez Reboredo Suggested-by: Gary Guo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: Use new Opaque::ffi_init from Benno's series v3 -> v4: Fixed name of parameter in Lock comment 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..1a8ecccf4f24 --- /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 `B`. +#[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 Tue Apr 11 05:45: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: 81735 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349598vqo; Mon, 10 Apr 2023 22:48:09 -0700 (PDT) X-Google-Smtp-Source: AKy350b8rONaqCHZODsahixoNDOifK6WNPHoN3EcOxuJpR7f95HL0GLdyQTTPTdZW3AOVPE0NIwa X-Received: by 2002:a17:907:1c1f:b0:94e:ea7:4efa with SMTP id nc31-20020a1709071c1f00b0094e0ea74efamr2100444ejc.51.1681192089258; Mon, 10 Apr 2023 22:48:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192089; cv=none; d=google.com; s=arc-20160816; b=xR1hCiwKk+S/Pp9J1MIsSQ4Zvh9MIa/3FLAnuCfbCRqd+1NWUDsh+nQppRhPKQYM/M iBjCjaPlc6/Xjs0hWxNtkgaPJ6Y4esxGZSBobjgeKc4e1I51UOkSi6NYsD+PhWoPjrM+ 9E+NW7ndG0OD7xTrA9y96+q2DP5kL8hSYrbXMJGERw7ku9iAhwfZ17qln0vBj8vh9vDu RwGzYOvC0yOee8iihWtrzDAOFuC+m8HGmN7fmpn8CDwtmY8H4XlxAPCS+HFREQVBaFDF eBNpX2UBYijiXYthRfhnSS9jC+H86s5eI5vm1p+9AFpvqbSwxXwf8n1xatjDk7RFJJ+2 U6WQ== 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=VL4SAF5/q9qhJ4toS87ARUNeVl0yq0aauKrjQLRBpsM=; b=n7+Q+otpDHlDjxS3+ilG1qNVYW9FCUH/yxGN0Klhqkyit9iun1GRmngI26hWgvcb5b Hb9CPJ1NuxA3xAGb6L4WmtW3GptmmtlLJr54ftDO9/wtgAGVY+KeQ4jLUTPVIee78IhP esR67jQ2LYOemQis26mfxCWsiutr4WU8eDWO/fEYUj1hd/alVibscBZBGov1WMly6CQH VsQCcbO1V61Owt7rJIo7y3pIWupOyC5DP7EraE0msJbOZnXRWoWQ30IoxSLOAupKHNNZ V8IBIM5695wH/7mCj6Rb9IyHPRI/bunC5UnSLwFiW68l2Bnny9J6GkyI7vS0V85esoIX Oklg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=O0jOkImT; 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 ud15-20020a170907c60f00b0094a55ce2d8bsi1091611ejc.606.2023.04.10.22.47.45; Mon, 10 Apr 2023 22:48:09 -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=O0jOkImT; 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 S230090AbjDKFqL (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230096AbjDKFqG (ORCPT ); Tue, 11 Apr 2023 01:46:06 -0400 Received: from mail-oi1-x22a.google.com (mail-oi1-x22a.google.com [IPv6:2607:f8b0:4864:20::22a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5C06530E7; Mon, 10 Apr 2023 22:46:05 -0700 (PDT) Received: by mail-oi1-x22a.google.com with SMTP id bg24so4712945oib.5; Mon, 10 Apr 2023 22:46:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191964; 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=VL4SAF5/q9qhJ4toS87ARUNeVl0yq0aauKrjQLRBpsM=; b=O0jOkImTs9oNDuKvb6A3Z3q43VibRlNxkR5SLEprXfU6PXoPfFRdkcoUfF6jCjIp1C PDHDllM6BVpZOzQoBSYZ1x0QlChxZVDd16M+ESAMePQO+sMwDBrix7uFUetPB32IKOyV 8z/r7wNgG8Rup3GWTSVvTsp7vDxnsOhZI58jzpWiyIf17PRYVrWitdUP9/tydiM4yLiX FTR+mDpI+zxcajIZ+aB53fFFATstcr7CWiHm4nNHhWuA50MzG0YKX3Uf8tzyWTusoeAf mrvu9xThN/8+znVbtS9W371sPn5Vr42ThF9sWyo0+dpZbnZEh2BBY/ElybgiRImDE2Sl TAug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191964; 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=VL4SAF5/q9qhJ4toS87ARUNeVl0yq0aauKrjQLRBpsM=; b=TxMjrbBTIxiSnBQ1hpEwUe+UFCtrT7XtF+SgkYFGIcUTCY99c1qB5Kh6XW+m3MxTna 0mw5mGtefm8QW1qfcW4e14mKfL0ptNOH0vNfGDuJnbaZ0aa04VUeqibg3FZS2x4rk0hU JZDiKc1nxVJ+16TCbvIr1OXDPlLLMdBZiip8/wz4zQrgyj7v6d+CkK3Adnj1/LT5fdmq kPDwq2ShK2holpCNPEB81no09AQxo/tpG8ViX5iDRmBjwwWoSstDkGah+omHiOgFrsPr zMh9+DXAgHIVypCMoNvJd0qnOE6XAtx8sRw7FKas+6kWWTyzvqO92v1s7d0/EFIuK8Im nfjw== X-Gm-Message-State: AAQBX9f8AWssxW3wG+1cH8/1th3OsTgSqNk8lN67XRK6II+pLmMhq8dG RRSOjA0tLP2MZjryN5JiH5DOL4n2uYY= X-Received: by 2002:a05:6808:4ca:b0:38b:4fbe:43d0 with SMTP id a10-20020a05680804ca00b0038b4fbe43d0mr880307oie.29.1681191964548; Mon, 10 Apr 2023 22:46:04 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46: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 , Martin Rodriguez Reboredo Subject: [PATCH v4 03/13] rust: lock: introduce `Mutex` Date: Tue, 11 Apr 2023 02:45:33 -0300 Message-Id: <20230411054543.21278-3-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857676060936679?= X-GMAIL-MSGID: =?utf-8?q?1762857676060936679?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: No changes v4 -> v4: 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 04b9be46e887..86af099d2d66 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -22,6 +22,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -29,6 +30,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 1a8ecccf4f24..98de109d9e40 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 Tue Apr 11 05:45: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: 81738 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349833vqo; Mon, 10 Apr 2023 22:48:58 -0700 (PDT) X-Google-Smtp-Source: AKy350bwl6zUx0XUdTyRk0h1lGqpozYseTmh3q0OdZ+WGBx3OVLG1CXZ/2rwCRNtGYO40titfwUR X-Received: by 2002:aa7:db95:0:b0:504:80a4:d019 with SMTP id u21-20020aa7db95000000b0050480a4d019mr9891209edt.12.1681192138634; Mon, 10 Apr 2023 22:48:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192138; cv=none; d=google.com; s=arc-20160816; b=z1b32omgNZxxsWpWBo3WB+n2+fhLADmU+ohG0YLbKE/64H+/V4Npu0KSW/GIiOmVfM NfciScWikvzWvsEzL0hNCA9wO+FpSnOIYT5B2lrFrGY/AagXVoh2fjyZVpg5iiWcfQgw t6S/pIc7Q0oAf1SxHEOSAfacrREukQgLLD7qkubA9IPLE2JYiExnFLZGvq3BWkQVBl21 QM06owFc19WW0n3I+w4JZB/iD3JjNp4qt4uIOm/cWT8W4QmPQeQQ7nCy6j1WIIb+c7Kk 1d1jv2D7Fq9svNU6Y7UH1SlHuVwqAPpAR1GU6QC2pOMNU07SxPfWwNg1dmWjiOT+wK5w N94Q== 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=OMoguo+iBIICiLerFXdpd+JcayaULGRY+QPKRH6ebeo=; b=BrLi42vEuUXwhi+cEJmqLXvghGIZ5Onk5j3YsIdqcaE+3De7jNN7GPWZpSXwDgZuBM iZZxuvYE9c2Uppg9+xVOiRIGj9yos24IV1uKIFfRQwJwAvZfl155e53fVErdzT2emAaQ xwQo8gJHxBwMd5zzkc0SQRLZ7Spq9PxBbIj4pCQgUfRDOi8obnB2zOJvc1hfBkuzPzKE b14dxTnBh/iahbqEP9dhw/qTV6Dw3Bdwk2lHGDRcpSGLwQ6AaDvoKLCbFajKjkMKi+ng jjkf7wvTi0tFqF6DfBaWZTVAS2k2K3SszuGFaBDFb9PT2zTnUNoYBECxPPvqxC8cgkzn a8tQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=Vy0MDXVm; 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 o22-20020a056402039600b00504933bb95bsi2968293edv.459.2023.04.10.22.48.34; Mon, 10 Apr 2023 22:48:58 -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=Vy0MDXVm; 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 S230137AbjDKFqV (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56114 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230106AbjDKFqN (ORCPT ); Tue, 11 Apr 2023 01:46:13 -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 436D130C5; Mon, 10 Apr 2023 22:46:09 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id f14so23130228oiw.10; Mon, 10 Apr 2023 22:46:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191968; 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=OMoguo+iBIICiLerFXdpd+JcayaULGRY+QPKRH6ebeo=; b=Vy0MDXVmlIUIX1TZ3HA4etUNBbauhNAB+kdihsmMwBX8Y17PAEDNf8npYjdk4om5df vreUWoEEYtyF0ulvNg7L0Tr+PAIMKpcHHGDMP0Z5wlcDl/hCzSEIKarx2WWmhV0TaArm EkhyoU40N7EAK5HNYmkkGOclOjq2WtzEXFjiVA/KQ5Y384dQm1eH4w742NnX+NUbNM8R TMIEtEcCO7NEY7rRQLIp8PdiV74u16QcfWMD0UnbqGWziY2/T0X/30GPmoDgEsc0zCQG 3UAW1w8bpUvtTXNb9PKX0VQpJbqgOAzL44k3Fi5Ygl2i3DKllsjRXGcp834zGHT8xAqZ 45FA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191968; 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=OMoguo+iBIICiLerFXdpd+JcayaULGRY+QPKRH6ebeo=; b=eYvrAaWuLD63uAF58Hmq1Fy/ku8R2408zl6pWslhcw0c6YOh0zxLDTiUvjjQwC0Z0W AJoKR7Ff8ZgdGAXj6LjyFO3bb+3BOeQAoKYCgCaNM3X4CvI1eqi8KWhlLGZhliznR/os OKOpoGRQos21j+QBxvG/dMnbh0fgX+bG8Gscn9xavqtTaCXCtMGAxRlCyZ8jOotacgct jqahvqHP/tgwFbzerDEq+69gTDQw3mV2+bRYg4b71ZV84KpllpqGXoqhkxtTs9fcxoKW OMU4OGYxTiHrm/pn942YKevfivbVsp+h6b4IzokmySBIUn/raw93YJ24IaWg7wL0I2QV 1FjA== X-Gm-Message-State: AAQBX9eowFFk55G75ht1Od5SqFaWbIESBSY0Nj5/JjUT9hrv6IKxYSUh NJhFzgAAMOQsdjbdG8VzcU0nq+PmjRw= X-Received: by 2002:a05:6808:2117:b0:386:e510:db0 with SMTP id r23-20020a056808211700b00386e5100db0mr6242965oiw.44.1681191968444; Mon, 10 Apr 2023 22:46:08 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:08 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 04/13] locking/spinlock: introduce spin_lock_init_with_key Date: Tue, 11 Apr 2023 02:45:34 -0300 Message-Id: <20230411054543.21278-4-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857727836360888?= X-GMAIL-MSGID: =?utf-8?q?1762857727836360888?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho Reviewed-by: Boqun Feng --- v1 -> v2: No changes v2 -> v3: No changes v3 -> v4: 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 Tue Apr 11 05:45: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: 81736 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349679vqo; Mon, 10 Apr 2023 22:48:24 -0700 (PDT) X-Google-Smtp-Source: AKy350aOFyTEAuzUV59YrMkiEYhUHeuVxvxtJmjvANBZiV78lg/jyywCncGXIcVIoTm2adDoAqok X-Received: by 2002:a17:906:facf:b0:92f:ccf3:f0ce with SMTP id lu15-20020a170906facf00b0092fccf3f0cemr13258511ejb.45.1681192103905; Mon, 10 Apr 2023 22:48:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192103; cv=none; d=google.com; s=arc-20160816; b=nxYIE5C+JrZSQIicnl4Y9eC9VHHKDic+tXbp/vaFx6CmBbsMty0KI4z1hunibp+qBM xrpqgwT27lrqwGmckBHt4p4MkjUfOCFcBizE0KdS9Hvn7oF2mZIqoBP67bLq3Ng62aD+ XkUYckuvGEEdZXFQtH1mkeqpayI5hKnv8k96nmNxcevZuvf2YGKOiQWSAHkKakDRXJWh 83FFwEan0OCjvKYMBTlBtN6vWrOJ5ohHqdQhB3pK59fEybZE1nTLedLtkn6zW+4+Hm+1 /JkdKmXXr4x3qcdgDybJ7N9abi6LhojiMFkW1lJh9xrN4vbDuxBtpDKUTq7xpM4+dF60 eAsg== 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=BU1aIfRkJj4hN5kETMCo+xD8d0WgAtSmo7HPla12H84=; b=NCVwxHq0mitMf9G43R9i4NgRUT/ZtpZG25KyALboZq7+HWSnTWmhJlI/aYu6EE9fUL IgTlm/kIkb2koKEvHx36JKJjdNlH1Hj5xu+6DEsY/IPCqcQ/JBroepv7tr1usM4Me3e1 qnW/AQaVQ/ksIan+EWiwCwUcKncUfi9kSFuwI0e6Z7b/Jd1S8AvUUiZeBvgXKvYKOkbX 0v54sA89NKD5qZyqYrr6rXNAp3paiuDi7uomSeFyqZlgYUlRhSa0Mb4UimWdzUZvRDHB GR5qbcQAmbthsv0pugMk0MWPp4g/GQYh7uDsN81O4O24mJGdVxuIyTf/kOYchlPritF8 weqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="G1/S4UI7"; 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 vi2-20020a170907d40200b0094a45d4b95dsi6137983ejc.652.2023.04.10.22.48.00; Mon, 10 Apr 2023 22:48:23 -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="G1/S4UI7"; 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 S230129AbjDKFqf (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230133AbjDKFqU (ORCPT ); Tue, 11 Apr 2023 01:46:20 -0400 Received: from mail-oi1-x22b.google.com (mail-oi1-x22b.google.com [IPv6:2607:f8b0:4864:20::22b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F0BA35A6; Mon, 10 Apr 2023 22:46:13 -0700 (PDT) Received: by mail-oi1-x22b.google.com with SMTP id r14so31017528oiw.12; Mon, 10 Apr 2023 22:46:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191972; 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=BU1aIfRkJj4hN5kETMCo+xD8d0WgAtSmo7HPla12H84=; b=G1/S4UI7gtPWoZCbBHrwVz7Ke4W5S3Hbv0HHt358FxInQiPwkT0ezglFtX8iFxb5AX u2L5+WDFeh39ZcelPn+MMp40CCbyfeI/X1JygXT52yOqx+aCJH8d772nAu7VCU0XTj8x k7k6RwhU8uJJA5HND5IQGtmzJjLMd2jO8fshIO+JYsHzgMdxfvcM/8vn/C3OWudiC2uT 6UMyRBqK1mwSnIeuJsjn4N54UzqsHhsVFhxRFYvoxU6yApLWYypapQfbVYxMKXvjAw48 meoPunso7eo/IjM5nvEPFRDXFMtw3PptsKVZX0a9AB5d1fjdhhYv6rx5p52SEjhCydz6 Pp1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191972; 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=BU1aIfRkJj4hN5kETMCo+xD8d0WgAtSmo7HPla12H84=; b=TkQBGM9Em+e4p4uX03ViMGrWGhH3KMTOYAWJzyHapVQ7TjxeY7DpcWXjqFL2oihUpD /gbqUnlFoyH68lLARuScCJcmErRDyKmXzXL9Ds6YvkpduGJe32ejPuZBuGoTGhsh/8LU ojp665q+FhV2Hd3xtLYiOZqL2BHTb1mcM+Ofsn7FTowg9+ox/aMyYUW/TzHhrvbPAF7l nu1s5FwL6kbKbYnnClk16M4j9ZZAZE/9i2G0UQOeXrfwoJPIQlrzr+RUfHZPBfEJLDwY h4s9mNuMVt4R0xHZMVI0+p4nTXPM1NYy8j8ztaWSO4VWPUOLX69ZgpIyiynUt7e2Oc06 b8Kw== X-Gm-Message-State: AAQBX9eUtb2t0fgCC65+2kmjEZDLEbnURi29kH5Z657YhruIU2EFD6DV QnPFHwolXdUnPz5FOsQocLQAFvhQXRk= X-Received: by 2002:a05:6808:2c4:b0:384:36f2:5109 with SMTP id a4-20020a05680802c400b0038436f25109mr5153993oid.6.1681191972355; Mon, 10 Apr 2023 22:46:12 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:12 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 05/13] rust: lock: introduce `SpinLock` Date: Tue, 11 Apr 2023 02:45:35 -0300 Message-Id: <20230411054543.21278-5-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857691065273666?= X-GMAIL-MSGID: =?utf-8?q?1762857691065273666?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: No changes v3 -> v4: 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 86af099d2d66..141308a78775 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -23,6 +23,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -36,6 +37,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 98de109d9e40..08adc3747033 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 Tue Apr 11 05:45: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: 81737 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349691vqo; Mon, 10 Apr 2023 22:48:26 -0700 (PDT) X-Google-Smtp-Source: AKy350bcXLe72YZebVIPvKWCxFa5T9uPEjWJj2WeEPQ4rrXqHKVXUCFdYXRyNhRQ8tLr0DAjnrsU X-Received: by 2002:a17:906:ef90:b0:94c:4dc1:8c0a with SMTP id ze16-20020a170906ef9000b0094c4dc18c0amr2820418ejb.32.1681192105903; Mon, 10 Apr 2023 22:48:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192105; cv=none; d=google.com; s=arc-20160816; b=p3w+parqLttKfqvUT4hpF/xbYHv4wVqYOCKJnkRBSY0uxxlxKDFZDXb54GwiYwT58b W8f9k1YGLLB6Z534lcs6EqOhQ9foDDpfTXib1BHz+UoVJbNPSucZXtUp5zz5PV11LMAj 3XcaS/LlaKetGc+Dy+A0OXYTc9KhnG5Wlt+1UjRlDJhrLFyJYcZ9CRytxsoFQeVGZRjg 2QN2jVHYJPeAn14GP3g7kQBYVDjRwqesa8EUcWdKCLn+iIdLznukjp2X/aEoucgbbQAr Pj9rWlJiAke92HbmenjCWQG+dR8D2IhMzIH2aQ2NWzGcJO3UnIevhQNBAtCahomnHXA+ Wpwg== 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=AAreLXMWIgov70baVUCg3TcwQ+G9hKF5u+kmMd3Sihc=; b=krQ3cij1LE98w63YotqfuxR5BUfbpAsKuZg+AaT0NzLQkK2hbwD7wMSRqaH3XeZLzI UXfkqFSQV71f9qT7WdbJA5yUOBHnEXy1RzZHz0EivgJbUjBLfjtnq04QEhkNvhd6/D/C c2HyNbE3Quvr5gQshqTsTwbRmnnZfajs8B5HGpF0aOVghGe8P0EGgPYMNvudiKqo5hM2 XQPSCMRlVPUbjxVZ3ZOhdgeulK1NHwDKvQDUR50ouowk+mvbbxsfJUjE0eqU/A0YwJ6U u4xto6mi56ELKswZbIABbWJexLE0GFAGsKo6X83fu2BhHmPRbucV09I2fVTvyz2uOMGm ONNw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=gEQkaR3P; 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 u25-20020a05640207d900b004fcf925a8acsi1756409edy.251.2023.04.10.22.48.02; Mon, 10 Apr 2023 22:48:25 -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=gEQkaR3P; 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 S230120AbjDKFqt (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230114AbjDKFqb (ORCPT ); Tue, 11 Apr 2023 01:46:31 -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 445C92D61; Mon, 10 Apr 2023 22:46:16 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id j12so4798517oij.3; Mon, 10 Apr 2023 22:46:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191975; 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=AAreLXMWIgov70baVUCg3TcwQ+G9hKF5u+kmMd3Sihc=; b=gEQkaR3P8AqjvIR7pewuoP8UX0zC/dEcw/ATVeKUBdbqqUMbiK10WEP9Lv7vq+ceZB 7OUZ3akb7OSG5f0u+tX+1G86wTj7wQQ18JogW/oBZjXH49H7q7eh1vLm5U8j4BIcAYgO zzLyS6/qUE64VVytwvFWIuslAPetr2ap0wM2gccbN2siOgNmOh4x4BS8o2x9loj+ZMuz qj3zD+Qe0egpXy6uoyUGTyWcUnVRJa5uu4leEZBwp6rZpejmBV261dTMth0p+FKCuoYv iBgV7Jlsa/uQ3k0ch3NagUI4JW/ufVWkqOMWDUCbePTFoo2trF1gIJ3y8HwZE6SNxARa eJJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191975; 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=AAreLXMWIgov70baVUCg3TcwQ+G9hKF5u+kmMd3Sihc=; b=3get5erOBSn1Msy6iaqhQ23OMtxAuZF3r9fNAkD0XWxWnEzlMGvp/dmu1SeUtGLyeG j0Rv7D+27yI9CtRB/awxhIypNnN50oi2oZUc3u/pwwiTAb7uAMdz6XMDtLQ1mtaNcmUG 0bL35AXUxfwu62Jkcxe/Vcu7WFp8Fa8HIUyaScEe6AYnQzsXoYkzljg+UNBefJuFU0bi 9Grd46vBZX51GwF0Tfdb+pYWCvY857Z+HsW+Y3pyonfNKvWRdDngRrlnp20th44u9V5K HpworlEpJl/Er5JHN5Yg81WN0rETV0zIhkFflIz+5f2sxKrkGtTocyN1s5L+ft+JHW3n gKxQ== X-Gm-Message-State: AAQBX9csbwn25UwTH6LotG3C37lRfpI5Dzq9c2KXtB1e3YjcHljagZ7h 8tpG8m9qPK01IjDiojQMIsjhtBhNZj4= X-Received: by 2002:a54:4716:0:b0:387:3694:d5d6 with SMTP id k22-20020a544716000000b003873694d5d6mr4071074oik.25.1681191975404; Mon, 10 Apr 2023 22:46:15 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:15 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 06/13] rust: lock: add support for `Lock::lock_irqsave` Date: Tue, 11 Apr 2023 02:45:36 -0300 Message-Id: <20230411054543.21278-6-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857693642396303?= X-GMAIL-MSGID: =?utf-8?q?1762857693642396303?= 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. Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: No changes v3 -> v4: 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 08adc3747033..819b8ea5ba2b 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 Tue Apr 11 05:45: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: 81745 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2352094vqo; Mon, 10 Apr 2023 22:56:26 -0700 (PDT) X-Google-Smtp-Source: AKy350byYbvhH6vMhTQ42Remf0jStcOwflDGqFgp2uKYj9vlhWE0VHdogXPsO0UNVjM1p1IZoBjG X-Received: by 2002:a17:906:ce23:b0:933:3cc7:4420 with SMTP id sd3-20020a170906ce2300b009333cc74420mr10034436ejb.45.1681192585986; Mon, 10 Apr 2023 22:56:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192585; cv=none; d=google.com; s=arc-20160816; b=odnYxCb6vPJ96rmrlZ60FiWVUNd+Ee3Me1W1X5QptTryIkk0K/vWJ/YQR2zrcLbYIF /1t/CFxSbBlEo4lbxJ7S8+eEwwV5/shpsta6SM2pR7PIf03l4QS99zXziPDyufsDFbFG I86/vY+5C24o5jSI+0HUyUd3ThGhcuGRTXdoFUGVUYYtM96q37+BhzpRyD0BuCed9J6P aEnDvJc46kJ95qNXGTH/pnoEwU/Cy9XELr/bZbcmnZqgcZcA2XeyYWEYLQfofhFpctqf adsOX9d2np6636zmUOVZTwG57FjazSAiKh/sW1fmylj7gbMvbzIUyqDjEFqobXhZ9+M1 Lepg== 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=Pv6qNRZHA9f9WsLjADdwd+ymESG3pRy2ih0fvHz3LhE=; b=UZCVnGW2wB4dIpNZupBFNvjFOQWuOyU9hHWXrl9TZp0+wEuUBP4n9DNPYN2w3hAhdP EenGXQNDZ7MdYWl0EEz7aR+NJXntcPDYUg9K6OdhSPsr1rbXWZbFXlrGWxvt7W9i/qB1 eVtd9Uhds0k1LpGnWSVUhfaJJs7qqseZqLMv1uq0GGHp5w+K+6IiMNAG+gZDU9Z8LaHm 9s7kJtvXm5ODslpzaTCxkmIljntY+jdqHI/PT4K4LEgP6kpLT4br0TasoBF31TUreWk3 swmyxerLUJo6nuaHcIetxEtrLPoiAbMCi325ENDYTMy8r4bnXkHozcjBFGPxILFQC8/n P/+w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=ideeZghk; 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 z15-20020a1709064e0f00b009332d435456si82528eju.610.2023.04.10.22.56.02; Mon, 10 Apr 2023 22:56:25 -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=ideeZghk; 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 S230125AbjDKFqy (ORCPT + 99 others); Tue, 11 Apr 2023 01:46:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57198 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230106AbjDKFqh (ORCPT ); Tue, 11 Apr 2023 01:46:37 -0400 Received: from mail-oi1-x232.google.com (mail-oi1-x232.google.com [IPv6:2607:f8b0:4864:20::232]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81AD73598; Mon, 10 Apr 2023 22:46:20 -0700 (PDT) Received: by mail-oi1-x232.google.com with SMTP id bf5so4751548oib.8; Mon, 10 Apr 2023 22:46:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191979; 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=Pv6qNRZHA9f9WsLjADdwd+ymESG3pRy2ih0fvHz3LhE=; b=ideeZghkQv4t9L4zEwczcldNB4KwoSCk6uFQ9dPWym9BzryvfJwYPw2XLs/OyWaZo2 QUInsoujXxznDtWvKrE0r/T8lbdoNHenhYMy/CR6TEO8jaUjKzI2eBxOaEfOt2bwPWJV R7JTTeNcdb2Mw5WJz5Me/vESsHQJVorJ3lgQUI8gk4xWU+1pBV2xtQdDXUpESzmw2gO7 LvjuE+n7uI2li1sxOt21l80x28UOsCkXhrPF+SZg47OHuObeAnTnsnaDJenmGiM2GGZV iqziTxvPKGMFTZdCetaLj5lI5mbLwRcyLxGzw9BZz0gnxVB5fpsOrsg5TMS6bx+bH4/9 YrKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191979; 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=Pv6qNRZHA9f9WsLjADdwd+ymESG3pRy2ih0fvHz3LhE=; b=eoEkFGqDRSzQd68D66KTrqvCYpxEq5cxvw2kmFlqDpiUKEPu7DwLCrpJqP3Wv/k0F1 QpaxGH4kajdxwCJnM9QXPayd1vmd2wPG+g5fDQdUt+chstqhLWBgVRrZY/PgJxhvK1Qq sX6HHBNvnwantlAEK05MHJC/0JOyhSoBpjhn2JdT6X4Yz6rPiQ63zKBmc/Qvg7vzM5GT fSODy5gl8TdGI24DZJmkoCqjs3HZxXb09oFti2yrSUlrD36R5KbmVMb1DvNSc9O7FQf9 gErcPLiDvOc3LOLn8E2Nl2SnUxzu7uYwRt8KP30//y3XsoeAEZY8OFJJEmv/9x9Rd98j na0Q== X-Gm-Message-State: AAQBX9eKpTZT1g3XMV4A1xtMIkqaiQ1Jh2RTQRU72f56M1T0rItoumRJ ytEI/h5Y8RX0mYsqoql+Er836je7LMY= X-Received: by 2002:a05:6808:3a85:b0:386:a2fd:398e with SMTP id fb5-20020a0568083a8500b00386a2fd398emr9927600oib.18.1681191979391; Mon, 10 Apr 2023 22:46:19 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:19 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Date: Tue, 11 Apr 2023 02:45:37 -0300 Message-Id: <20230411054543.21278-7-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762858196952923194?= X-GMAIL-MSGID: =?utf-8?q?1762858196952923194?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: No changes v3 -> v4: 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 141308a78775..efd5b1e86f6e 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -60,6 +60,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 Tue Apr 11 05:45: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: 81743 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2351793vqo; Mon, 10 Apr 2023 22:55:29 -0700 (PDT) X-Google-Smtp-Source: AKy350ZV8+dVOBuMdHnqBwmBb4WOggMnmoSb6hyUC+eNpSlLfjXeUIGX6/MrJCxR1jhIofOKi+Kp X-Received: by 2002:a17:906:2e85:b0:94d:a2c2:9aeb with SMTP id o5-20020a1709062e8500b0094da2c29aebmr2549723eji.49.1681192529252; Mon, 10 Apr 2023 22:55:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192529; cv=none; d=google.com; s=arc-20160816; b=U0K8YF11T+3JLP171QkRfT1UdAwAB1hwXkJn8ydT+L6UhPmjnKPtLLktDzRcWF8HfY G8CX2MoH0L1Jnn+6puNPOqipcFptE05ih2KiVfvOOh5diMuLgadOCRBhq2hCvXxr6eLl CvIk4Ld+2BKdh1FnHhDOzp4PgLXHsUyRcAyPREQj5dYGoMO2aien1c6zJIyB4mkeIU+C 8JkfW2WtR3N0se4SM94FdQnQdGEPPZS6X0T1FrrGWng2/6fVSFr9MSwPNnLKLtYXLOO3 QR5b9DtAlA5rlBS2rxtUH3It48/eMonRPhCaGx5+8jgcpsGWN+4HG5+FclMw7Xb58h+t b+dw== 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=lNoumsGmcTI11a3EyviqrqaE0Uj9EE9DrxAixIJSJC0=; b=qmxB9IlAGCEbplh5WBS3tKwejN0L4nm3KdpJXpwLRUe9R+DpwQRlHQiHY4YcMMCM10 cYnTly6/I4/6uK+JMSYfXdh0LFoeVnz9tfzAik96zHIRsTs1dq8Yp7mRSN/pyg3W85Hl zgYPlbBvlPyi02jpA+yvTYNM9IEC8pkkUUNIi6MlQhKKG2onTpEkA1bk3ksUHVft2uAC KtPmlLSEZhawU+KnLvHubGJIEiy9lkSKArtahLyPWK7i15XEKyOzTosj1MMHdNlP8fYm s0bTLyQsRjPbYxM/vtm6FySd+GUn02etnnYEZalBytK7hcbCyRiI4wG4Q/tTCbOymTG/ 2SBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=J2yJ1jws; 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 e8-20020a170906c00800b00946872f37c6si8698161ejz.450.2023.04.10.22.55.04; Mon, 10 Apr 2023 22:55:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=J2yJ1jws; 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 S230167AbjDKFrB (ORCPT + 99 others); Tue, 11 Apr 2023 01:47:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56106 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230113AbjDKFqr (ORCPT ); Tue, 11 Apr 2023 01:46:47 -0400 Received: from mail-oa1-x31.google.com (mail-oa1-x31.google.com [IPv6:2001:4860:4864:20::31]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35D943AB5; Mon, 10 Apr 2023 22:46:23 -0700 (PDT) Received: by mail-oa1-x31.google.com with SMTP id 586e51a60fabf-1842cddca49so8681820fac.1; Mon, 10 Apr 2023 22:46:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191982; 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=lNoumsGmcTI11a3EyviqrqaE0Uj9EE9DrxAixIJSJC0=; b=J2yJ1jwsNzIMBz5LAw//6l/1EI6gA2yewEhLtusaC728F+hmsWLU2lNQ0DnrD8zKVw Bsvei8W0IG6PlJVKavmzkDC4QEi0FnbNWV6FTmnEd3IPhGFMvXr2Z1vUP8kzikEqiJsL ZFT9BB9EycLpk4ZAooerfaKYdKIZZEVUF7Y/EvfhRfO19tsnbs167Z5VNzL4ZZQEtp2E oCL1EwIqKyuS/GfKlpKOLicZSuMDOfmurSCh5TlqdUzQNwaYoQoUf016jqd6l8JLenhj rKF+MT5OP45eitRYcIXVo1uacl6SHbiRS16xGl35JyHnMm6HiH6kOVqpkdYLa0q8ioXT tJig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191982; 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=lNoumsGmcTI11a3EyviqrqaE0Uj9EE9DrxAixIJSJC0=; b=GMmFhKkdPsCDaV43+oTD6uQWRmbwGn8AXb0DZlxUvqxVF/vm0du2vovO9/fP/QbFrI RbxU67VHdKSVw813hjoLlSp3di3ob1zGm0zU323jmUv7F4Ev/6vZIZuqA47sXtzXEki8 t0FSwHLiCVAh2QRUL+JQBf6yS1MC1lcQg5w1dSSgFjDTSUHjX/fgHmxs8pViIcEqPWQG 6qdhCPItI+st8w/Ibjf8BQHBqqmTbfNizOA+e1oinjOzk848h17za1a3zRYbwzBbahBo 7IUmGue/OQzdOBEqMz2TuFmzM0bvCQtDc2BI3Sg5RQ6W+bOmenfz90ssR0rW9ZvhctMQ pxfw== X-Gm-Message-State: AAQBX9eqpo08G6Le0uFaPHKcfXWTIOSL1Mw0geFOso0sq82l/Ruy6cUh LyvBi9HW3M84zP/KPfDcpxkXnsgCvfc= X-Received: by 2002:a05:6870:40d4:b0:181:d654:30c5 with SMTP id l20-20020a05687040d400b00181d65430c5mr5638095oal.4.1681191982433; Mon, 10 Apr 2023 22:46:22 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:22 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 08/13] rust: introduce `ARef` Date: Tue, 11 Apr 2023 02:45:38 -0300 Message-Id: <20230411054543.21278-8-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762858137328728838?= X-GMAIL-MSGID: =?utf-8?q?1762858137328728838?= 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. Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho Reviewed-by: Gary Guo --- v1 -> v2: No changes v2 -> v3: No changes v3 -> v4: 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 a4b1e3778da7..29db59d6119a 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 Tue Apr 11 05:45: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: 81744 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2352021vqo; Mon, 10 Apr 2023 22:56:16 -0700 (PDT) X-Google-Smtp-Source: AKy350YOnNLousOteS19NDSaQBH3WMwSZnCi2WwVpFWliDONpjh0PR97u1ZugxFWLOn8L91Dn5tv X-Received: by 2002:a17:906:eb85:b0:94a:658e:1180 with SMTP id mh5-20020a170906eb8500b0094a658e1180mr7026741ejb.26.1681192576704; Mon, 10 Apr 2023 22:56:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192576; cv=none; d=google.com; s=arc-20160816; b=AMx081UYuKd0WX/UmmsTG1KilBLZNaDViHFrADp+UjetmGNid+Ax1ML+YnygGf4adF xMSvDUwRBB60HoKEydsA/XYqt32+A8xszzcMd4iXBDhbmDqbYmao4ZF6wH/IAVHStBMQ oWdJOUUB4clDiVr6zRwCEaEbtwJ8c7IJjdzpnh9ivMi42bo1HBu7mJW5wPG7eLgnhwDZ cm/6IbSqnxxyCzL9YLN1Nb/AXh+m5wrc+G8tK57ANFK+hwgzyP5pTVDYDJxWUYy844bT ynwtMANeOQ+AxFznaePgfehuln3xLbBM4dZsDRL/jaJ90MiwsnerhM1J3iDJqlogLDx9 DD0A== 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=+0ZE9/PqwNMu99Q0OKeqOYCNEDEQw5CDxMBCw+OXX00=; b=GipE9DZ29S3zw4U+RDDp5uWFdsvHM1gpm1WfHnwb22PXzQbBLr7fph9grDA4S7+a/s XYUd7V0S7emCeYGraJ3JAbALAMIicFocwzjxvmLiA6wKW80GIuO5fuRB2k7j9QxN+HsY IN1ir0l8PKUCP5oLI43LGwOBVqVdOFgilJt6ZxcoxvSopn/5G6pFe7SBSLcuo3MiEG1D 1T5gn7FJCdIr8+Nm7tlu8zFhVnRvSNymKYVx2S5tmUdFodFb0EsFPwpHIdIvCYBF+lz/ 4iuQXZHb+8WNE5GrGsbL6oRtcOtnFSTui0jDtmAEn4hU8mMBVC/KaxvU4Z1bDfTqu1xy ga8Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=mqGSpDZs; 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 a14-20020a170906274e00b009236b7f4417si11275010ejd.527.2023.04.10.22.55.52; Mon, 10 Apr 2023 22:56:16 -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=mqGSpDZs; 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 S230178AbjDKFrF (ORCPT + 99 others); Tue, 11 Apr 2023 01:47:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229910AbjDKFqv (ORCPT ); Tue, 11 Apr 2023 01:46:51 -0400 Received: from mail-oo1-xc2d.google.com (mail-oo1-xc2d.google.com [IPv6:2607:f8b0:4864:20::c2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C7DE3C0C; Mon, 10 Apr 2023 22:46:27 -0700 (PDT) Received: by mail-oo1-xc2d.google.com with SMTP id j4-20020a4adf44000000b0053e8b5524abso5075163oou.2; Mon, 10 Apr 2023 22:46:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191986; 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=+0ZE9/PqwNMu99Q0OKeqOYCNEDEQw5CDxMBCw+OXX00=; b=mqGSpDZsCP5tkLznKrmzxgqdN62WfnN72WO/PfyFOmSJrUGQwMDaWi1IHJjbaqfOMa O5Y52+zouWSEMqwKzoh3zGloHd5rieZMJBAneMVXlP5txO6dTFkxlzkMSivTj/qG/4Et k9SNJgL/+Db66lMKLNac76SUYR8NQX2GcGXr1mkTpXGlyHXFUzTH/3sQSWgn5rzqPAf7 Fa6dqupfXRrcudj0/+QrZQLGX+DaqNO1NggqVgsM6nZ75QcySN/8IBWeVCtIY2IDY/Fi 5ULW2HAe/pWQc+/ROjaey6YRpEnwLXJwbaRa0MYjxM+96N0TIXnClFlY3vvWMe80qhNg zf8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191986; 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=+0ZE9/PqwNMu99Q0OKeqOYCNEDEQw5CDxMBCw+OXX00=; b=uIfY8UP6jGsdtWcjBEcos1rLBKjonHn1bxAjmyvi6Ae3gya7mXpeU76ztmVEOretcP /gX0SZdzm3MKL2rw4PUUi5SWXRFP+KWi7/3eENgw5IWF61jrZvF1ZG9x5y6A4VLToc6f E29T6hceKH5IWX2YJg5dZNdKpN7wno1aqLe6acL1vCEhRAWjV5XJ0JjkD5eknJtFwUMc Cyqt1eaJym/WftjZvlqqc7cBsc/K9W5WtGJlHasHWnUzKtzyJV5hdGMUaToAaeidIUfE WQMaXPdyKwdfI7J1lQEdndgORnPtRKI5s3yxmW56Lru2GirZTmenVNqWkCCGfYVVs5fi srLg== X-Gm-Message-State: AAQBX9cShJ965h3LvLvw61QaCl7j2g6+nCF+7Y0QMCGoJkuUCJrztJza 1Mnua/MBpt18ppjU/rzJRMTf0/onjP4= X-Received: by 2002:a4a:49d1:0:b0:525:4316:7dac with SMTP id z200-20020a4a49d1000000b0052543167dacmr605537ooa.5.1681191985907; Mon, 10 Apr 2023 22:46:25 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46: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 , Ingo Molnar , Peter Zijlstra , Martin Rodriguez Reboredo Subject: [PATCH v4 09/13] rust: add basic `Task` Date: Tue, 11 Apr 2023 02:45:39 -0300 Message-Id: <20230411054543.21278-9-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762858187412159809?= X-GMAIL-MSGID: =?utf-8?q?1762858187412159809?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: Wrap task_struct with `Opaque` instead of `UnsafeCell` v3 -> v4: No changes 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 efd5b1e86f6e..f545923aedd8 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); +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); @@ -112,6 +119,18 @@ long rust_helper_PTR_ERR(__force const void *ptr) } EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR); +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 Tue Apr 11 05:45: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: 81746 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2352119vqo; Mon, 10 Apr 2023 22:56:35 -0700 (PDT) X-Google-Smtp-Source: AKy350bUiqNKluurmPv0BihytLbzART/coaMvdWZ6CHtw459RJLsBsQbOayX8uea662u3z+F1Jnz X-Received: by 2002:a17:906:b17:b0:94a:8f4f:5755 with SMTP id u23-20020a1709060b1700b0094a8f4f5755mr4807745ejg.64.1681192594941; Mon, 10 Apr 2023 22:56:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192594; cv=none; d=google.com; s=arc-20160816; b=Btq4vGEv/KSwX9Y+QLQL4jMFfQmL9Ax4XSvmereb19rfEMHTuxjx80wm0qUQnyj0NO pR/yzTsbDu5Zfp7t6KoSWYH2QA/+tDLUHLMJ6+OX7mFUg0PSsnnMVGmYnozOGoVxAIs0 +mFv2aPvrILOYG2gcY8xLlfaKntemWzNWdlfxeAmtwpdP4h3J3NX1gzY0HK73rOVYUAv CCc2RLUKkSodz4eIj6oVoTh3vogxDJ7Gg3CxGAGuppIyzTCMuFFzHhGRBTLwoxBTDZ68 vCqgXrFbOC9FB5c308/f8iz43lDEJM7DFM2zFa0WxukNFs/PnFstWKpFQ5EndNRZUs1N RXvw== 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=zUkx2cNtJ9nWEz5p2C115hP3yX3TNsqfTu3Xx0TaZoc=; b=06hJg6FF+2KickOnZczXSn0hhKuuKmCzGT9R+euXbD1vBwRdTFjLxz1kMWstzVfF2p MeafSZvFtW0CLk3cnqkPQC3dKahTvCkeQq6/JqIN5zu6S19KIzSrZrEWUN5mD2BM1XXP 2c8JsUUS3YOiu56UGCFDTIlShk7jFDxMZswgNJZaSLa0ynMPFb5PddleY50Et8GgpMw4 7M39LJNI8lclcRxnFGlqExGbBo9HL1wgsIHsjoR1vkoXutfTPAdS+v9d9DeDpZzPtmF8 3UNgbgWgk5g70smGySuX3NMz+gRGaizWxGrmoNJV2Tj2o3R4b3LEwgI56qxlVlsSLhpY ufMg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=pPOb333I; 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 sd35-20020a1709076e2300b0094a8988e37dsi99813ejc.151.2023.04.10.22.56.10; Mon, 10 Apr 2023 22:56: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=pPOb333I; 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 S230140AbjDKFrR (ORCPT + 99 others); Tue, 11 Apr 2023 01:47:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57288 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230089AbjDKFqz (ORCPT ); Tue, 11 Apr 2023 01:46:55 -0400 Received: from mail-oi1-x22e.google.com (mail-oi1-x22e.google.com [IPv6:2607:f8b0:4864:20::22e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F55030ED; Mon, 10 Apr 2023 22:46:33 -0700 (PDT) Received: by mail-oi1-x22e.google.com with SMTP id bf5so4751688oib.8; Mon, 10 Apr 2023 22:46:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191989; 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=zUkx2cNtJ9nWEz5p2C115hP3yX3TNsqfTu3Xx0TaZoc=; b=pPOb333IxbtfUtBRo9n91qNlTUJCGuqiBxRAynTWiqR81UZb2LtF1gQja+MEx2fLx5 3emHHqVnU/+xcWMwIfqZdT2+/gYDf8VBZtREnQSUIiGf0YMNJLP30JCKSasirTiD4ib0 kyotpoA4fNA/MPcQmBOCrxoaKP8Bov79k+A2DSEbzjeG79XeK3jkhNTMTHQtIi757H3c KjZj/bXM+LPnYMACtpQJaVSrT9fRZ1Q5dJWd2c4PP1m9uLFBHSrElG2ZPazB8AyJfUWw uWxrmQpGIaKbwNgAaVTE31CefYBB/O6trikgOkxTH1TxrdKCRFU9wEbNJtKdUc6O17qc pAEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191989; 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=zUkx2cNtJ9nWEz5p2C115hP3yX3TNsqfTu3Xx0TaZoc=; b=u250c/B0ChTqXy3E6o6YIrDOwB77XzSf4tQ7kgx4hnrl+E8H+oQ23ftGyIykv/qM3X JV+Rov4wrYxVoZ64iOhPGcriX9Q/9WUZY8h3r3simQe9UlzCiARPfRUtch8w05mMOX7E pMn/csLOMWUuXhfSNJoBKwy7xlfc3yBVegmll9utc9Uaa8rvQ5tj+6Sw3Y3e5MjDI3KD zc12FwHz47jdozno+gbEzTRvg0KcOLWYr3LilaKUmD+v9NN7Gb2pFTHAcOhDMHHHwjAy UjLKSdFNGuSj41K2dXXmiUuHsZ7WQ3efzZ0S2icOdhkt73/rw66f1zYWIwJibHaDbbod 6I5Q== X-Gm-Message-State: AAQBX9eFzPAco6Y+HSukqZGRqqSGy4IwCOMGOLcwXx599cDtqL4Onj4m ZxA+BFXB17brfcmj2t1e+vA/56TFNwc= X-Received: by 2002:a05:6808:a8b:b0:389:5164:9db2 with SMTP id q11-20020a0568080a8b00b0038951649db2mr5896169oij.48.1681191989480; Mon, 10 Apr 2023 22:46:29 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46: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 , Ingo Molnar , Peter Zijlstra , Martin Rodriguez Reboredo Subject: [PATCH v4 10/13] rust: introduce `current` Date: Tue, 11 Apr 2023 02:45:40 -0300 Message-Id: <20230411054543.21278-10-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762858205931468678?= X-GMAIL-MSGID: =?utf-8?q?1762858205931468678?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- 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` v3 -> v4: Remove impl of `From>` for `ARef` rust/helpers.c | 6 ++++ rust/kernel/prelude.rs | 2 ++ rust/kernel/task.rs | 82 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index f545923aedd8..fba3c62a77f1 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -119,6 +119,12 @@ long rust_helper_PTR_ERR(__force const void *ptr) } EXPORT_SYMBOL_GPL(rust_helper_PTR_ERR); +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..526d29a0ae27 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,40 @@ 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 { + struct TaskRef<'a> { + task: &'a Task, + _not_send: PhantomData<*mut ()>, + } + + impl Deref for TaskRef<'_> { + type Target = Task; + + fn deref(&self) -> &Self::Target { + self.task + } + } + + // 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 Tue Apr 11 05:45:41 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: 81739 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349894vqo; Mon, 10 Apr 2023 22:49:18 -0700 (PDT) X-Google-Smtp-Source: AKy350atvGJbMFGlrDNdPj9ubtnE/AqVmTLWmHYe/Z/hIJ/72GdN0ykWZv3+mnAKOcYdsmQVr55+ X-Received: by 2002:a17:906:1057:b0:94a:921b:c805 with SMTP id j23-20020a170906105700b0094a921bc805mr5536610ejj.45.1681192158390; Mon, 10 Apr 2023 22:49:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192158; cv=none; d=google.com; s=arc-20160816; b=baPdlxGWx/n2aKeYIogOuMVsWzilceKLgPp96RFs9IOr/QGK6LMLaBDQhF/aSYrueE E2F6Y5Gy/q5uOFoel6kc5ATPQCq6TdWcM59/dKN2GIbSjcBWxvlB5/s69ZBrfP6K8pwE iOHBfXbFsYNWv6P+czj/SVa4WiJaInprDZO2ubcWeTncw2naIQIEKFZxD0nKzDsdZDo5 YPLgbav8Sg0dJOid5+/9H3DhCb9UnUyRibYS4VPhNlRqw4UN/FJAjP2k+v2pxm4ykHqP A10DuSe0Zre5oML7oF6pZ2iAjDs2DXnxOCmQb8demSR0j2rRxNdefu01Dbf2I85bftMP wdKA== 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=aaXy46x7GR5XrSzVHQC7SvsfS2kUsSvNQ00pK7ZlJKE=; b=MfVSLje7WL+UU5d6FPeTwOVL8I9h/FahAPXCXu6cGr/1HO3sjMDhC3V+OG8nk5ikvK p3UuTpAgvSjB2vmUob7eTZ+L8uQywXKtCuLk6EYndp1HZ14DGc9nYuFNhEuBpr4M88lF T9w54EiqoeFo59Qez7o1tG8K48YsWBSa7S6tXicoeeKN+DcdO7eo3u8uv857ymP8NQAg xhrpw4OPts6cEHV9JsrREUOY0W+D2EnhxrwjiOi9OdNsTCdzwhrI54Hggm60NUc0Xw+Z koKJMJF6Fwl/7b9fXrBJwhxdMS1w5e4Nhr0yR7dABVM+IJVrKbStpXF52zWDFYE4wXK+ uINA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=UJLg+Vs5; 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 ca23-20020aa7cd77000000b004c698b5018esi157379edb.347.2023.04.10.22.48.55; Mon, 10 Apr 2023 22:49:18 -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=UJLg+Vs5; 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 S230159AbjDKFrU (ORCPT + 99 others); Tue, 11 Apr 2023 01:47:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229759AbjDKFqz (ORCPT ); Tue, 11 Apr 2023 01:46:55 -0400 Received: from mail-oi1-x233.google.com (mail-oi1-x233.google.com [IPv6:2607:f8b0:4864:20::233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DF772359F; Mon, 10 Apr 2023 22:46:33 -0700 (PDT) Received: by mail-oi1-x233.google.com with SMTP id bf5so4751729oib.8; Mon, 10 Apr 2023 22:46:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191992; 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=aaXy46x7GR5XrSzVHQC7SvsfS2kUsSvNQ00pK7ZlJKE=; b=UJLg+Vs59cCQxvgXFa0R/s2/3v6HTFoRsrG7JRs6qN2ByOGN0VWBkXMrs7MXStX3Yb z+swJtuQTgsm8GL26/3D6foDwZlhExpvKItRwG/WjKwjr7O/aenzMS/Q3XEuxQL/aDM9 m0VB2YmR16oQUIafVzMct0GKJUuMheRK800QUR1ZSrBW+P7iAejmOjlWuOl2qMnVMzT6 qBQZ8Dc2M5twSX3EDsjvFUl6MaL2ZAkmAOSk0R8b1k3HvGB7H3nPrpYDsEg86rXq//9z zDlU+Yuh/rEEWTpaD5KyqzrDxblHI6yVm1ybOz2zhpEteqxF2StSb7axrNuBtwdB+1H+ kdmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191992; 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=aaXy46x7GR5XrSzVHQC7SvsfS2kUsSvNQ00pK7ZlJKE=; b=Y0n8I0aXDFGq558+vH6xm+yzRhfCHlDRMfM0Jo/yzK17OJAb9JuOXZXlJ3gNo3JwgP 0Hufk3GTvKgvZHDNh0id+Ugk2bw2GZ2sUUa2maPRn5hdIyHrEjunkLw3qebePBONGlJi OjLw+Y2X7vskDd6fPBajyluLi1DlTwG5G8cTx8GyoL9Y4CUA4XS8Us3Qk/D9bPNaHUUF qRJJYWAYJpTAqWXdRvnqnuB3wU7SS+8TmV5lSVz1ueyA2iEvjyZQf0MqOcVZzjcro9Ne Pk7OP34jm3gfMOjp811xb/hUnU1DLIeSU7v7vzsDSerGQe27yRjlPQuTcRRb3qaM/wyL 5dYA== X-Gm-Message-State: AAQBX9cR4u0Gp/gsY4Wl9SC0J/gsZ4+KWB13c0k+TwHM1gNJeG83FeB8 ey+1TVNoP9fLpIjuLcoLc6vvwqLUah4= X-Received: by 2002:a05:6808:4092:b0:389:607:f41f with SMTP id db18-20020a056808409200b003890607f41fmr643215oib.4.1681191992528; Mon, 10 Apr 2023 22:46:32 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46: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 , Martin Rodriguez Reboredo Subject: [PATCH v4 11/13] rust: lock: add `Guard::do_unlocked` Date: Tue, 11 Apr 2023 02:45:41 -0300 Message-Id: <20230411054543.21278-11-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857748671520653?= X-GMAIL-MSGID: =?utf-8?q?1762857748671520653?= 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`. Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes v2 -> v3: No changes v3 -> v4: 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 819b8ea5ba2b..cde57756795f 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 Tue Apr 11 05:45:42 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: 81740 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2349968vqo; Mon, 10 Apr 2023 22:49:33 -0700 (PDT) X-Google-Smtp-Source: AKy350YcP3f8aPhsrKtnqOPfzYBhoajTGt1hgvaJsVNiWnNseY3IqpFEHdE8wViqa0d4i6yeRiiV X-Received: by 2002:a17:906:f182:b0:94b:d72:bfa9 with SMTP id gs2-20020a170906f18200b0094b0d72bfa9mr1396949ejb.18.1681192173201; Mon, 10 Apr 2023 22:49:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192173; cv=none; d=google.com; s=arc-20160816; b=Xk9+hf+s1Y8Ac1BVPxxzJjYlJWY8g2FreWVRZ1w7rtxHUMZ+v9/IgUtfjpayXdfSX2 Q+nO1bL9y4mrk46+qfnnQO6Y6Pf3WR8n9rxlp1S2YPQZqOJ8grOcwPIa9mOTxOEiReRb 8q5rQSfTiQnhg1ZgUs2Xlthhcx2PfU7xWJMcpM2bNuR3eYUL4L+qmHIB9SLIWdB1wf1r vsm8PT9q3BNW5oXa5chRguXQLrKUYy8wLP3sDRCMcJ9eXWb62J0tLYeVkYp/QrdDJOMc ZZ8yEznxiGa3pcBmq+PMVPV4v3pDADIxOOcg6+yK53Wp80NA6Jdl6Sp5/C2+aeGLexYk fRoA== 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=H+34VFeE0L8cj38goD+qCt3AF3Uzi3TSt/WQrb45RTg=; b=lwm2V86YscbbJMVaNwCUw0PDsp3cKKNRBPRzyzbq2xiiLlqmd6Xg5xAxe0cc85ZTm1 WW3dsueOUrInc3BI+AND1o5ehNbYrf3rzvdb2JL07xskBCreIAl+04YpEKPzJSt0c9zp 7i6EPAiQ3WSViEoMA/IDOGXO7gRjZiZu5Wc/AtfZomtPx3koCc6CSAAugy+vqoRX5Zt4 3vy5Hu2Gqd+xo5TJ4i5MWIgnnptHzK0yv+9/ibDo5luLsSiqb7m6yLbcfIMZC/eh/tkZ T64pG140s2VawEY4DJ0lTynIvkHufWKdd59HQ0rcg79TbJuis9bbbMUVQv/cJylra5r0 mouA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=JPJUWByD; 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 tz8-20020a170907c78800b0094df6570f73si109566ejc.501.2023.04.10.22.49.09; Mon, 10 Apr 2023 22:49:33 -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=JPJUWByD; 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 S230209AbjDKFr0 (ORCPT + 99 others); Tue, 11 Apr 2023 01:47:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56104 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230164AbjDKFrA (ORCPT ); Tue, 11 Apr 2023 01:47: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 A145A3AB4; Mon, 10 Apr 2023 22:46:39 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id bx42so21144407oib.6; Mon, 10 Apr 2023 22:46:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191996; 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=H+34VFeE0L8cj38goD+qCt3AF3Uzi3TSt/WQrb45RTg=; b=JPJUWByDZ4xdp/z04bE4bWkqvWgufhuYv/WnPZi5jsjO9T5qkYwUDow4r+RnDTFb/A cvnsw93uzzzrDIuUsMroD+4DBVKX63ozRNKIM3Zo7p+xsnBf3hPG0TVNgdmc5dVBX1Un eik9CCheuaNVdQOzE3xD+uryKDM2yDlCxL3hr5eLrwnGzzbI9OyoSC3R0q41cK9BjP4w UgUMhjxexKKTt51On1eDxfjV24hFIPHHQ5BfKHbPXf3kufMyrLsL7j+3gApP4d07hOCQ Ace1P2aGCIaaTZcG5k2NoqGJq8ESUOacVzznIyyki9+d830CgQahIAXEd1zZ+pHSErIA 0vlg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191996; 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=H+34VFeE0L8cj38goD+qCt3AF3Uzi3TSt/WQrb45RTg=; b=QGACS3QzVw0ythGC2KRMtbLWGxeJU6PtXDDLmDYI7AmsAT2kel/ATGoTefDNfyFjdX aLcUKsY+kGXvFVGHT8mD12LjZjKyPsEQXUsWhFDSzxkzbOMdsF/Onl/2DQ15prsC3dEq JFDiNmiUC9JPRkMclZKCO/eJUKkhT0PiyDE878jvSK+ERm88auCP6MOJ++KBv39+Y9IB +OmksRIz3PZd7xRDZJJwbrg/WUYjVpkuei1m9i+tC7vkKYlj/0h9p51GW2E6mvb1OueO fKCGtIBg5yJvrPYjwdVDbA6o0feDwBH3U3SfbtcGBe/N4zYygtANLsYByWebitMxbDHH 5PNw== X-Gm-Message-State: AAQBX9cMGWGagogTU4rpSBKGvcKhyU3tkhf3X65pnp1RnvE3rAF8F3Ra p8nKX9vENbnzbWtiV06Qr0GrU+257II= X-Received: by 2002:a05:6808:8e:b0:387:2075:59c with SMTP id s14-20020a056808008e00b003872075059cmr5348486oic.37.1681191996522; Mon, 10 Apr 2023 22:46:36 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:36 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 12/13] rust: sync: introduce `CondVar` Date: Tue, 11 Apr 2023 02:45:42 -0300 Message-Id: <20230411054543.21278-12-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857764578091958?= X-GMAIL-MSGID: =?utf-8?q?1762857764578091958?= 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 Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho Reviewed-by: Alice Ryhl --- v1 -> v2: Use the new `current` macro v2 -> v3: Use new Opaque::ffi_init from Benno's series v3 -> v4: Fixed typo in example in documentation 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 fba3c62a77f1..2512252f621e 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -25,6 +25,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -77,6 +78,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..ed353399c4e5 --- /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_value(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 cde57756795f..816c5d3bba12 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 Tue Apr 11 05:45:43 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: 81741 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp2350166vqo; Mon, 10 Apr 2023 22:50:08 -0700 (PDT) X-Google-Smtp-Source: AKy350YdSsRuHlJus79JCOA1yaQNw2pS3CFPTTjbh3wd2DjEg/t5bbKZB+i7Au2S3UKAEPCH5xKy X-Received: by 2002:a17:907:7853:b0:931:95a1:a05a with SMTP id lb19-20020a170907785300b0093195a1a05amr10018662ejc.62.1681192208575; Mon, 10 Apr 2023 22:50:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681192208; cv=none; d=google.com; s=arc-20160816; b=Ojk/+nGNJHYxXW1tVf9ypt4boijan1RzJpe4LjcY38zd8/MG/PIgJOTXo4FDa82WkZ zXXzt7qlXb84uA63M1YaYhftW9RDQ7SEjfmqYcXXQ9X2vGz+rtCp2MHao3pX0YyH9epg wulKjm6TzuWRKRPSSFMa4h8wdLjr8Zf5WpqAjvllDLFZPY2vbMIG44tPmSkEedbEkhPE vqe+GE0xOS+RSTq+Es9B0p6LHW8k9UNajzCUdFprizgMLn6nMYPfnDVUeVMqozW7ffaj y3wNbIDMMbgNg3cwYh8VQEqf2IVLcLU+0knVbHiJQ9elVc2dCXpbRGSqFAsIHlPB16rA u1qA== 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=XgB0YMTALi714jlWS5MjgBj10Lq8MN7ZWt0hNjRBEmg=; b=dIeacINaJnFzu1gaSOVOJgkvc9D2lC9Iuivkzoms+B86sEafOiM7hRNDocSxQGbhB0 vQQqyaG2mLvvGVzWm06iZNduToHlc4+gkEQrCXR9hQ25PEOfs8bhYYL5is0Ztwv9Et96 PAjvMEN28VOuKJkDX0pJE9aLVhOMXCNyiIW/5x4zYLlirRwZHb6YEn/6gdS99WgXz1pW DPIQwPOdKzvBX8gjPD9TuMYHrBY/6PIfIt2gy4xt8ei5uJFVpGz83T06eiMf9RTymqsi Z4T6rhKZy8VqGsrPt5EarhFBQuXYyX/F81Nu0s46ApYqo//uGxdLcY7EUOhvRQ65ZlF6 G4Zg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=Fd5QF4fS; 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 o22-20020a056402039600b00504933bb95bsi2968293edv.459.2023.04.10.22.49.44; Mon, 10 Apr 2023 22:50:08 -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=Fd5QF4fS; 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 S229800AbjDKFr3 (ORCPT + 99 others); Tue, 11 Apr 2023 01:47:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58030 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230179AbjDKFrF (ORCPT ); Tue, 11 Apr 2023 01:47:05 -0400 Received: from mail-oi1-x229.google.com (mail-oi1-x229.google.com [IPv6:2607:f8b0:4864:20::229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 12988D3; Mon, 10 Apr 2023 22:46:41 -0700 (PDT) Received: by mail-oi1-x229.google.com with SMTP id bg24so4713460oib.5; Mon, 10 Apr 2023 22:46:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1681191999; 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=XgB0YMTALi714jlWS5MjgBj10Lq8MN7ZWt0hNjRBEmg=; b=Fd5QF4fS6HFrlai4MhzBvkpuDmjCE2SvaXB/Jee5HcGIl8vJx+gx59v6A3strn/bQE LJOBc3yZoJhGbBvMWpEnwMkxXrYgTXkxIcBPpPqyudpGo0dk736HchRsh3vYHT0NbtPI QJY86YQHbbAEqXdxrlt8GBuPL2TAYT7yUA4L5bGTp1RWRyG44tVVQ3HyoBuZYBAyLh0E aFEqjscqgasf4/RG0pt/jZwa8W1QdN80tEUKtrn1cl8jMyYVMzbnA703VMSi9TtqrQSZ 4Bp2xI+GJvRgrdFlFYW1v74YI2cZ4nom8kvGllyHiMFL55P6wg1HaK6AFoutPH/su/nN +zqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681191999; 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=XgB0YMTALi714jlWS5MjgBj10Lq8MN7ZWt0hNjRBEmg=; b=zCzGKTqLP8oSNl2R6Yoh5dko1yEPkTuUHJxbg4SdodcdgklV7yiAqTNYXRw396jdqK gOdh5TsisA6xXne1RlYjdn/tuB2TkgPB75Oho0Yxmc19joAJHqvd1xryWleA7xpN0/jE V1Oz4fzEfDwmuLePWwIg/ZNkoz0HxK9zlV0Xrz84XE/FT0GSQsX46hPEc492FeVdqS/Y W1twJcTqD1Ko4nV/jOpyqmdoYA7XgpWJNDZMd3/lF5pAwVDl/bPzq+cjQ7h0XE7MbdQG T4t/xD9SlTndc5YZgfWQpT7xGZmePhV7W7CT78q4S0hLTArerYNBETjTcMCeKPM1TIez ZjwQ== X-Gm-Message-State: AAQBX9fwwQy23hbnOCEtjP0Wp15jlDTJ5CYEAjzGw1VWlurWrGhkT9Hq 0uY98yHB/H1kmTUZw6QMmAtVektu0rA= X-Received: by 2002:aca:b541:0:b0:38a:63c8:800e with SMTP id e62-20020acab541000000b0038a63c8800emr8291992oif.7.1681191999568; Mon, 10 Apr 2023 22:46:39 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id z186-20020a4a49c3000000b005252d376caesm5440706ooa.22.2023.04.10.22.46.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 22:46:39 -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 , Martin Rodriguez Reboredo Subject: [PATCH v4 13/13] rust: sync: introduce `LockedBy` Date: Tue, 11 Apr 2023 02:45:43 -0300 Message-Id: <20230411054543.21278-13-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230411054543.21278-1-wedsonaf@gmail.com> References: <20230411054543.21278-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?1762857801212203153?= X-GMAIL-MSGID: =?utf-8?q?1762857801212203153?= 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. Reviewed-by: Martin Rodriguez Reboredo Signed-off-by: Wedson Almeida Filho Reviewed-by: Benno Lossin --- v1 -> v2: Added build_assert to rule out zero-sized types v2 -> v3: Improve comments around panics and support for ZSTs v3 -> v4: - Added build_assert to LockBy::new - Updated build_assert calls with messages - Included crate::build_assert and mem::size_of since they're used repeatedly. rust/kernel/sync.rs | 2 + rust/kernel/sync/lock.rs | 2 +- rust/kernel/sync/locked_by.rs | 156 ++++++++++++++++++++++++++++++++++ 3 files changed, 159 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 816c5d3bba12..14940312141d 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..b17ee5cd98f3 --- /dev/null +++ b/rust/kernel/sync/locked_by.rs @@ -0,0 +1,156 @@ +// 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 crate::build_assert; +use core::{cell::UnsafeCell, mem::size_of, 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 { + build_assert!( + size_of::>() > 0, + "The lock type cannot be a ZST because it may be impossible to distinguish instances" + ); + 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 { + build_assert!( + size_of::() > 0, + "`U` cannot be a ZST because `owner` wouldn't be unique" + ); + 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 { + build_assert!( + size_of::() > 0, + "`U` cannot be a ZST because `owner` wouldn't be unique" + ); + 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() } + } +}