From patchwork Wed Apr 5 17:50:59 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: 79841 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489140vqo; Wed, 5 Apr 2023 10:53:41 -0700 (PDT) X-Google-Smtp-Source: AKy350ZOF9dABRC70kOfn2XAIHJdfODmt4C2AdSgeq9JW6MDWNX0H7BD+9Yy0ue4nkcow737ylHU X-Received: by 2002:aa7:c50b:0:b0:4fa:e129:31cf with SMTP id o11-20020aa7c50b000000b004fae12931cfmr2954485edq.23.1680717221028; Wed, 05 Apr 2023 10:53:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717221; cv=none; d=google.com; s=arc-20160816; b=YZ4GRAOQIGGYXKMCTFq+vQnl2tq1dOyyNErgpJWzcDiUzfAHiKzW+PjWFOjXADJ51d 7ts7xJNkS8Fzdc94V1OQ3FeB4gGCtg5jlgKQrtKgHNwV3GbeyBvVX1PmJMpdjPa9d34Z D9Z67lwO/2eahxTXC0UdLmTN9DioXSZhEA9qUVZlZow6yFJZZv4SRvoOEWm8yZOfKL/w Ifaf0lNWRFkgexa++mMnLB0YbqzGhixhHXzjBiEzcI/V0pKH5YJfKWstcqG8rckfw9Cn 42zAb+IjJFjRNZ3C8q+l7jvb1YUPcsy4TmxNSMWFnwZz6OFL4jo6BDA9MDTVroQh3OaP bbHQ== 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=gMP0vMNBwrLjFKEPy2CMu1fnlfs0/NqzPWZqghLoLH0=; b=VygUp9fac2tOL2STL7irOwthUehT5c/pO/cZa+GtjmAOYY7zzklcwQFZpWT8qhKp25 JwIL9KNHJJmyOJo/qdGa4cB49yFqVN31StM7SukNPoGjhQjRVWIysjGONQc6R1YWoVt+ 6aM18SDIXR2EzWckR5fEt5v4fzwzviPabZqw7SALESunc2IVs+dn+mgCTn0VR9m7+QTv POphtyy9g/PBF92wAN3Lx2xFUg87nz7qElGlqVki56piaWUPo5GZwDXcBq6xoqUNjsJQ iZlcMW+5LW3VNi/AwHmI5ftaZACyM2u55N+DJ8reP/G6jpPnioUiZ/YzsPn3lBpwy8N+ RKqA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=FlNG5Mh+; 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 a6-20020aa7d746000000b004fd3ad97e48si2083520eds.55.2023.04.05.10.53.16; Wed, 05 Apr 2023 10:53:41 -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=FlNG5Mh+; 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 S230313AbjDERvu (ORCPT + 99 others); Wed, 5 Apr 2023 13:51:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38034 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230031AbjDERvt (ORCPT ); Wed, 5 Apr 2023 13:51:49 -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 43F794ED2; Wed, 5 Apr 2023 10:51:48 -0700 (PDT) Received: by mail-oi1-x229.google.com with SMTP id r16so27164948oij.5; Wed, 05 Apr 2023 10:51:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717107; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=gMP0vMNBwrLjFKEPy2CMu1fnlfs0/NqzPWZqghLoLH0=; b=FlNG5Mh+LYHiKmpVO5Kkc4ndfZx6rglAL3tzSlmi/R1LjGSO+vBbn6ks5jH5DYpZgt FT+BqMYU+CEicm4jafguOkkUALEXGHPS4q1txwi8kO8aH8je0r/wiM+0UiVVrl2BvUrP 1VniGaZvNHas/TWAvQ5/7l6AvbmGkHLL4JIbGTjspA4xamSeiaJQRAxWfJV80u6FtTHM OW4aksSQ5cf9DyJHjnGu9daZqwAiLwpFR74E+UZvj8ApO280bzLe8K8JsYCkkZYsL7xw aFEv2G0FgZ+65ZbkB9QDtO66naum9o1X12ufKAhJdQ2ZbMQ2LAXsT9NRMDUv4towzBK6 gm6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717107; 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=gMP0vMNBwrLjFKEPy2CMu1fnlfs0/NqzPWZqghLoLH0=; b=SfZPn6gAXjbBPHGulWdhKaQkqlagEQS2yHaIMW5/hT7RlVi0UR5zxwHA4kpfomwtJy IXvqpIhzF2VQMY3vkJTBjMiX/g3v1X90UPpjz0u7cjq9iO4Pd0b9uAGl9W4+3bqqoepO zO3JVYSpAOxgrXYDSX3rZVcDSt3TwPwkZsQ6v6ZWl6efUT3vXxlLm0RQvN56E5ziWAEn KRUcZegsp4hB7uFwBLpHe9IqeORMFnwHTv+MNKTY5ToJzQoiTbNEubtiGAcd6fQ/zyRQ LrMIGdI0K5LivBb9NoQKoUdlMUm/Vbq7tYDmfulAJ4hKQMnxMRqT+qwY1lvViQxPgUIx cvag== X-Gm-Message-State: AAQBX9egCtYV3tTiHvam437CAFFKAto6OIiP4cxPHdVb7RVd6FXIfi/p 52Fyf+HM//UafxGxE7AtJG7vWA++zoSYEw== X-Received: by 2002:a05:6808:6084:b0:386:f58a:2262 with SMTP id de4-20020a056808608400b00386f58a2262mr3259621oib.57.1680717107544; Wed, 05 Apr 2023 10:51:47 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.51.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:51:47 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v2 01/13] rust: sync: introduce `LockClassKey` Date: Wed, 5 Apr 2023 14:50:59 -0300 Message-Id: <20230405175111.5974-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?1761766876235586081?= X-GMAIL-MSGID: =?utf-8?q?1762359741056386712?= From: Wedson Almeida Filho It is a wrapper around C's `lock_class_key`, which is used by the synchronisation primitives that are checked with lockdep. This is in preparation for introducing Rust abstractions for these primitives. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Co-developed-by: Boqun Feng Signed-off-by: Boqun Feng Signed-off-by: Wedson Almeida Filho --- v1 -> v2: Fixed a typo in comment rust/kernel/sync.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 33da23e3076d..84a4b560828c 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 Wed Apr 5 17:51:00 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: 79851 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp494329vqo; Wed, 5 Apr 2023 11:02:38 -0700 (PDT) X-Google-Smtp-Source: AKy350a5FVfSYeAaq6vceb4feQ4BEiE2JOeaKPzjOqhpHowM85hp5OQGBWfNpiuiDukMNrZcboOB X-Received: by 2002:a17:90b:2d8d:b0:237:ae98:a47f with SMTP id sj13-20020a17090b2d8d00b00237ae98a47fmr3501648pjb.1.1680717758362; Wed, 05 Apr 2023 11:02:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717758; cv=none; d=google.com; s=arc-20160816; b=tzf3Q6E7xTySghFcHmufsAfPbOoOxZZ7DZGNYEBnAqgTQJ3GsxC7/43m5KnL50TW4U KpeJPXMoCll9knvYxlQdtoNBGeX+z3kgYEcwjtTIcrrDqERHD8hhFsnSNqG1G7dWktIK b4AVMhaya81MiDlp7HwRndUEP9pX0Ll1h9+H1JG1Evmep948mTH401HIX8qm7o1RnXMB K1x+noTcS8VyEBBCYUfiMdrIe8QUEf7/ua1xu6ZAyxo4JwMke8KEaKBV/TIhFa+wOazn TwtBEa3AkT/BHhVVSHY2aKdBNhNAXkoPwXVMEjbwbt6k1Po26VlZbwzSluhxr/4Rtl54 UI8w== 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=h4CtoUCbfJKvJDUejPnqVKPbox3V5JpU7mD+YHnrxrI=; b=nwg/bBl1GL8XUp0TLu0NwBzKYY6/bLJihWJ0QqEcLngM/08HQFggkElbLjjXBc8qPt 6KBBYpyZFT2W2VPj/UCBX0EEF+yLus9+rs8N5lIwIRDLmM4f7qZgPt8ruOB369BdoyWJ vfcNFYEVScK4qCvHNsaY55tMnXmvdx4VUGVfaDfHyFawLxh9vxz2935EFKpizDmFXYJL Dm+sqltfWmV3vw1zG7Y0FLlYDhV9tNQZJXBwy+d9t36RZGe7ge2gqHsj2n7pQtzPoPTK 0XgEuR01H7/1PF+CL9pAbXtgz+pUl9jbu1FZI7gVpndNbIglda/QsQnG9WYnLXg9beBT mTZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=U8A1YMhx; 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 g1-20020a17090a828100b0023b340b6388si1711929pjn.97.2023.04.05.11.02.14; Wed, 05 Apr 2023 11:02:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=U8A1YMhx; 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 S231311AbjDERv5 (ORCPT + 99 others); Wed, 5 Apr 2023 13:51:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229544AbjDERvx (ORCPT ); Wed, 5 Apr 2023 13:51:53 -0400 Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com [IPv6:2607:f8b0:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C79A565A6; Wed, 5 Apr 2023 10:51:51 -0700 (PDT) Received: by mail-oi1-x22f.google.com with SMTP id q27so26502839oiw.0; Wed, 05 Apr 2023 10:51:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717111; 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=h4CtoUCbfJKvJDUejPnqVKPbox3V5JpU7mD+YHnrxrI=; b=U8A1YMhx9n67wS6QvN2LO5fauGQUWgbFZIQk29wT51pdEiDN2+nLR1vN1KvLhK9y1c GPve1WrCx5ywrc4QDsiSj+4B42uHyfKzJ+XeSH0E8AWTKnZb5MyEE6OCWbG5jynVL7Bm eomN0l9hDgpqLHgC4Olj8JN+lHMXN5ARivBHdNn+v6hjCdP32gJWZuP3hn/+CZOoT0rU UwGUR9Osi91eqVDJMb+s9a+D4qh2K3o1iue9ia/jUUmztMhUio2R1d7+7VyC7RuYoS0A ksByHVle3X+WYRpCVhHlp4jmMdAkD/Y8/2DO+3F28wR+m8w8oS4zQr4TkHYioCcIsLIH GoiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717111; 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=h4CtoUCbfJKvJDUejPnqVKPbox3V5JpU7mD+YHnrxrI=; b=nFmdwOlMnLoExYQvBcK1kVaHdgJKXpYWyU/o6ZCOCBJwep2HAoedfpfWgwzqv6tyEd lrUxeq1PRBLsu7ejboCAI3RKdqA/gFQYLTR/Jzy/m2C46xPtHLXHgjj97mZ6mP5auK3u WVWGaSctZN3QQHGJLwZ1NS9a/FwLQ9bmv+Ot1rjHPnarLCKoalm6H+5bo/W80qVeAquo TCgchCAQYEnAFv+vpp53EfW8o4xPSZzL7zjJxC+A44AtwI9At9eNgs/sgJs9mlCXh6cV 7MrYlVSCxGz//aZPPSosdSk3lbRKRwvFKoaX5RB14EpdvSQTPwuXGk+pAAK7A64o30gM W6yQ== X-Gm-Message-State: AAQBX9fr4x66hN8XZNYGiMULu12jGjlG4WbqUoUqY7mEQ4pjVaH0Cqvx Y9qvZtkkiHMvfjfGsWTmomKJcp3AbLhUnw== X-Received: by 2002:aca:221a:0:b0:389:888a:73b9 with SMTP id b26-20020aca221a000000b00389888a73b9mr1323517oic.28.1680717110798; Wed, 05 Apr 2023 10:51:50 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.51.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:51:50 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 02/13] rust: sync: introduce `Lock` and `Guard` Date: Wed, 5 Apr 2023 14:51:00 -0300 Message-Id: <20230405175111.5974-2-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360304008760580?= X-GMAIL-MSGID: =?utf-8?q?1762360304008760580?= From: Wedson Almeida Filho They are generic Rust implementations of a lock and a lock guard that contain code that is common to all locks. Different backends will be introduced in subsequent commits. Suggested-by: Gary Guo Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes rust/kernel/sync.rs | 2 +- rust/kernel/sync/lock.rs | 160 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/lock.rs diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 84a4b560828c..bf088b324af4 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..f5614bed2a78 --- /dev/null +++ b/rust/kernel/sync/lock.rs @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Generic kernel lock and guard. +//! +//! It contains a generic Rust lock and guard that allow for different backends (e.g., mutexes, +//! spinlocks, raw spinlocks) to be provided with minimal effort. + +use super::LockClassKey; +use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque}; +use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned}; +use macros::pin_data; + +/// The "backend" of a lock. +/// +/// It is the actual implementation of the lock, without the need to repeat patterns used in all +/// locks. +/// +/// # Safety +/// +/// - Implementers must ensure that only one thread/CPU may access the protected data once the lock +/// is owned, that is, between calls to `lock` and `unlock`. +pub unsafe trait Backend { + /// The state required by the lock. + type State; + + /// The state required to be kept between lock and unlock. + type GuardState; + + /// Initialises the lock. + /// + /// # Safety + /// + /// `ptr` must be valid for write for the duration of the call, while `name` and `key` must + /// remain valid for read indefinitely. + unsafe fn init( + ptr: *mut Self::State, + name: *const core::ffi::c_char, + key: *mut bindings::lock_class_key, + ); + + /// Acquires the lock, making the caller its owner. + /// + /// # Safety + /// + /// Callers must ensure that [`Backend::init`] has been previously called. + #[must_use] + unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState; + + /// Releases the lock, giving up its ownership. + /// + /// # Safety + /// + /// It must only be called by the current owner of the lock. + unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState); +} + +/// A mutual exclusion primitive. +/// +/// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock banckend +/// specified as the generic parameter `T`. +#[pin_data] +pub struct Lock { + /// The kernel lock object. + #[pin] + state: Opaque, + + /// Some locks are known to be self-referential (e.g., mutexes), while others are architecture + /// or config defined (e.g., spinlocks). So we conservatively require them to be pinned in case + /// some architecture uses self-references now or in the future. + #[pin] + _pin: PhantomPinned, + + /// The data protected by the lock. + data: UnsafeCell, +} + +// SAFETY: `Lock` can be transferred across thread boundaries iff the data it protects can. +unsafe impl Send for Lock {} + +// SAFETY: `Lock` serialises the interior mutability it provides, so it is `Sync` as long as the +// data it protects is `Send`. +unsafe impl Sync for Lock {} + +impl Lock { + /// Constructs a new lock initialiser. + #[allow(clippy::new_ret_no_self)] + pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pin_init!(Self { + data: UnsafeCell::new(t), + _pin: PhantomPinned, + // SAFETY: `B::init` initialises the lock state, and both `name` and `key` have static + // lifetimes so they live indefinitely. + state <- unsafe { Opaque::manual_init2(B::init, 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 Wed Apr 5 17:51:01 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: 79853 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp494886vqo; Wed, 5 Apr 2023 11:03:17 -0700 (PDT) X-Google-Smtp-Source: AKy350YifUsyMnOi8bP42hThZrfibEJjMRG1sMzGP+gAQxArmME1e6aYUT/ZeBV4AuRB0yZ5QpXi X-Received: by 2002:a17:902:d506:b0:1a2:749:5f1a with SMTP id b6-20020a170902d50600b001a207495f1amr3526527plg.26.1680717797607; Wed, 05 Apr 2023 11:03:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717797; cv=none; d=google.com; s=arc-20160816; b=g/ALMZw5jRW2MuzYU3BiH2hKzVoMBhfCtA1L+izYGH/QGzJKOx8MEw0H51epogsUAW aBYCc0WVynt2LUcg6/zXuDBIoKgO0UoBHgHuQHgIFipfw43pXgkmvZRhCLSQH1EDUeOD c0wr15/g+K/3rag01fE9gnFxEWi/2rBEqzLfF2miy40JK95T9Yp3ClsutYB8cWHeDU4s Dy3ZXrHNcVVctwSo6TqfbTo+t7WfaLxDUuIUYAICdPrHvi6ZWHHIUBo7q5N08x9mVWeb gz+PE/jwpUI47vF73Dk0FqaCq0FOHiTHOkt3zWGchSrBNaqMUwNr3sp9Lu9Zrjc4eh7Z l/5w== 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=VKPe4ZYrLaif7r3R3bAYVGcjt87OAmyTt+kMVWIS4fY=; b=TRaxre9f1Y4TRIq/h9ulIfC5DWI632chz4zDHkQJHhQb8VQ2K4JAzWssfXN+x3/EGj 9YJWvy5i8gtdjvHBBk4rTMOZyKV8w3siE7RROho3GKWRI73N0XYFLaWE2HO/iHHcMEsJ MZOtJBu7KpeZJPKYgmx1r9U7s+/huMUXCgOFysg8Ab1jeDY5PG1VnTy9u9Xc+6V7kx/s 1X/yWM6rjODXx6Q/f51hqhRMuyGtU5k0lqcYDL6tOe/wiiesGCECOSESoxOtTVwXvC1F CEXWQ98Pyq++vHun/BPiMffEvlBx8s+DUfRlTKTt9l/GdlmZjlnOk4inb+ABaGGLWjSd zTCA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=qcz0U3y6; 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 b10-20020a170903228a00b001a076305275si2116206plh.318.2023.04.05.11.03.04; Wed, 05 Apr 2023 11:03:17 -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=qcz0U3y6; 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 S231767AbjDERwB (ORCPT + 99 others); Wed, 5 Apr 2023 13:52:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38314 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231393AbjDERv6 (ORCPT ); Wed, 5 Apr 2023 13:51:58 -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 0FBD66591; Wed, 5 Apr 2023 10:51:57 -0700 (PDT) Received: by mail-oi1-x233.google.com with SMTP id l18so27218462oic.13; Wed, 05 Apr 2023 10:51:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717116; 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=VKPe4ZYrLaif7r3R3bAYVGcjt87OAmyTt+kMVWIS4fY=; b=qcz0U3y6hWuVizzxQUsKTB35TzlsMweQZ0HY8cickbzYT2OG6oK1yD8EiEHx+lygrq yR2N46drRxixL6+kFeymTN0aB6cGi+ttgwytfuRJzcdZc0DiV2NVHJOsr3UQyxw/vZJL hRaq/rGoFJWYubf8U5K6fM4Y/ikDpqi6WfH8C7uEvQxZTlT7XcpYO5oblhq5l/9yfMUc /O1b2HdJVb/Nkb9FYGBfP4jXxZv55ytFZp4VbUpfeTOpniklLI5pNj5Du7JPrISEY7Xo 68viJPfjyNTY8jV8QBI+KdU1buQv9Gr5I2bKTkHSEsOZDBt4ZPCyd1yvmqZ9AaDBpffm zHiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717116; 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=VKPe4ZYrLaif7r3R3bAYVGcjt87OAmyTt+kMVWIS4fY=; b=DS64XMf6Fd+XiEibCRnRpgKf5NatHwYejubJjLKHgzK4E5T4SZUkRcP3YgKgCqbACN UIxlByY3naCp6aOHxjEhlT4VTiMbficId9Dt++jUr1Kb7mfi3ZEsSsyxb9/hwRZhfcjs apyLD0zm1KOlZBdnVcogEntOdJY6M23zPfOZtlmw548/xdnIDkbX5+7cjz5OYfrmIZcy RHFYYES+qbH4MbQGds574S9DMhyHQSnFpjNG4G4VZw3or3CSW7tZg3md7DwYHhVe5nOh PUjrsHTswe4r1fYZFXezdTRYOvuTt5O//9Xo0Pj4mXUEGOJQOCoFi5jAyHf2PwFuy74i diDw== X-Gm-Message-State: AAQBX9ewXxPF7ux9SIhGfwQnOSVtnLepbKOIk5qlmlpyU6Q1ZnsDpbfS 1Q5QAXSw925bXyfkTdebrmGkK3wkytrlVw== X-Received: by 2002:aca:3d84:0:b0:389:4bcf:83a5 with SMTP id k126-20020aca3d84000000b003894bcf83a5mr1674731oia.9.1680717114517; Wed, 05 Apr 2023 10:51:54 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.51.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:51:54 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v2 03/13] rust: lock: introduce `Mutex` Date: Wed, 5 Apr 2023 14:51:01 -0300 Message-Id: <20230405175111.5974-3-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360345439519901?= X-GMAIL-MSGID: =?utf-8?q?1762360345439519901?= From: Wedson Almeida Filho This is the `struct mutex` lock backend and allows Rust code to use the kernel mutex idiomatically. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes rust/helpers.c | 7 ++ rust/kernel/sync.rs | 1 + rust/kernel/sync/lock.rs | 2 + rust/kernel/sync/lock/mutex.rs | 118 +++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 rust/kernel/sync/lock/mutex.rs diff --git a/rust/helpers.c b/rust/helpers.c index 09a4d93f9d62..3010a2ec26e2 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -21,6 +21,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -28,6 +29,12 @@ __noreturn void rust_helper_BUG(void) } EXPORT_SYMBOL_GPL(rust_helper_BUG); +void rust_helper_mutex_lock(struct mutex *lock) +{ + mutex_lock(lock); +} +EXPORT_SYMBOL_GPL(rust_helper_mutex_lock); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index bf088b324af4..9ff116b2eebe 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 f5614bed2a78..cec1d68bab86 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 Wed Apr 5 17:51:02 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: 79849 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp492402vqo; Wed, 5 Apr 2023 11:00:27 -0700 (PDT) X-Google-Smtp-Source: AKy350btSg3EC6p9kROOtYZv7XTkHi/KNJYhmZ+il5BKVnEx8CC6/Y7Vh4b3sAkGnt3IlW6uEQYh X-Received: by 2002:a17:90b:1803:b0:233:ee50:d28b with SMTP id lw3-20020a17090b180300b00233ee50d28bmr7941622pjb.16.1680717626748; Wed, 05 Apr 2023 11:00:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717626; cv=none; d=google.com; s=arc-20160816; b=aRnjKv9PQe/MqkUAfTXQjnWqzkL3wLu3QO1Hnsv4omEk8/OQe+TB+BJQVNByBz+NnH 6OC78TlzfiZid2+8hHaD2B3mbcamtox8KnBehR+3sexuKxzSKY59q9doP2NT4kA1BTQv gvMq4xOmqpclEYFmjD22eSnqHijoKRdCGlh0aT7HkB17xhv4v6CgkRbvv4SfOcRbiqbc JU6Z86hIcBjYw8oxPRv5cIv9QQV5uKsZGduvBId1SJ4/BUuVobLtO8IZq7VmEQnErFcO KlFD8vUE41OyQG8tnfwIWCg5DRjtqBzONNpP8bygG7yfpSoswVuB6FHe7miikY4eUB78 AtaQ== 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=NWfXCnCRLHGCdfIApvX9+B1Kyu8tR4YNh4ctx6G09S4=; b=ffOCbqWGRJgYS5YbCkm2qMTDQ9lCmI08/G55q5/DpEp8zJrbL6fivyXawqRcFng+i6 6UURxaBkUQFAqLiJBAsQreKHBSaQtKdEYicbSo9XDuc33R6SN88rvynqySc/0doVZBlb Z0s4nyrPLPmkm+QGWEFtl+wgjF35+gZ3B0XKO7UK1GubnWXEK8Ty+wbYrJbv+XqmkgDO ZhiF/qsEHgJ/42EqCNZUtbljShEWp3mYt6CkZ/MF2RSAUB3Io0WcAuBgnOOg6vSIsppQ KlnAfuYyuI5qTtycZFerpepRcOST9mCrsA1lQvQuUNF+DpYXKhHdkDK59rk2FdGAV3hx LUXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="Ka/svnAH"; 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 oj16-20020a17090b4d9000b0023f37b648d9si1805807pjb.157.2023.04.05.11.00.11; Wed, 05 Apr 2023 11:00:26 -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="Ka/svnAH"; 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 S231393AbjDERwE (ORCPT + 99 others); Wed, 5 Apr 2023 13:52:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231564AbjDERwA (ORCPT ); Wed, 5 Apr 2023 13:52:00 -0400 Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com [IPv6:2607:f8b0:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B2516591; Wed, 5 Apr 2023 10:51:59 -0700 (PDT) Received: by mail-oi1-x22f.google.com with SMTP id b19so27233463oib.7; Wed, 05 Apr 2023 10:51:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717119; 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=NWfXCnCRLHGCdfIApvX9+B1Kyu8tR4YNh4ctx6G09S4=; b=Ka/svnAHZR+5faSaZQK9uR5ULlK+zzKrSaBtJLoNuMfsdOw62K8ztnFxbZ5NRtbVQF ul/Ju8isfNSoJoiVnkLcQGZ9VuOo6vWfcuFnwJkvlGOpsKn4pi/zHS7Djb4dxn5ywYBR UYwaItHimsDc4HSyx+7DYUyHP2kcC9sRClOjJPTknmW4mFoCeuK8mpb6B4yjljM/9N/F 1Q9vZvaMxsj/7a/W7kzBnvKsAt1n4EaETqIQkzJ0JD8ncpRvcHE6aLBsPp1rj1z4z7Bx FJ+CRsDRm60NgahLiPMhD4Qk3xam8KHE162pHCjU3jieBlwiizeY7mF0Miw0VZepD2aM mAFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717119; 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=NWfXCnCRLHGCdfIApvX9+B1Kyu8tR4YNh4ctx6G09S4=; b=G1a61ZhOFZEWJ0vdnSR3K2/U5GoNDRY5aFF/LSIQThqJm5ldDzIinOBfVnN3ZVNAoo 0ZCFKcPlasLQEpMXQWffmnDlMmaG68Q8kssnXGaka5kB3eFYqyzCxl9Pq6EUNHLtgMFr kQkARr6LXkxSbHm8QI5V8mwATbDxHTMf/DeH85mfjl2tZk7XUgdC3O3WQMuf2mfWY296 qttj6gFZ0v7VFEzPe3IAiDiq/BLq/PgKTO9dhJYkg6CkqoqIg+yvWxxTMvAL6wgnF2IW O/eHGoi8sMGvcQdmlKyj9KdP7UFUVNMIOql309tb6hv5huCFAw2SzzNd15VjqkhjmLH0 BLWw== X-Gm-Message-State: AAQBX9df6QFP5/Rw+y1D3hG+hpwGBn6Mw368qCjmXENWu5JQAI56dVeI n4+XfEKCa6mYZ73Mz18OAL7HNsZw4W5nEg== X-Received: by 2002:a05:6808:2b02:b0:384:118f:f9c5 with SMTP id fe2-20020a0568082b0200b00384118ff9c5mr3120794oib.25.1680717118868; Wed, 05 Apr 2023 10:51:58 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.51.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:51:58 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v2 04/13] locking/spinlock: introduce spin_lock_init_with_key Date: Wed, 5 Apr 2023 14:51:02 -0300 Message-Id: <20230405175111.5974-4-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360166147644312?= X-GMAIL-MSGID: =?utf-8?q?1762360166147644312?= From: Wedson Almeida Filho Rust cannot call C macros, so it has its own macro to create a new lock class when a spin lock is initialised. This new function allows Rust code to pass the lock class it generates to the C implementation. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho --- v1 -> v2: 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 Wed Apr 5 17:51:03 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: 79843 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489250vqo; Wed, 5 Apr 2023 10:53:53 -0700 (PDT) X-Google-Smtp-Source: AKy350bWQ0H35g44SiqSWNPgKUY0yrjHOQdxF2aOoF8n+AgINBRNcqeSU/NbHNbU826EfonvpP52 X-Received: by 2002:a17:906:7e49:b0:930:28d6:4581 with SMTP id z9-20020a1709067e4900b0093028d64581mr3571222ejr.59.1680717233400; Wed, 05 Apr 2023 10:53:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717233; cv=none; d=google.com; s=arc-20160816; b=sROe1o8byoZvvGHV/WsqWERjWdW4Im1NK4n5F2u+WUQ5VdXZW9ko6pvyKljw/K2ciQ vFNuG1IyBwMLysOO8D89jqtabNgzJN7zTMFC4pC9o9/EfBKKJdH0VW5DuOt4XYIjy11z CN9tBJUabunSwP+/6pjbkNlchY1mDVzflc/BrvG/hq5k3iWL0tJQSrBCxo5D34iMDJLH xfbyUm8KqynYRnxCfLvJCt5/7b4cMzaCKrhjRRy7Gn9kQhfsSCxREZ89XcVrw6MTqQgs JM07Dg3QovIpiwpeMfzItF22H012yzF9/9SoBAWo3HkbbW0yTM/Szxpfb633SZM9qoRS JrJA== 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=Rc5vjhZEE+1JaJ4UEjyTi+WD/ZvoFrZiKdNDQzYgVUE=; b=VIdi8EDBoWLs5htFmESPXb7AzhSUWn5iFoqEtJWJSUx+iPqe+B9f0E17gT2pB29FzG QCotcwbxa56T4oSxBcsId4A6h9CkAHYGWx/9/38fyUUl3KLYcq7wu303V5/Y+kFWKYxo txZPxPDaZvKjLkc9XqLF7JE7MGe+37c7TaOE6bgupJ2F+1nFa0oZ0FrjxFrG/G8fb5zM X5aH2kLd3qO/oOc2MXqiv38iZ2gijuHE3PQoE6vNticjhPcd6zcyLKoMGzg3FK6Ars4I EvdYY1iNtKByAstClvR2EtnovUPH306ckm43shzDxCkhcBaGegboeu1cft3jfhzcYoKB Ex4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="j/E0lBnN"; 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 z13-20020a170906814d00b00939f6198089si11373755ejw.859.2023.04.05.10.53.29; Wed, 05 Apr 2023 10:53:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="j/E0lBnN"; 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 S232400AbjDERwQ (ORCPT + 99 others); Wed, 5 Apr 2023 13:52:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38952 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232224AbjDERwL (ORCPT ); Wed, 5 Apr 2023 13:52:11 -0400 Received: from mail-oi1-x235.google.com (mail-oi1-x235.google.com [IPv6:2607:f8b0:4864:20::235]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 05583729F; Wed, 5 Apr 2023 10:52:04 -0700 (PDT) Received: by mail-oi1-x235.google.com with SMTP id bi31so27219302oib.9; Wed, 05 Apr 2023 10:52:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717124; 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=Rc5vjhZEE+1JaJ4UEjyTi+WD/ZvoFrZiKdNDQzYgVUE=; b=j/E0lBnN3bsNNdU6EfTb9bTo+6dfMsVCWvhvg/Jv1LGwm77sY12q+idQBNN98xPCfc Ms1D+qiPvYQMBMy0HPe+wXIBo4deBoopUtZ1vGzUcP4Omoa1+0568ay9+lrL8aj5f/Yn rpA8qEOuGnGstfHQKNwsVWzkdirj1+eJA8UbOJgp37Mk20XaiQKXfVxj8ajgiFcztxDI tS/o0qi/oZnWuUv3KQR+9HIWdRkhs66slyVID4XKC7TbFb42zx1xiNRIWRqqX7foP6h3 jzuvQK68oGdMH0DWH24Pg4IpD+5DnOFRMf1b3zQ1FbJRrOrmGd3IQ9OldNCX66AJR/GV hceQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717124; 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=Rc5vjhZEE+1JaJ4UEjyTi+WD/ZvoFrZiKdNDQzYgVUE=; b=viCRDQG7a4XDwkrq7jnxWkNVjHRvxbLxa1BXESWnxQf8PD3zxxmx9djS5w0CBn4Axk aVn2jIHst3FWQQxKucnWUI5Pk1qhF/uAllyHnhuLoP6OiqSK6h3vnmiculhoHPMuVVrj YZ+/csf/19l+Te3JCQaf/ys7jzILTLd/gjZy507+6P++xUdKvAVZh1Spx5LkJ0KvE57B zmaQn++LR6Ogj2zkaA9sGlGCp7zw+2kLqjDsJl/matm94qU+K9DOpCcIoHYQrGET86xy w0waYWxaOGIZvjbM9yMLHVLon+Z7f8BgI4uPn2wyU3RzGkdDOZQvaFMTqPyibjGBKyM0 b2nA== X-Gm-Message-State: AAQBX9c3EczyhjwVpXQ+Csex/17vjH0R7DzwqPW3266CLgmcwxWEpnp0 egwUZ2ifuRz6qq3XAKhiI/G1R2QgjlLE4Q== X-Received: by 2002:a05:6808:179d:b0:378:a144:f7ad with SMTP id bg29-20020a056808179d00b00378a144f7admr1777799oib.17.1680717123367; Wed, 05 Apr 2023 10:52:03 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.51.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:03 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v2 05/13] rust: lock: introduce `SpinLock` Date: Wed, 5 Apr 2023 14:51:03 -0300 Message-Id: <20230405175111.5974-5-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762359753719251347?= X-GMAIL-MSGID: =?utf-8?q?1762359753719251347?= From: Wedson Almeida Filho This is the `spinlock_t` lock backend and allows Rust code to use the kernel spinlock idiomatically. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes rust/helpers.c | 24 +++++++ rust/kernel/sync.rs | 2 +- rust/kernel/sync/lock.rs | 1 + rust/kernel/sync/lock/spinlock.rs | 116 ++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/lock/spinlock.rs diff --git a/rust/helpers.c b/rust/helpers.c index 3010a2ec26e2..05694e3f8f70 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -22,6 +22,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -35,6 +36,29 @@ void rust_helper_mutex_lock(struct mutex *lock) } EXPORT_SYMBOL_GPL(rust_helper_mutex_lock); +void rust_helper___spin_lock_init(spinlock_t *lock, const char *name, + struct lock_class_key *key) +{ +#ifdef CONFIG_DEBUG_SPINLOCK + spin_lock_init_with_key(lock, name, key); +#else + spin_lock_init(lock); +#endif +} +EXPORT_SYMBOL_GPL(rust_helper___spin_lock_init); + +void rust_helper_spin_lock(spinlock_t *lock) +{ + spin_lock(lock); +} +EXPORT_SYMBOL_GPL(rust_helper_spin_lock); + +void rust_helper_spin_unlock(spinlock_t *lock) +{ + spin_unlock(lock); +} +EXPORT_SYMBOL_GPL(rust_helper_spin_unlock); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index 9ff116b2eebe..ed07437d7d55 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 cec1d68bab86..bca9af2a9a5a 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 Wed Apr 5 17:51:04 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: 79852 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp494334vqo; Wed, 5 Apr 2023 11:02:38 -0700 (PDT) X-Google-Smtp-Source: AKy350aOcwXEPxkeIv9SnkexUWHRo9dvWEEE69s4P7uC4A2rfPaKbig5nJk3urDu7K5AizhwmAhT X-Received: by 2002:a17:90b:33cf:b0:23e:fa90:ba34 with SMTP id lk15-20020a17090b33cf00b0023efa90ba34mr8083747pjb.37.1680717758621; Wed, 05 Apr 2023 11:02:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717758; cv=none; d=google.com; s=arc-20160816; b=tBBqQzcBGyZ0rCVJCGx1yAQVVAU5rSOD8TANv6RCnAz3TnsVpzgjtycg4f77r59xF1 G/xbVawnFGa7tDPrIgQajU7dkLhLZhxVKuPi6x6Bq4WizGjXA8uDiT3wrO0OGJQ3bFxm HtWYV9c0r+C7DtpyhJSwxMsrb3jkPs2UAuoeHZJfa4RheqZLKMU/sNLauS5aKdOHZ2/y TReKj6pSIY+2FrlGGx80CJ4gp55Yj7KtRE9UyfFFp8WqhlJZSdK9lflNHuYSv1VPhZah c1CepmWl5f1YuP+Fyc1Vtn4SDqWK6Rdrpp0WM1hlwYELkYY4wBIfYwWksmOMkpUwIFBB qktQ== 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=sG++w8NyFtmU3a0MKdVasgEDSXcDlxmofOYd/dEc4Vg=; b=RVFhTqzNrJoVUHyiHE1Y1AkwEttk/g5a6JRhhSg9vy2Aq564RXBOoPZJ0UCPDp6z7H tN38hBlwL0Lm63fZt1Hgm7KLBTxgbA6tc+WbHvKDm113+pgnG78ZTIzDKGBid2/RljM/ YC15A+g5oYx0xJGCTmCnir/6uKQpB+uPMXyyyloTwKP6fQrQk9ZurW0gm+tEHbrvLMZJ mzOzdy8U2jj1Ycw9NPkK/JkEnu1HF7jGLq9KSp+XmLR58CNIKxgpXOaKW2oxlIi6aP5n BmyZNHL3X0Wi2YzWszDjEDRtS5SvqYCb2ih3xCbN2NW11cZaWj566FHZTKcElRqh2P7V mfvQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=MqTYpyAJ; 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 f1-20020a17090a700100b0023cff9a12a3si1817391pjk.50.2023.04.05.11.02.13; Wed, 05 Apr 2023 11:02:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=MqTYpyAJ; 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 S232224AbjDERwT (ORCPT + 99 others); Wed, 5 Apr 2023 13:52:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38554 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232079AbjDERwR (ORCPT ); Wed, 5 Apr 2023 13:52:17 -0400 Received: from mail-oi1-x22f.google.com (mail-oi1-x22f.google.com [IPv6:2607:f8b0:4864:20::22f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6CCD065B2; Wed, 5 Apr 2023 10:52:07 -0700 (PDT) Received: by mail-oi1-x22f.google.com with SMTP id b19so27233751oib.7; Wed, 05 Apr 2023 10:52:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717127; 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=sG++w8NyFtmU3a0MKdVasgEDSXcDlxmofOYd/dEc4Vg=; b=MqTYpyAJ0uiRFQpxjXrrJm0DoawAd2L4V+h9dx2IhPXHokDFQ0nQosHQrSNLNNW3Eo z6vOY/TRmvjtzI7nD3AwKa5mBy6xN/VvLktI8E9nNvDXCz3+qXze8p7iPC58i+w/b0rW 9p22SV0DtBbtIIR3fzf+hccTgSsXyL/zSTXAiwTB/IsjVP/B5GXSdIDlA+AmO95Eoj6q Sa0vO6fEis4pZtAOdFCznr26WIZKeiuBgO4d0djF6daQDx9iNyhlq3glL+VObxTbTCxo RbG3upqiyIosE7AUb3Jj7xmC5ZlygF9XB3nRF2icOXCgN3egsgfWWb2lxxGBzviR+Qbr ZylA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717127; 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=sG++w8NyFtmU3a0MKdVasgEDSXcDlxmofOYd/dEc4Vg=; b=FzQyGyLQsXhFsa9e8lbdlN8dRloXb5BzP7j320LC76xrszOSrxM030Xift10+jKNoc QWYlGaaDPt54fH2E9++lA2OjgfxXXp2ZeaKH6lSfX+pGSXlLI3Sqj5PRIDSPT8bImoq8 7U+kspqGt7qPY8h03ZFq/aMQsi8p2rkwfBguLgoSczZnpWLx+CDJwvlOnHqKzgDFPWkm PhC65svNUrrAA0eur0iB5GrXYqVpUIXqZHr1a6HuTQCPAGI+Kiy4Su0C8Ju8qZX5OUN4 D9gOd9l1SRBuqj20IzVzdaBA/sUx7KgwJ6CkadRf9WfQxAFtFxWWZXz+MzAkRVGW8jJN Xjfw== X-Gm-Message-State: AAQBX9fSLUGjbgdFTTQrVYpHFBYU/wLaNgcGl0eIgARC96h/w+MxHC/h a4wI87XRZsa3o4MYih1ipZIiObOpFc8= X-Received: by 2002:aca:1e0b:0:b0:387:2075:59b with SMTP id m11-20020aca1e0b000000b003872075059bmr2901893oic.24.1680717127067; Wed, 05 Apr 2023 10:52:07 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:06 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 06/13] rust: lock: add support for `Lock::lock_irqsave` Date: Wed, 5 Apr 2023 14:51:04 -0300 Message-Id: <20230405175111.5974-6-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360304508364228?= X-GMAIL-MSGID: =?utf-8?q?1762360304508364228?= From: Wedson Almeida Filho This allows locks like spinlocks and raw spinlocks to expose a `lock_irqsave` variant in Rust that corresponds to the C version. Signed-off-by: Wedson Almeida Filho --- v1 -> v2: 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 bca9af2a9a5a..491446c3a074 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 @@ -109,6 +132,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 Wed Apr 5 17:51:05 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: 79848 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp491937vqo; Wed, 5 Apr 2023 10:59:54 -0700 (PDT) X-Google-Smtp-Source: AKy350Y2fOjl+37Qi27oAuzHgz3kaU3qlIdnHEYNzg5Q0LuiyvUBYLzqVDaZwTGZkh8uNNdbB44z X-Received: by 2002:a17:90b:33d1:b0:23f:7dfb:7dc1 with SMTP id lk17-20020a17090b33d100b0023f7dfb7dc1mr7799289pjb.33.1680717594309; Wed, 05 Apr 2023 10:59:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717594; cv=none; d=google.com; s=arc-20160816; b=In3OmT5y9S1qVo29eJey1clWprTOM9hZJuSlFELewLXuqY8EXT5XPvfMx97/Y1DuVr IXAXLrVMgcOlseGChV096aeNE+mief9b6dFk07h0ScDZYkZuCdow909IINcFlm1A4Zfu GBumCxvwnyGxrxvoW+b28k76VUbLP9L2bk07fhmx9hFDAo2sosv0T/U3YyE7G0IoTaUi 9DaGuBjk55BOgKMM+niYdQf5YN05P2+41LvpxZp4gF66ooHFJ2vgl9ShXIL8LnTvj9ft NCWm3lCtYPHa3GIk6cEVHh77V4IBEgxIfsKwKoR3JTyeUYmqo9VNr1l6x3MgGCSGVHCU px/w== 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=thG4ce95lzXfSBdJf4lBPCfVabPBzlVobrhWMpvttHs=; b=gDeKNJgKQI6+oSnJKKQ5P6AVnPi8FjLtBVBXwOltE7Y8DTPHHVOhFQh4lvRsBDLopW y/37Rbcsw9FNU6nHUoBEb0RRVfrslZ8zHrLLxAmzsU5ORuMGpPfzctrqU8FbDpblniqq SlSwmTA7iYO8fpVUfUPKv37wAoH48iVPQUgnuzf+YFnkVzKNID09GkPXjj/fJis2JOAa KESErDS/8Z9I3Q8PPVlrrnuXg9tHB0euk5DCheZDdYFcbseZJGHU/Cgpr08smnqrPwSA InMnz4B1dYyc8IGnnigINP2TFIbxswapgjddRrVPJQe7u2q5PFJX7w+o97NAcxPqXsm1 8DTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="qNK/SIs8"; 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 l1-20020a17090a4d4100b0023f064f20c7si1738705pjh.168.2023.04.05.10.59.41; Wed, 05 Apr 2023 10:59:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="qNK/SIs8"; 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 S232442AbjDERwi (ORCPT + 99 others); Wed, 5 Apr 2023 13:52:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232695AbjDERwd (ORCPT ); Wed, 5 Apr 2023 13:52:33 -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 D4F156E80; Wed, 5 Apr 2023 10:52:13 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id l18so27219028oic.13; Wed, 05 Apr 2023 10:52:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717132; 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=thG4ce95lzXfSBdJf4lBPCfVabPBzlVobrhWMpvttHs=; b=qNK/SIs8M2jkyqqxmQ/DCMtwbI3QSDnkF3limYjePtyO/x9fvjArvFmaUqnP8K82al J59iGA8rz000+AE2sTr833F6LQZCsP0AU+WDnCa6bRmIyXxGU+TUqu7B5cktKmX9CLWI +AjdbgvgkVxM8FeffK+8F9+jvCy4h/93U3OXXQT9ZiIIc8DBqaAHWfBS6Dj/c6VELm7z K7GSBgA7PBQiBmpRdHnI2Yy624mTwD3fM/yoTGvOIRhLeX3likGXqsol34v6OmkDik4a 2qOFM/9dzHZZ696M/gszpspo/GZ4oA3yM+17Vzm697Ao3O+YpZtZ33YLeFprLtfhI5sI F92w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717132; 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=thG4ce95lzXfSBdJf4lBPCfVabPBzlVobrhWMpvttHs=; b=QU3jkvQruUTq8RLwPpFHEhFpV5iMbK1Lj8VH7foSRehvx4WCqTfq53oKkvhLOWu9ep RO8bqllkRleVtP2rkvLAIW+vxCWyHOA3GZ9JfRMPWhtaFEle9POSyHTzpatLnBIuTevb 5cgbaHVkfpPgFEtVDHCKp9bkno+CiOjRIEfJygsQfgXKPwN8udlMAZ99E5SwT16Wl3+V SQ+jI6Lcghhq75Uvx2Ta2KfQs2XG90Cw6WUrWFuoF2ppzoCfSwiRDbTxYi9oIc3k9S1V 6mUXuYZsEAzH7i9JiC+rouzWQanfpDRwvEMWjRVpJqc2AlgBZNXy15/yNNHl/PSxvULZ PcxQ== X-Gm-Message-State: AAQBX9cr7OiUSP6bM0Q0DMtBY2eMe3tyWbQ5kwvw32BkHeRNOcw/0HsB G0Uz9oMdmYcle8YQ3WCZ1Ei3WNZ7pWYIIQ== X-Received: by 2002:a05:6808:2018:b0:384:8a1:c14b with SMTP id q24-20020a056808201800b0038408a1c14bmr4182868oiw.31.1680717132470; Wed, 05 Apr 2023 10:52:12 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52: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 Subject: [PATCH v2 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Date: Wed, 5 Apr 2023 14:51:05 -0300 Message-Id: <20230405175111.5974-7-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360132378291296?= X-GMAIL-MSGID: =?utf-8?q?1762360132378291296?= From: Wedson Almeida Filho This allows Rust code to use the `lock_irqsave` variant of spinlocks. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes rust/helpers.c | 16 +++++++++++++ rust/kernel/sync/lock/spinlock.rs | 38 ++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/rust/helpers.c b/rust/helpers.c index 05694e3f8f70..e42f5b446f92 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -59,6 +59,22 @@ void rust_helper_spin_unlock(spinlock_t *lock) } EXPORT_SYMBOL_GPL(rust_helper_spin_unlock); +unsigned long rust_helper_spin_lock_irqsave(spinlock_t *lock) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + + return flags; +} +EXPORT_SYMBOL_GPL(rust_helper_spin_lock_irqsave); + +void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) +{ + spin_unlock_irqrestore(lock, flags); +} +EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs index a52d20fc9755..34dec09a97c0 100644 --- a/rust/kernel/sync/lock/spinlock.rs +++ b/rust/kernel/sync/lock/spinlock.rs @@ -61,6 +61,8 @@ macro_rules! new_spinlock { /// assert_eq!(e.c, 10); /// assert_eq!(e.d.lock().a, 20); /// assert_eq!(e.d.lock().b, 30); +/// assert_eq!(e.d.lock_irqsave().a, 20); +/// assert_eq!(e.d.lock_irqsave().b, 30); /// ``` /// /// The following example shows how to use interior mutability to modify the contents of a struct @@ -79,6 +81,12 @@ macro_rules! new_spinlock { /// guard.a += 10; /// guard.b += 20; /// } +/// +/// fn example2(m: &SpinLock) { +/// let mut guard = m.lock_irqsave(); +/// guard.a += 10; +/// guard.b += 20; +/// } /// ``` /// /// [`spinlock_t`]: ../../../../include/linux/spinlock.h @@ -90,7 +98,7 @@ pub struct SpinLockBackend; // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. unsafe impl super::Backend for SpinLockBackend { type State = bindings::spinlock_t; - type GuardState = (); + type GuardState = Option; unsafe fn init( ptr: *mut Self::State, @@ -105,12 +113,30 @@ unsafe impl super::Backend for SpinLockBackend { unsafe fn lock(ptr: *mut Self::State) -> Self::GuardState { // SAFETY: The safety requirements of this function ensure that `ptr` points to valid // memory, and that it has been initialised before. - unsafe { bindings::spin_lock(ptr) } + unsafe { bindings::spin_lock(ptr) }; + None } - unsafe fn unlock(ptr: *mut Self::State, _guard_state: &Self::GuardState) { - // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that the - // caller is the owner of the mutex. - unsafe { bindings::spin_unlock(ptr) } + unsafe fn unlock(ptr: *mut Self::State, guard_state: &Self::GuardState) { + match guard_state { + // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that + // the caller is the owner of the mutex. + Some(flags) => unsafe { bindings::spin_unlock_irqrestore(ptr, *flags) }, + // SAFETY: The safety requirements of this function ensure that `ptr` is valid and that + // the caller is the owner of the mutex. + None => unsafe { bindings::spin_unlock(ptr) }, + } + } +} + +// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion. We use the `irqsave` +// variant of the C lock acquisition functions to disable interrupts and retrieve the original +// interrupt state, and the `irqrestore` variant of the lock release functions to restore the state +// in `unlock` -- we use the guard context to determine which method was used to acquire the lock. +unsafe impl super::IrqSaveBackend for SpinLockBackend { + unsafe fn lock_irqsave(ptr: *mut Self::State) -> Self::GuardState { + // SAFETY: The safety requirements of this function ensure that `ptr` points to valid + // memory, and that it has been initialised before. + Some(unsafe { bindings::spin_lock_irqsave(ptr) }) } } From patchwork Wed Apr 5 17:51:06 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: 79842 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489199vqo; Wed, 5 Apr 2023 10:53:48 -0700 (PDT) X-Google-Smtp-Source: AKy350bdjmWLqzpHZPN6jhp6F/BMM00SlA/0osR6MlvX9x+lalt+vbagUoVBLk1oIpCOFSth021I X-Received: by 2002:a17:90b:1b03:b0:240:d275:d61b with SMTP id nu3-20020a17090b1b0300b00240d275d61bmr7457496pjb.36.1680717227874; Wed, 05 Apr 2023 10:53:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717227; cv=none; d=google.com; s=arc-20160816; b=dSmPboEQjafWtI9kq6sX8Y5Po+afnNBwcWCZhk3LvsC0LkFQUfjzZXXymk8ny3C+pf mB0FQw/LXgIm0zfXpPhUM5CAfASEZpz9gugv1n6aGbevhDhvoL47QD9eo3z0IVex6XpP +lC/UyMwiLMLg3Idkvzk5D1SGVosLAxEjTJL+eFYShmThyaio2e5+ZNWMzDvaLr1xijj xGmyrsPYPzJut/lPbtcI4pec5jUNnBX8bN0A1gNgY0/q05y/ke7pRrqruVJUX6midUDi 83j7fMi1UBVhNnbwKWJ6Xs17ds2OM+9l753YhfElJa//6uAK+8MpoXJZnzjMDS+m0SgD g5ag== 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=yDKrcsZh/wP/lITy5QMY3W9uqlt+ywEoUOGYJrXbNMY=; b=J8MtjNVhR8Rv3ely2Ts2z28JSfpLK2DXDEZrmVMc/TWPl89oYLCLIDzcx6x4Oj1OTD 40O3VaQyFc2el8mZA6cC6LJzTvJpCIXKt8O3pwb45HE/MEd0yDPmFJypSrBBnA4K9ouh PzgvRoG/Q3fg1Ls5rwGzaTphFDIQCyyWzHSPCLWlFZZIn/zt/g97MIHo/jfTDMq+QCxK U0pxQlaiXlD2PjD8p5lNIGoXszJ7mI2uLqh8Nt/M7EJHa8uU9P9H2Bon4zvZfrPnkRDY aiYzWblgbcAatZh89xviyERsv+Z0rep+fUIV0txHXg7Az1/I1PshOQxsGkQtTIv9lGe7 TmTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="B/OTciN2"; 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 k7-20020a634b47000000b005139e210d10si12496680pgl.587.2023.04.05.10.53.35; Wed, 05 Apr 2023 10:53:47 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="B/OTciN2"; 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 S232695AbjDERwt (ORCPT + 99 others); Wed, 5 Apr 2023 13:52:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40050 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232079AbjDERwr (ORCPT ); Wed, 5 Apr 2023 13:52:47 -0400 Received: from mail-oi1-x235.google.com (mail-oi1-x235.google.com [IPv6:2607:f8b0:4864:20::235]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9EE4A729F; Wed, 5 Apr 2023 10:52:19 -0700 (PDT) Received: by mail-oi1-x235.google.com with SMTP id y184so27232254oiy.8; Wed, 05 Apr 2023 10:52:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717138; 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=yDKrcsZh/wP/lITy5QMY3W9uqlt+ywEoUOGYJrXbNMY=; b=B/OTciN28kbRHCwGguPcjRZzHoK8qkWPrMjQOltw7nWygfMtMu8Fq3RBOlurtP5vIo cD5ZIDTTmI9fUJGEWt1e/oEQuKOFJEuM0RT9GqGRHPrsJhBnxEMsw0ymiqqAo1WKEmb1 BtPyexqr5J6zBpeCCmo2XosylDfOCLH1G7aTdxJ9TjdBfRFrZNJkl7I+1n6zFaRJ437Q wVgX9fwX0Kg5lgJ6sH24X3XaZ4GNNbGcb3wstSU7fbv6woY5MgnOOmgz3i96fPY3IoCL a2TXs3XSh38D3ybYh9rPZi+OX1UG6EjKHfIkdU4vXA9JV4iIurUSS2fDghs/+dNabLmK 0ePw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717138; 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=yDKrcsZh/wP/lITy5QMY3W9uqlt+ywEoUOGYJrXbNMY=; b=FamiMgBgYvLQoFWSPtFD1QyjnuY0OYo6I1o1bIykIRN2HGJsXKJ+j7JuYt5dopYHuI 8KxZhmr/UD7UHgxgDJWGrfpRsnz3D7DuiMkAkO6Q3e4pNy2lJxHZTzusARtjweUzxt5f zc+GVa74Ab3l/qi846CJp+26qicD8iyOR+lYMRjFJ1nXJBz3dl/CTsZLTV4UaHWMo7Vx eR7D+R5rTxWTmHBn1hFm1/dYR6Ya4JyJfnvBZCw4VbDnzp1rv5CIJhtIh+dZQd4IFQlx K8rU7kToYcm4Tj27WzpnlA6EmzZlVoLjm9Mv7mi5TWoYcO7L9qXulCZWMU/emCoxQ9Ec 721g== X-Gm-Message-State: AAQBX9camDSVcm1mdbMfZfGXbkUKHtY4KBfUxCEoJX4FZqGjs44wSXeY hIAfZrN7DEbl1F+O7Go65jEghX+nFkI= X-Received: by 2002:aca:2210:0:b0:386:9873:d377 with SMTP id b16-20020aca2210000000b003869873d377mr2780365oic.56.1680717137736; Wed, 05 Apr 2023 10:52:17 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:17 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 08/13] rust: introduce `ARef` Date: Wed, 5 Apr 2023 14:51:06 -0300 Message-Id: <20230405175111.5974-8-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762359747877136151?= X-GMAIL-MSGID: =?utf-8?q?1762359747877136151?= From: Wedson Almeida Filho This is an owned reference to an object that is always ref-counted. This is meant to be used in wrappers for C types that have their own ref counting functions, for example, tasks, files, inodes, dentries, etc. Signed-off-by: Wedson Almeida Filho --- v1 -> v2: 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 dbfae9bb97ce..b071730253c7 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. @@ -295,6 +297,111 @@ opaque_init_funcs! { "Rust" manual_init4(arg1: A1, arg2: A2, arg3: A3, arg4: A4); } +/// 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 Wed Apr 5 17:51:07 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: 79845 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489618vqo; Wed, 5 Apr 2023 10:54:37 -0700 (PDT) X-Google-Smtp-Source: AKy350bSrJ5ceDMUmR9WLr8Cimig8c8cQuJPMAqy1moxxLtWHgKM+562UK682iFti0zP1PbeDTyh X-Received: by 2002:a17:906:da11:b0:878:7c18:8fd9 with SMTP id fi17-20020a170906da1100b008787c188fd9mr3341136ejb.44.1680717277718; Wed, 05 Apr 2023 10:54:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717277; cv=none; d=google.com; s=arc-20160816; b=oSeyTtCs5f0Jnpkexoi3byE0JZOqmYA020OeS9Ybexo5WQ8atDFvAArkhma7iZZNSR Yx43kOkY583KO4n7ftfszC/PSFobpM1BhemygL8kXKubhBpbuQUEQw5tudZ+sHj+TeTh H7pI3h5Svhn90P5D/TNwvhxknpSJODUcmOJzH193T9Mea47QKX0TVDBm/SIKrS2V3/5G b1B2ItMe3/CFUqMRXdWpYpItWTiuJRlwUZq7WrjmKo83m9undTIH2oLH5qj8UPy0CHXh cpNeVuByrSDI+J1iwVTpyUf7xrM9hMXlTWcrc+md6yJbeVVwdDpQdG5rNe7nZlqKohys pMPg== 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=Uocgwe3402X+SGxBrEAOB8aX32adol5RFJ3Rm7rkR1M=; b=sQzDXEAzL44PD6tHcyrdAnPbOT19nrjugqWP6OE28qVRI6iiWHFYthiErKVROOjkzf o692d4nLI4Xlx5i4jD4yCKVhgOgTN71N1hZklqi4tM5J3Rb7+OwEJpxs8iKHE59qZGjy 0rFSYby+Hr81VOl+lzKYGAB5de8pvLEzSJi2VIhJsLD++iLtH6clAVWAsAE9z4SrtF2G EncSdAoirjCyJ3qjWKfkWy/qE8U3kuuK0A4iWjpFxR8Y1gqYhU8mYxySCzU+pfep6/gh maI9Uy4MRO+CxGJe5DFJyGwC2btspKJLVRAgxgR2c8AnDRRWfaGOiGzv9L4gBNh98DPy HiTA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=H3b5JZrX; 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 sc37-20020a1709078a2500b00947d54e4c1fsi1610575ejc.88.2023.04.05.10.54.13; Wed, 05 Apr 2023 10:54:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=H3b5JZrX; 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 S232116AbjDERxA (ORCPT + 99 others); Wed, 5 Apr 2023 13:53:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233100AbjDERw4 (ORCPT ); Wed, 5 Apr 2023 13:52:56 -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 10FB37A9E; Wed, 5 Apr 2023 10:52:24 -0700 (PDT) Received: by mail-oi1-x22e.google.com with SMTP id y184so27232400oiy.8; Wed, 05 Apr 2023 10:52:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717143; 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=Uocgwe3402X+SGxBrEAOB8aX32adol5RFJ3Rm7rkR1M=; b=H3b5JZrXjwVVxh77g6AfD4FgP2iz9QMuIN26A643ILL/PT2nI2gwzcwQ3aRhdCWr5h oMJdzkZ1ycexjNw/7i70b3yc7mqOAPNNWFVh4tNUyPb7o/SxmN4F7htwm3QHQnF8OhSM uoXh2V9/hpmkRz1aa28P+CDh9vDNRof/ZsLHCh/4amlnOlr1O7EtOUSK2PbTzraTBd1V F6QH83tfMRTdQ5To7gYPt0LKZq3XZC1Ty98eoZP9KfbxM3t94rbgOG9SV3W39n3dFHQx jK8ZUBaj8UZO/WCePVLvesyjnDWHSxB3jnWb7elRwj9r+HHCs8AWjS+pIAe1dWCQEgNI MGOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717143; 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=Uocgwe3402X+SGxBrEAOB8aX32adol5RFJ3Rm7rkR1M=; b=CfgFrD51/Hy+JNeEujlM+eeRnmOlj4VOw91m49F0pzhgoewT5cnLs2dxS96cO9YvWo 4cuAU6SvvoDY5/M5+zn0gIrDEeU5I+IMNuFqND3+fr8ZVmA7gojb9NJwLyHejOQpOVly +ZJRIChPD3opKjU6RCLKpB8jBzVaqF64LlXbTy6P8kUxfDK9SZ7Y5E0GiINJs7H+Cw6Z MPbbURDDg0a4RZeB+7WHSlmVwhZOtG9LOtb2ogMnzNC8FGINuA1RDqHum4nkUFAqRMR5 xxeHIVU9fbxw4Cend+Od+8ywdTnI1dyG30kJnKUtpH8uDFVAo+2eAfepPySj+ffezHaH CZ2A== X-Gm-Message-State: AAQBX9dE9QOzuw7M3P8V4HSBYuAssMAv/oTrvauoB5HYMSjTq2ul32p+ uQiicFRcu8OODxvkK1CujTVPXXJ2d4Ftgw== X-Received: by 2002:a05:6808:b39:b0:38b:6b17:f72a with SMTP id t25-20020a0568080b3900b0038b6b17f72amr892617oij.3.1680717141396; Wed, 05 Apr 2023 10:52:21 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:21 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Ingo Molnar , Peter Zijlstra Subject: [PATCH v2 09/13] rust: add basic `Task` Date: Wed, 5 Apr 2023 14:51:07 -0300 Message-Id: <20230405175111.5974-9-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762359800351986970?= X-GMAIL-MSGID: =?utf-8?q?1762359800351986970?= From: Wedson Almeida Filho It is an abstraction for C's `struct task_struct`. It implements `AlwaysRefCounted`, so the refcount of the wrapped object is managed safely on the Rust side. Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: Wedson Almeida Filho --- v1 -> v2: No changes rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 19 +++++++++ rust/kernel/lib.rs | 1 + rust/kernel/task.rs | 71 +++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 rust/kernel/task.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 75d85bd6c592..03656a44a83f 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -8,6 +8,7 @@ #include #include +#include /* `bindgen` gets confused at certain things. */ const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL; diff --git a/rust/helpers.c b/rust/helpers.c index e42f5b446f92..58a194042c86 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -23,6 +23,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -75,6 +76,12 @@ void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) } EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore); +int rust_helper_signal_pending(struct task_struct *t) +{ + return signal_pending(t); +} +EXPORT_SYMBOL_GPL(rust_helper_signal_pending); + refcount_t rust_helper_REFCOUNT_INIT(int n) { return (refcount_t)REFCOUNT_INIT(n); @@ -93,6 +100,18 @@ bool rust_helper_refcount_dec_and_test(refcount_t *r) } EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test); +void rust_helper_get_task_struct(struct task_struct *t) +{ + get_task_struct(t); +} +EXPORT_SYMBOL_GPL(rust_helper_get_task_struct); + +void rust_helper_put_task_struct(struct task_struct *t) +{ + put_task_struct(t); +} +EXPORT_SYMBOL_GPL(rust_helper_put_task_struct); + /* * We use `bindgen`'s `--size_t-is-usize` option to bind the C `size_t` type * as the Rust `usize` type, so we can use it in contexts where Rust diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index d9df77132fa2..4e1d5ba2e241 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -43,6 +43,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..8d7a8222990f --- /dev/null +++ b/rust/kernel/task.rs @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Tasks (threads and processes). +//! +//! C header: [`include/linux/sched.h`](../../../../include/linux/sched.h). + +use crate::bindings; +use core::{cell::UnsafeCell, ptr}; + +/// Wraps the kernel's `struct task_struct`. +/// +/// # Invariants +/// +/// 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) UnsafeCell); + +// 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 valid. + 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 valid. + 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 Wed Apr 5 17:51:08 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: 79844 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489468vqo; Wed, 5 Apr 2023 10:54:22 -0700 (PDT) X-Google-Smtp-Source: AKy350YZablawQfjWW4VmXj3DHdAJXrjffZRJLw1DHPKfHieLoRIX+fpxaDFwc+nKnXvcM1UCDBE X-Received: by 2002:a62:1cc6:0:b0:624:f46:7256 with SMTP id c189-20020a621cc6000000b006240f467256mr6944752pfc.21.1680717262045; Wed, 05 Apr 2023 10:54:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717262; cv=none; d=google.com; s=arc-20160816; b=MQx6yeKxM5NsDwOI/hWSpnu5+WzGZ6R/QYPZKevhd2jJklxbS74cYo1eZthP4y4q7v M/uHSStBkxQ6nIGelub7yR1TW00GUnEHxAQN8c+a5w87fx9kO7EIs99O827+CRoJZ+l0 lXao5MFI4LBMrfP0F077vsSSvMFb6EQw6q+GAgMPkWFj9yaaO7Tk2nDvRV8664SEM9sk A7mifkqkxkeXlhbPtFNZGJB53B4nIcm7p1Cv8BQBUs+E9oP2H4ukx/MVZ/zqvoMVSj6K bK205hNt7OkDJM1qrwUqqUd87aQPCjPSmX16S4hb25KFGskhiJIBYPwEQ3c/cKNUDUzu JMgw== 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=vJPRX95Pq0TPwhRdP2GRuAB3gcXMGchPHxgINwURD70=; b=rv2NFaBrLUf01vvAjGMoawK9Ni6j3N+iOjho3cwEBFb4qHCpii383n3iFmnPCMEW2I Dx6QouTfYjqyCxV4tYtt9XSjFZCRe67koqU57SPhpLp1LC652T1WmM5gZ+TzRHNznRdg WUacyjgFriQ7PDIqRFKkRHoIOVqskqajUP/AoND0r5j0i1adzIkQJ7cvC3mdLi0g0Tx7 PqQpej2Lfu605Q75Yrdvrs8IgMu1IllRQ/DsRs9Kq8VWnxLA2o6aaEJAlVND+AmC3ueh oCEoPXNgaIdMQHl39EimKUoaH0kHtjbioPsdLusTerBNCnHxOnmSzNpC+4+62eNG1w2f mjZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=hcKVIzrs; 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 y14-20020a655a0e000000b0050be1da8e95si12784952pgs.439.2023.04.05.10.54.10; Wed, 05 Apr 2023 10:54:22 -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=hcKVIzrs; 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 S233567AbjDERxD (ORCPT + 99 others); Wed, 5 Apr 2023 13:53:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40612 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233419AbjDERw6 (ORCPT ); Wed, 5 Apr 2023 13:52:58 -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 C48F376AC; Wed, 5 Apr 2023 10:52:30 -0700 (PDT) Received: by mail-oi1-x22a.google.com with SMTP id bx42so11690410oib.6; Wed, 05 Apr 2023 10:52:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717147; 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=vJPRX95Pq0TPwhRdP2GRuAB3gcXMGchPHxgINwURD70=; b=hcKVIzrsNxzcyWyQf/GJBa0U2oqIb+9tCiQ2N3+Gt4CzgZj4djzw1r4pq5cDTkV+Sn XV14zBPb5qClEkqMH00ekiQFqOt9R799k+4ze4R3d5p5fxEU4+UGvzpyy5z4blw+YFPB jx5vRS2v5voiSjdVa/N2bKcLkPUKme1JC09aqhDe7MNf090ssEq4pIfPQ06skJaockXP GqU73gwUERq1Q6jOSibsJ5LTTBRR4DGKvqRpOoAfz+JhBsxLgHYOs2aWRKuONsnO7HgA cs7VjowL5kbcL4qXwfms+Rb0IHl2T3ouS9D78dYWl2c6BkKccwh/LekLK46E2xdoc5Zm rksA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717147; 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=vJPRX95Pq0TPwhRdP2GRuAB3gcXMGchPHxgINwURD70=; b=kU3YTdRonqCKT2dmi4Ma9yK6fLMUubC/Sl8TgwYuTQxGUOj3Im9JIO6rwZWQs+WPV5 H/C/lPXVhMOBRw1e+qleVGyaz+w/uD/T5ADz6icGKdYM30hzD4uIyd/O26h4gq9pxfjp zv5dV193u71t0BYo9sbVSL1SmbIOh8B4WDe2nnnkKpWiKh/pAXDoEoRFUNv4NOPdgww+ ddryOlH8hQjkKuhItV5hxMNqNPIpbR95o+/h3b55lPMOnpRsf6Xg7IjMJytQq0gzs/X+ nuBG4zR9miaXE6XBI5fhBoGAEzUJZBDfD2Lr2QJ373FitgHJaLAkCA6DPMj5xPp4ZC0q 3lwg== X-Gm-Message-State: AAQBX9esOUO9F9DZouQSQieyk/WwlQS+d2dhAOI+eDLeZIwXHKx5OkLC q0b7AX+aHVdyj2nrptwhEhBPlJuiqZHy3Q== X-Received: by 2002:a05:6808:1492:b0:386:cb87:d205 with SMTP id e18-20020a056808149200b00386cb87d205mr4353982oiw.47.1680717146507; Wed, 05 Apr 2023 10:52:26 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:26 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Ingo Molnar , Peter Zijlstra Subject: [PATCH v2 10/13] rust: introduce `current` Date: Wed, 5 Apr 2023 14:51:08 -0300 Message-Id: <20230405175111.5974-10-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762359783912707438?= X-GMAIL-MSGID: =?utf-8?q?1762359783912707438?= From: Wedson Almeida Filho This allows Rust code to get a reference to the current task without having to increment the refcount, but still guaranteeing memory safety. Cc: Ingo Molnar Cc: Peter Zijlstra Signed-off-by: Wedson Almeida Filho --- v1 -> v2: Make `current` a macro to prevent it from escaping the caller rust/helpers.c | 6 +++ rust/kernel/prelude.rs | 2 + rust/kernel/task.rs | 93 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/rust/helpers.c b/rust/helpers.c index 58a194042c86..96441744030e 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -100,6 +100,12 @@ bool rust_helper_refcount_dec_and_test(refcount_t *r) } EXPORT_SYMBOL_GPL(rust_helper_refcount_dec_and_test); +struct task_struct *rust_helper_get_current(void) +{ + return current; +} +EXPORT_SYMBOL_GPL(rust_helper_get_current); + void rust_helper_get_task_struct(struct task_struct *t) { get_task_struct(t); diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index fcdc511d2ce8..c28587d68ebc 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -36,3 +36,5 @@ pub use super::error::{code::*, Error, Result}; pub use super::{str::CStr, ThisModule}; pub use super::init::{InPlaceInit, Init, PinInit}; + +pub use super::current; diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs index 8d7a8222990f..468387a5f7eb 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; -use core::{cell::UnsafeCell, ptr}; +use core::{cell::UnsafeCell, 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`. /// @@ -13,6 +23,42 @@ use core::{cell::UnsafeCell, 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) UnsafeCell); @@ -25,6 +71,24 @@ unsafe impl Sync for Task {} type Pid = bindings::pid_t; impl Task { + /// Returns a task reference for the currently executing task/thread. + /// + /// # Safety + /// + /// Callers must ensure that the returned [`TaskRef`] doesn't outlive the current task/thread. + pub unsafe fn current<'a>() -> TaskRef<'a> { + // 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 valid. @@ -69,3 +133,30 @@ unsafe impl crate::types::AlwaysRefCounted for Task { unsafe { bindings::put_task_struct(obj.cast().as_ptr()) } } } + +/// A wrapper for a shared reference to [`Task`] that isn't [`Send`]. +/// +/// We make this explicitly not [`Send`] so that we can use it to represent the current thread +/// without having to increment/decrement the task's reference count. +/// +/// # Invariants +/// +/// The wrapped [`Task`] remains valid for the lifetime of the object. +pub struct TaskRef<'a> { + task: &'a Task, + _not_send: PhantomData<*mut ()>, +} + +impl Deref for TaskRef<'_> { + type Target = Task; + + fn deref(&self) -> &Self::Target { + self.task + } +} + +impl From> for crate::types::ARef { + fn from(t: TaskRef<'_>) -> Self { + t.deref().into() + } +} From patchwork Wed Apr 5 17:51:09 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: 79850 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp494183vqo; Wed, 5 Apr 2023 11:02:25 -0700 (PDT) X-Google-Smtp-Source: AKy350bZCBkIPMN74ujPYsdM4qkwOXjb+ZmA8jwiKMBCxMjhV80AFdX7cJWenb49+L6YVX+oke3Y X-Received: by 2002:a17:903:11c6:b0:1a2:7afc:7cd with SMTP id q6-20020a17090311c600b001a27afc07cdmr8645101plh.22.1680717744712; Wed, 05 Apr 2023 11:02:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717744; cv=none; d=google.com; s=arc-20160816; b=DsRzw5+v2OBSwkSVwDvnIUoDM3AJcSHO3fZL+dP4XdKjLOmJFU4o+TgRVmGdAFk6HJ af1d2ja5tefU344nqmXGNCIZ2H25Cu04JyK7ByWLa8h5vUt/HzUVrxj22F8VmQ0C/l80 86aFvYJBRBCBB9r3KKkbIHgp56JSYlI7Zdc/QDrd7NfJJrvYUeObvMti2U5RXbdjphvT OdLctg7W2Sh/Ay0u9vnpowa5sFZyaTDaKkjfGt91qgyICjr90T8uMKobs54x3mK6ZOdT 0sURAjV1eTPRp6Z+fO624vIkfH7iyx4PTsQQPSA595ZydIJY+wLwvMsTs8s9Ba9vDkLt GVQw== 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=m1wZE/v6mgSkCeDVAKOm1WIZXGoTy4TNz5YfKZmJxYE=; b=EIn5dPFUu/wdT45kSkA3gAhI8MIjFD+Dkjyl8krweiwivIXswHNoSpEW43IG4pD4zC FJDniBwmmIfXd5FXnUptAqoVKZjhyPrPAbH/LpVWlcjNDLjDHlNsGFVGFi0vPb1ye5Xq wT6XK6Yeowk7mOKF6d+EZzpKiUjydaX4Ar+jLFqPa7OvMM3XohRiaSmqpzXXGZRFThHe hzcR9DMDSH4JBHClGXFGspff+bxi2hWRKyXspOVzpVdloGpQ7UI/EdC+1c3PEUnlaLBR jOOwH8V66ZVCXAOQA24mnoDRiyjjzosMhCnERtWbcktmU24X5vI5Ts9TFoiSD1qzUiTx 9jWA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=lZ5xmw7r; 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 n33-20020a635921000000b0050fac33eb8bsi12628228pgb.144.2023.04.05.11.02.11; Wed, 05 Apr 2023 11:02:24 -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=lZ5xmw7r; 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 S233704AbjDERxI (ORCPT + 99 others); Wed, 5 Apr 2023 13:53:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40646 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233522AbjDERw6 (ORCPT ); Wed, 5 Apr 2023 13:52:58 -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 864B372A6; Wed, 5 Apr 2023 10:52:33 -0700 (PDT) Received: by mail-oi1-x232.google.com with SMTP id bj20so27246496oib.3; Wed, 05 Apr 2023 10:52:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717151; 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=m1wZE/v6mgSkCeDVAKOm1WIZXGoTy4TNz5YfKZmJxYE=; b=lZ5xmw7rFK96HMotVpl+UgpAmE/at1reFhBUu+W4sxAtXLGyhABu2M8ozzEjK1BAym GYswSzNSuRw0VqTWrq/G8pWw/fhuSx86FqU3l53QDWuH5coqbtRA/b59PmrOcOwch6yr D+j3S/HWojNwVGp8WpquVHJLll2VYrh416lgBzdUu2flZx4z/dlXOrGkQK/akWwaxr/v KTPWbaN7vH+NtG0tCZGhvZLd/PDSXRapMg8Yp7Gl9c6YDo2tzx/rcEk4BBOnwPdPocnc 9AEb2IVyraha6hsknEzfGgYjC8p5vNp2tODNFUArqbMaUJE3clrnUon8ULaTfFtVkN5O CfOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717151; 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=m1wZE/v6mgSkCeDVAKOm1WIZXGoTy4TNz5YfKZmJxYE=; b=NoyVd7CoUKJDxsx33lcoJkw2/BTF4gSJqYbUAWT3503d848emZznXWZUgSPl67x+KE RrDd1G/yGr59hvDZl0Af7Ab73Gh9uXNHW/TtehXTPPhHYJvs1Wuuv7l3cw62i+R9ldT7 6szy1tejgX+vIgoNJorJL/I6gKtWsh/zvRrwhSHKeaKHIBGN8GvLnpNGM7+S06SmTtqG IWtXXzn3JIO4sh5wFjPMz9XAgjiP1qIAXMQ0bOld6ETOFK+VNeEaKb2T/CAsVCRC6TLs w4/V+YJQIXITSIiUWpgjQPVCyM0tHDGFvNH1haSiNgcYpvuLVDUpVgefq3tbft2CFjdK fQ2g== X-Gm-Message-State: AAQBX9dM8bswktZI8nnFMlDWnE9iftWOavDMrRMKL/05wXC9jIDFTP2k 5ObeNUPP/b0NwXUUVQj0glIA2ZsKgFw= X-Received: by 2002:aca:2411:0:b0:389:9c8:7734 with SMTP id n17-20020aca2411000000b0038909c87734mr3621583oic.12.1680717149903; Wed, 05 Apr 2023 10:52:29 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52: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 Subject: [PATCH v2 11/13] rust: lock: add `Guard::do_unlocked` Date: Wed, 5 Apr 2023 14:51:09 -0300 Message-Id: <20230405175111.5974-11-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360290009889926?= X-GMAIL-MSGID: =?utf-8?q?1762360290009889926?= From: Wedson Almeida Filho It releases the lock, executes some function provided by the caller, then reacquires the lock. This is preparation for the implementation of condvars, which will sleep after between unlocking and relocking. We need an explicit `relock` method for primitives like `SpinLock` that have an irqsave variant: we use the guard state to determine if the lock was originally acquired with the regular `lock` function or `lock_irqsave`. Signed-off-by: Wedson Almeida Filho --- v1 -> v2: 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 491446c3a074..ae20277c39c8 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. @@ -162,6 +176,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 Wed Apr 5 17:51:10 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: 79846 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp489934vqo; Wed, 5 Apr 2023 10:55:18 -0700 (PDT) X-Google-Smtp-Source: AKy350ZY69CCSnkuHkvONtQ5HPxYC64wGa/4VnfgJFvGTXp1oWJG4ypDP5xYx6IqTgyCnhx0AqNl X-Received: by 2002:a05:6a20:a8a2:b0:be:da1c:df65 with SMTP id ca34-20020a056a20a8a200b000beda1cdf65mr35933pzb.28.1680717318392; Wed, 05 Apr 2023 10:55:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717318; cv=none; d=google.com; s=arc-20160816; b=tfpqi7ELClxZ5nSZDd9/cdDztC0BocXO8cDbwOOjKxkYe5XufVpvN1o4q2gXgJKEJi TcI89lqAMVO8H5aoVFekiXedEnzN+yXQ/+UA7BhiGNMx5tAjsx3yK+oOLIf8k0cP6Z2y k+QvTCDyMNqMg9+aiYOIDOHu5gGDwuc6H9jcK5lmucPS3DMTi3UMlUIwGi/4p2OXtnMn oGYtMSUMO3xvu4352G3yKwIw5PZw/D9LTGlMPyN0yPYHJL6mIUv0j7TquOcUV5l2nqul UjDzLHk3exm4r82cjo6hjPUWffon7+POsjJz45ulG1/y0Ex22ttPN9mFDS9WKuOTJj1i Xn6w== 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=N+gZiyyLxRiSG37zAfSNgoy4l7b34DC1t6Bz5rq/u0E=; b=tX42/0SuSVxcuZyM5u30AhLdvutPm8zQBSi/Uf0uWTY5/LtJihgPy+crykJepfyr7n /DPXkBRgFrQUaYPN1E5yzvFfXzZ4U5OQu3tvTYmlf1acO09QvLvER6tHZvIEas8hm20W kR5srmGATgSIieiyD1fsyCBux8AOj4VaebdZu3nI/Jp+ikMMiQcNSYBgX2ym7zp6zqM+ rgpMvfmnHa94llK1eDcvdU6gWCQELyfUV3e5/q3hbxvTUjG/B/bJV06ByAl2CeGG+wM/ W++F91tOepvyKF5kBRAIS1Ugr/ftAOdmIqQFZNdwq0dbp69J8CXc8rEIcPEZhnIsFQ+j YWKg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=j5XuEcww; 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 x70-20020a638649000000b004fbd79d66c9si12643456pgd.23.2023.04.05.10.55.05; Wed, 05 Apr 2023 10:55: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=j5XuEcww; 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 S233742AbjDERxL (ORCPT + 99 others); Wed, 5 Apr 2023 13:53:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40616 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233282AbjDERxA (ORCPT ); Wed, 5 Apr 2023 13:53: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 674DD65A6; Wed, 5 Apr 2023 10:52:36 -0700 (PDT) Received: by mail-oi1-x22d.google.com with SMTP id r16so27166592oij.5; Wed, 05 Apr 2023 10:52:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717155; 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=N+gZiyyLxRiSG37zAfSNgoy4l7b34DC1t6Bz5rq/u0E=; b=j5XuEcwwKsKpNqfakkkqT8jKEOUWA+DuyM9I5THZx1ldm3xH+qLHaQjMAIm1dyTGy0 nlTAoY7F1B5Z5hwP5RkYpBme+Cg89dpUE9pdb5DlqU1/D6WnQsocuTQC7aN8qlh3Tdq6 fIp1LK7IOFve3+4n40nHMR6aIOYykCtpQ7NnVFVSE8ZftV7nQ/zYdzQFcHogANFCGGhj uZ3jrbyJbbQqe2AAvUaSZnFiDIL+GS26Uj8GLA5oeJXsxn7x4Kyp8Z50CGXZesK7X8GY qDQX/ZNMPsRQV2/omgM7KJ6Ddb0ByY39689OuAkW/r0Iv+y+xFvq+EXvheIRfMxse7Rk YG/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717155; 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=N+gZiyyLxRiSG37zAfSNgoy4l7b34DC1t6Bz5rq/u0E=; b=cDzdD0vkZRJ4KS+lU5zCesxEbu3z2d3BOkS+hz7Tsl3dVs8NmFGuSM4CLAlEqOkcJy 3d4UpWNOeZuSUKRLIMOojS30e+jTYbx7Qzp5QK3h5zOHqNQnXPu4eS7n/t0KvVcPP+jD /gCwHLGpf/yfLRJJRmbIJKy9xNwwwn86mOrWVep23ngsc73awzMYMBeIeReyYNsgpKtX rX6HVRJdM2akOWU2m5EY/uS/pLLcoJ6YqYieOZCLhDTOrPzRa2uO1VSGQS9ulV4/83gs igDLDUcatb/+Fi5/ujibNkEWUqN/QHubnNc+5tCokNqCKnaEuito9IWiXDQ0BayfFswD gtOg== X-Gm-Message-State: AAQBX9cXGPQIknikIRK8FLZu2zPvvYEFVjZjHUDAgQnaak9yXPv+drV8 85wmiHZbS7LDCrgWg+DZehSHCvQLNL3RvQ== X-Received: by 2002:aca:ba56:0:b0:387:1e10:2dc5 with SMTP id k83-20020acaba56000000b003871e102dc5mr3214280oif.20.1680717154690; Wed, 05 Apr 2023 10:52:34 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:34 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH v2 12/13] rust: sync: introduce `CondVar` Date: Wed, 5 Apr 2023 14:51:10 -0300 Message-Id: <20230405175111.5974-12-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762359842740709427?= X-GMAIL-MSGID: =?utf-8?q?1762359842740709427?= From: Wedson Almeida Filho This is the traditional condition variable or monitor synchronisation primitive. It is implemented with C's `wait_queue_head_t`. It allows users to release a lock and go to sleep while guaranteeing that notifications won't be missed. This is achieved by enqueuing a wait entry before releasing the lock. Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Will Deacon Cc: Waiman Long Signed-off-by: Wedson Almeida Filho --- v1 -> v2: Use the new `current` macro rust/bindings/bindings_helper.h | 1 + rust/helpers.c | 7 ++ rust/kernel/sync.rs | 2 + rust/kernel/sync/condvar.rs | 178 ++++++++++++++++++++++++++++++++ rust/kernel/sync/lock.rs | 1 - 5 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 rust/kernel/sync/condvar.rs diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h index 03656a44a83f..50e7a76d5455 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -8,6 +8,7 @@ #include #include +#include #include /* `bindgen` gets confused at certain things. */ diff --git a/rust/helpers.c b/rust/helpers.c index 96441744030e..8ff2559c1572 100644 --- a/rust/helpers.c +++ b/rust/helpers.c @@ -24,6 +24,7 @@ #include #include #include +#include __noreturn void rust_helper_BUG(void) { @@ -76,6 +77,12 @@ void rust_helper_spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) } EXPORT_SYMBOL_GPL(rust_helper_spin_unlock_irqrestore); +void rust_helper_init_wait(struct wait_queue_entry *wq_entry) +{ + init_wait(wq_entry); +} +EXPORT_SYMBOL_GPL(rust_helper_init_wait); + int rust_helper_signal_pending(struct task_struct *t) { return signal_pending(t); diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs index ed07437d7d55..d6dd0e2c1678 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..9de76110e6b5 --- /dev/null +++ b/rust/kernel/sync/condvar.rs @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A condition variable. +//! +//! This module allows Rust code to use the kernel's [`struct wait_queue_head`] as a condition +//! variable. + +use super::{lock::Backend, lock::Guard, LockClassKey}; +use crate::{bindings, init::PinInit, pin_init, str::CStr, types::Opaque}; +use core::marker::PhantomPinned; +use macros::pin_data; + +/// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class. +#[macro_export] +macro_rules! new_condvar { + ($($name:literal)?) => { + $crate::sync::CondVar::new($crate::optional_name!($($name)?), $crate::static_lock_class!()) + }; +} + +/// A conditional variable. +/// +/// Exposes the kernel's [`struct wait_queue_head`] as a condition variable. It allows the caller to +/// atomically release the given lock and go to sleep. It reacquires the lock when it wakes up. And +/// it wakes up when notified by another thread (via [`CondVar::notify_one`] or +/// [`CondVar::notify_all`]) or because the thread received a signal. It may also wake up +/// spuriously. +/// +/// Instances of [`CondVar`] need a lock class and to be pinned. The recommended way to create such +/// instances is with the [`pin_init`](crate::pin_init) and [`new_condvar`] macros. +/// +/// # Examples +/// +/// The following is an example of using a condvar with a mutex: +/// +/// ``` +/// use kernel::sync::{CondVar, Mutex}; +/// use kernel::{new_condvar, new_mutex}; +/// +/// #[pin_data] +/// pub struct Example { +/// #[pin] +/// value: Mutex, +/// +/// #[pin] +/// value_changed: CondVar, +/// } +/// +/// /// Waits for `e.value` to become `v`. +/// fn wait_for_vaue(e: &Example, v: u32) { +/// let mut guard = e.value.lock(); +/// while *guard != v { +/// e.value_changed.wait_uninterruptible(&mut guard); +/// } +/// } +/// +/// /// Increments `e.value` and notifies all potential waiters. +/// fn increment(e: &Example) { +/// *e.value.lock() += 1; +/// e.value_changed.notify_all(); +/// } +/// +/// /// Allocates a new boxed `Example`. +/// fn new_example() -> Result>> { +/// Box::pin_init(pin_init!(Example { +/// value <- new_mutex!(0), +/// value_changed <- new_condvar!(), +/// })) +/// } +/// ``` +/// +/// [`struct wait_queue_head`]: ../../../include/linux/wait.h +#[pin_data] +pub struct CondVar { + #[pin] + pub(crate) wait_list: Opaque, + + /// A condvar needs to be pinned because it contains a [`struct list_head`] that is + /// self-referential, so it cannot be safely moved once it is initialised. + #[pin] + _pin: PhantomPinned, +} + +// SAFETY: `CondVar` only uses a `struct wait_queue_head`, which is safe to use on any thread. +#[allow(clippy::non_send_fields_in_send_ty)] +unsafe impl Send for CondVar {} + +// SAFETY: `CondVar` only uses a `struct wait_queue_head`, which is safe to use on multiple threads +// concurrently. +unsafe impl Sync for CondVar {} + +impl CondVar { + /// Constructs a new condvar initialiser. + #[allow(clippy::new_ret_no_self)] + pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit { + pin_init!(Self { + _pin: PhantomPinned, + // SAFETY: `__init_waitqueue_head` initialises the waitqueue head, and both `name` and + // `key` have static lifetimes so they live indefinitely. + wait_list <- unsafe { + Opaque::ffi_init2( + bindings::__init_waitqueue_head, + 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 ae20277c39c8..f52ba9ab1b70 100644 --- a/rust/kernel/sync/lock.rs +++ b/rust/kernel/sync/lock.rs @@ -177,7 +177,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 Wed Apr 5 17:51:11 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: 79847 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp491111vqo; Wed, 5 Apr 2023 10:58:06 -0700 (PDT) X-Google-Smtp-Source: AKy350ZSYlknn1qieUw+mSmLnVEp8NdzM8UeFMw7o6HL7bnac+CVRp6VhrdSYmWkiuPxfFwOkksV X-Received: by 2002:aa7:c993:0:b0:502:251b:3a4c with SMTP id c19-20020aa7c993000000b00502251b3a4cmr2733485edt.20.1680717485834; Wed, 05 Apr 2023 10:58:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680717485; cv=none; d=google.com; s=arc-20160816; b=Htv+OpEAvK983ubigXVV93rzFypsE4l2yDdeB+pE1lcr65EtR9m55kbVmbVWHiVNmm ++CGbr9gThALqHaML9lSjusHsRsB3PGM0KXO4FUU7lb3H+1lyX74cSywBZCdGNAoYWK2 mhDv3nykjN9xVRmN6+KbTgdeGLJs8tCkATjEHI5Ns2CSdNto58R1hGlgGRiggzrSZ6ah pm5H4MZSCCbmKzq2TBE8wAJC1x6xoLQz7DchwcZ9HMct2Cu9X5ZmATDEgtZnHYOSceU8 dq1ZgWak699UZYuNIKg1cYhP2162I5LbZhfDMCdswCEL8DDLZF9sLV7ugTVgFduos5QV YWOw== 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=zNUYspx19IADgHh5+dQkFTo3WdN9gKiyBBCTIaE+T8A=; b=QqwT7Qm9jIlIMBnsSgdChY9jFOrgvI/h6cuVKFw/jqdUstyTMiFrko3iJaLUIQZFN4 FwyG6aMr64MOnzDrnEei4/D1ZvxV+OU5v1dbERGW3NquPbYP9WOr0uTpQmlASb32bVd4 yvQjt3nOfpGM75Ht1THKGlpObhYfqmpCo93O3n6eKxyEkmjXQpB8VentAVYHim1vTdwX tme9W9epCAxWaQkQvr5AomnxBZzbmkX3lQ1WwKRHpI8MdJATWUM+8FSbhaz72GHvBO5G rQxtejAhewpT7bMlXnzhpzRZd2RCPxBKG1cbHvc/xQlb0vlIfbjchat2nZ6vgjP6I79F wD7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=lYYGJ2oj; 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 a6-20020aa7d746000000b004fd3ad97e48si2083520eds.55.2023.04.05.10.57.40; Wed, 05 Apr 2023 10:58: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=lYYGJ2oj; 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 S233773AbjDERxO (ORCPT + 99 others); Wed, 5 Apr 2023 13:53:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233317AbjDERxD (ORCPT ); Wed, 5 Apr 2023 13:53:03 -0400 Received: from mail-oi1-x230.google.com (mail-oi1-x230.google.com [IPv6:2607:f8b0:4864:20::230]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 833FA7683; Wed, 5 Apr 2023 10:52:39 -0700 (PDT) Received: by mail-oi1-x230.google.com with SMTP id bj20so27246757oib.3; Wed, 05 Apr 2023 10:52:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680717158; 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=zNUYspx19IADgHh5+dQkFTo3WdN9gKiyBBCTIaE+T8A=; b=lYYGJ2ojuoGdIra0r5s5ocFIVoOj2hZT+oKToAmI6i1YXSLMd3VvIFxIcEbHYSqYFC MVo6iuE8kZ7cE6/XC5PL/2sMs3ld5pUYVk2MD00o/IFKvaY9BM1ED9w3affr242wCAoU 3OI1AZ7CaywpMQTXCFGJp+UH0jSfKNah7bDux959gvn6EDLOYD6C2Qpu9eLJTv2HwfPQ RerVeJc0xXcmtDjedmRZuMBFr3oJa89eTD1E2qa2OIM1rJQCQ9mgLazt8ova1aYwWv/j V8N0NpVSuEHad9hlua7aGgGPQNaynI0gCK1Rx+n09cw8jmkaIKQMYaDJSx0C5Nh9c4pW myiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680717158; 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=zNUYspx19IADgHh5+dQkFTo3WdN9gKiyBBCTIaE+T8A=; b=hS81iNyEJ4X5rAsSfIIS6lb5TI2dhcZKVVN8CiRQa1GJOMEnWJIgg767uT6Zq9WP7L xc3zZs0VfZ9nApNhG5FXSQzLFJiZn6DWtkbchvyg27eVpdK9UC3r9aDz/lUn7z8ghmhQ +PN+ZH/46Ob/iGT3/Iy8FfihotaJZG9JaUZADn9jb4yeLGy+nfy0sKIagmdKY9+dPADx TIiNIVLyTTHAIVF0FFk1FLl9RlyIF5FwA3AqEgYd7Dvr88UZzxW9R3SC6+1DFtG+c6DI 7gFp9LpRODuxLl33CEtH8+VMrkddgF18QHCF/tf7rA2fRQ24NWcjOqxNCK90nNBVZPi/ Opcw== X-Gm-Message-State: AAQBX9fbQVqYCjw8erxkq/LgETbiLDRiveLaQ3KpA06vOarysvnw8KOf MIU4u1j1905k3U3ggBQFEg59wcbRdKE= X-Received: by 2002:a05:6808:292:b0:389:7ffe:5059 with SMTP id z18-20020a056808029200b003897ffe5059mr3001434oic.58.1680717158019; Wed, 05 Apr 2023 10:52:38 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id w185-20020aca62c2000000b003896e31867esm6604045oib.49.2023.04.05.10.52.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 10:52:37 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH v2 13/13] rust: sync: introduce `LockedBy` Date: Wed, 5 Apr 2023 14:51:11 -0300 Message-Id: <20230405175111.5974-13-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405175111.5974-1-wedsonaf@gmail.com> References: <20230405175111.5974-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?1762360018348491940?= X-GMAIL-MSGID: =?utf-8?q?1762360018348491940?= From: Wedson Almeida Filho This allows us to have data protected by a lock despite not being wrapped by it. Access is granted by providing evidence that the lock is held by the caller. Signed-off-by: Wedson Almeida Filho --- v1 -> v2: Added build_assert to rule out zero-sized types rust/kernel/sync.rs | 2 + rust/kernel/sync/lock.rs | 2 +- rust/kernel/sync/locked_by.rs | 128 ++++++++++++++++++++++++++++++++++ 3 files changed, 131 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 d6dd0e2c1678..f8edb6d0d794 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 f52ba9ab1b70..51c996ca2109 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..191e37d804e5 --- /dev/null +++ b/rust/kernel/sync/locked_by.rs @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A wrapper for data protected by a lock that does not wrap it. + +use super::{lock::Backend, lock::Lock}; +use core::{cell::UnsafeCell, ptr}; + +/// Allows access to some data to be serialised by a lock that does not wrap it. +/// +/// In most cases, data protected by a lock is wrapped by the appropriate lock type, e.g., +/// [`super::Mutex`] or [`super::SpinLock`]. [`LockedBy`] is meant for cases when this is not +/// possible. For example, if a container has a lock and some data in the contained elements needs +/// to be protected by the same lock. +/// +/// [`LockedBy`] wraps the data in lieu of another locking primitive, and only allows access to it +/// when the caller shows evidence that the 'external' lock is locked. +/// +/// # Examples +/// +/// The following is an example for illustrative purposes: `InnerDirectory::bytes_used` is an +/// aggregate of all `InnerFile::bytes_used` and must be kept consistent; so we wrap `InnerFile` in +/// a `LockedBy` so that it shares a lock with `InnerDirectory`. This allows us to enforce at +/// compile-time that access to `InnerFile` is only granted when an `InnerDirectory` is also +/// locked; we enforce at run time that the right `InnerDirectory` is locked. +/// +/// ``` +/// use kernel::sync::{LockedBy, Mutex}; +/// +/// struct InnerFile { +/// bytes_used: u64, +/// } +/// +/// struct File { +/// _ino: u32, +/// inner: LockedBy, +/// } +/// +/// struct InnerDirectory { +/// /// The sum of the bytes used by all files. +/// bytes_used: u64, +/// _files: Vec, +/// } +/// +/// struct Directory { +/// _ino: u32, +/// inner: Mutex, +/// } +/// +/// /// Prints `bytes_used` from both the directory and file. +/// fn print_bytes_used(dir: &Directory, file: &File) { +/// let guard = dir.inner.lock(); +/// let inner_file = file.inner.access(&guard); +/// pr_info!("{} {}", guard.bytes_used, inner_file.bytes_used); +/// } +/// +/// /// Increments `bytes_used` for both the directory and file. +/// fn inc_bytes_used(dir: &Directory, file: &File) { +/// let mut guard = dir.inner.lock(); +/// guard.bytes_used += 10; +/// +/// let file_inner = file.inner.access_mut(&mut guard); +/// file_inner.bytes_used += 10; +/// } +/// +/// /// Creates a new file. +/// fn new_file(ino: u32, dir: &Directory) -> File { +/// File { +/// _ino: ino, +/// inner: LockedBy::new(&dir.inner, InnerFile { bytes_used: 0 }), +/// } +/// } +/// ``` +pub struct LockedBy { + owner: *const U, + data: UnsafeCell, +} + +// SAFETY: `LockedBy` can be transferred across thread boundaries iff the data it protects can. +unsafe impl Send for LockedBy {} + +// SAFETY: `LockedBy` serialises the interior mutability it provides, so it is `Sync` as long as the +// data it protects is `Send`. +unsafe impl Sync for LockedBy {} + +impl LockedBy { + /// Constructs a new instance of [`LockedBy`]. + /// + /// It stores a raw pointer to the owner that is never dereferenced. It is only used to ensure + /// that the right owner is being used to access the protected data. If the owner is freed, the + /// data becomes inaccessible; if another instance of the owner is allocated *on the same + /// memory location*, the data becomes accessible again: none of this affects memory safety + /// because in any case at most one thread (or CPU) can access the protected data at a time. + pub fn new(owner: &Lock, data: T) -> Self { + Self { + owner: owner.data.get(), + data: UnsafeCell::new(data), + } + } +} + +impl LockedBy { + /// Returns a reference to the protected data when the caller provides evidence (via a + /// reference) that the owner is locked. + pub fn access<'a>(&'a self, owner: &'a U) -> &'a T { + crate::build_assert!(core::mem::size_of::() > 0); + if !ptr::eq(owner, self.owner) { + panic!("mismatched owners"); + } + + // SAFETY: `owner` is evidence that the owner is locked. + unsafe { &*self.data.get() } + } + + /// Returns a mutable reference to the protected data when the caller provides evidence (via a + /// mutable owner) that the owner is locked mutably. + /// + /// Showing a mutable reference to the owner is sufficient because we know no other references + /// can exist to it. + pub fn access_mut<'a>(&'a self, owner: &'a mut U) -> &'a mut T { + crate::build_assert!(core::mem::size_of::() > 0); + if !ptr::eq(owner, self.owner) { + panic!("mismatched owners"); + } + + // SAFETY: `owner` is evidence that there is only one reference to the owner. + unsafe { &mut *self.data.get() } + } +}