From patchwork Thu Mar 30 04:39:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 76883 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp873101vqo; Wed, 29 Mar 2023 21:50:21 -0700 (PDT) X-Google-Smtp-Source: AKy350YBKqiXmlRgW2C1Fp3DGMY9lvkqcUy5oW/gl9ewFkAOK3lC/MSw89+kJpUZbFRJ4/6rQgw7 X-Received: by 2002:a17:90b:1104:b0:240:9b09:e9ce with SMTP id gi4-20020a17090b110400b002409b09e9cemr4721178pjb.16.1680151821503; Wed, 29 Mar 2023 21:50:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680151821; cv=none; d=google.com; s=arc-20160816; b=ppkYIzGq3ZNrN60CzjY8dfhMCuQwv55nAKS79EDspkA1fyHd5vwkM4KchaNAQ5UeUO bPHRuPOIihCTvFkuaMHF/EmJmkmwZKPX8tkk0AxuNkIcH6fRfmT3uurVfhTW1Yax2Ckp 77W/xDZeXUdiJWO7yCL6oxFuodJOQQ1puF+2iTKnUYTIwxiaZBDSrmSmhs1UcBXmIaeX q02jDjkFUM9uEGyYDrPedMvqH7EvfMU9nOs9EIUG/gasWRL48VwYPSBaiffJnylCuoON Hq8sDHuhO7cMExiuAFP8Z4Kc8Iki87BQRRs7qi12thlx5ZUHLF3fpdooTG3KyOGEvUUF aIdQ== 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=rLQtYNZFpddodHi/ahJfQCsqx8fDKLCv/AuGB4H5UvE=; b=naFcXM3zltoN+ZvZuLi6oOcOeE9W+zNz/lzZiNq2yOiNfKW/1Ua1VpzD8FjsJpyy5o c8JjgMDYvHCm+94Hh2y51VapWvJkYml7CGUeV0ad7dpf0MrbDNZQo9ph+yXgHFqYtDH1 nJREX+0fpWNYxHx/ONP40cbniZMsg6xNhQmcvbLxS+BsdtFx1kAuf42WLob0ATYAqmeo IHg2rqzWdVQYL08gEzHjGjvRQ8XgmHyizyTRT7tCpJ5RZYtjutfBRN0bPBsbb3bUU2ZO GGdU3KYdlxbOzbbGRckY8eYD2paN+7p34X3zPM/jCVrhJ4Q8ED74TVT8MrDPMBm/bQMq VqNQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=IyJZWNVj; 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 nn14-20020a17090b38ce00b0023f0955f301si3266843pjb.166.2023.03.29.21.50.07; Wed, 29 Mar 2023 21:50:21 -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=IyJZWNVj; 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 S229678AbjC3ElC (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35602 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229481AbjC3ElB (ORCPT ); Thu, 30 Mar 2023 00:41:01 -0400 Received: from mail-oa1-x2c.google.com (mail-oa1-x2c.google.com [IPv6:2001:4860:4864:20::2c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96CA9618F; Wed, 29 Mar 2023 21:40:46 -0700 (PDT) Received: by mail-oa1-x2c.google.com with SMTP id 586e51a60fabf-17ac5ee3f9cso18533073fac.12; Wed, 29 Mar 2023 21:40:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151246; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=rLQtYNZFpddodHi/ahJfQCsqx8fDKLCv/AuGB4H5UvE=; b=IyJZWNVjjZ8/W8dHQs79bS3aAa+GUYXGhoabxs417dD1lH3ar/QQ9Pp9/L5d16GPAL tTH25vZr0ronU3Je4ybnvYKw7teys1hfsl87OSR4a0Wx5NHoCiyUQCfc+2WLWIm9iRT5 TDC6lE5mJermYKgsiBPBoV5Ov+1kBaiJDjY90oeIHB/iADj9voJMmcsgqTc9e6odc2oh 4c+UZMuVtDbekur4g/yLZX5RZ+zp0bjPmiCp0kK0JC2qum+TzDirISqDgMK92qXHUMIM P50YC0LPUoKglhRlUyWiNo7I8S4Xo/s55wISc9Bx0w7IMvc5ZTUrtqgWNJfm+tijzaRg VWSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151246; 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=rLQtYNZFpddodHi/ahJfQCsqx8fDKLCv/AuGB4H5UvE=; b=snExaqrpvZxhGi5xwpvhBDzoZRjDqsDsnzWM0kJa7kjvWou87LOPYAmDaUHEhTJRtD ACClUkiFCy54VaZaY0xcpJWK/7TViC0uTs5e8TKu728dxQaQDYYtHpU2C3NPFgw5jQyO D8xjKXQN5iVX9gMSggYsuT1kqfbMY/MFU2xzbOhvAWHHxXMpAWPcP2g94RMtlJpTwpav JgRxMZKMacNEL0hWods6wrXHQYoLYxj3XZrQJ6ekIExoG5c0UunBUMhCDjlyAKgv5ZrB KVVqQwV7VZhDPiDNXEAZkgy0sv/erUHEKgXv2OgI09CJHCT2fuqMeekc4tssQgslDEop QPmg== X-Gm-Message-State: AAQBX9d17BhJG1kmuu1AUenNlO2V+IcOzmlUxN5dEbySOmEqwI/D3Iyx SjKkbAuBF/IZr5ar7tGion439WFg5en6lg== X-Received: by 2002:a05:6870:c150:b0:172:289b:93c5 with SMTP id g16-20020a056870c15000b00172289b93c5mr2508515oad.0.1680151245805; Wed, 29 Mar 2023 21:40:45 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.40.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:40:45 -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 01/13] rust: sync: introduce `LockClassKey` Date: Thu, 30 Mar 2023 01:39:42 -0300 Message-Id: <20230330043954.562237-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?1761766876235586081?= 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 --- 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 generateis 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 Thu Mar 30 04:39:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wedson Almeida Filho X-Patchwork-Id: 76885 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp873305vqo; Wed, 29 Mar 2023 21:50:54 -0700 (PDT) X-Google-Smtp-Source: AKy350Z/jQGCK+LXCe5cvaBe12PjybSXOqHA/GdJW+6IwKKWqKT2VPzF5xzIErDmqI4q818ECo+u X-Received: by 2002:a17:906:27c4:b0:931:c2f0:9437 with SMTP id k4-20020a17090627c400b00931c2f09437mr24142452ejc.8.1680151854388; Wed, 29 Mar 2023 21:50:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680151854; cv=none; d=google.com; s=arc-20160816; b=PtIY2Cn05sO16K2CUyWGSPXsMsH6t2nmBKOR07Z5lfWWKSHm3FBl1bZEZ6PSekchuw j+GCCWfr8N969XBwr8DasClSp+1NL2NItDUJJ3ZETr5dvRXz+NcoMzhZCUPqu6UIpkpi CM7xTktQvmobN4CUAVPkUeBIHD5zhSdyzAhyeYEwKtZWPQ5M16HI2gOfzABW9GEk40kp vEhVfosiblTiGQLx3UmGwWc8Q8pyxQcMa7XaQ1MAFvFZGP6ft6WI/Xx/5uS8/M9MEl2B 5nXLmE3vFdSzy1zTg9mGWQNQKUuoLV9MmjMZChQgMMQlZlv9pgvBS0SQDsbuBTaKe03Q 6ARg== 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=10KpFBgmcYjxGutew/HixzYci2huFC433d/siDnSI3w=; b=BhF9Y3p1V5hpnbJuOQClkc/t2ofL7UIKzjR/D39piUZiK+leW8c6EBFTLghA1XAq6v 0pmOj22sv04fDa758VdmHfPYbcsd3S7j0Rwlgqb8NyWKVycXd43CYiOYgnlKp85kWtEL PYaZcUoqtXmvo+Hcyz+LS97ctk91z8TtmNkjxdP0bZL680y/+hD1sJTVqY6WAWU1t5I9 S6ar+tRVnt80ccs4hm8ExomvGADuuQ0GjYeAkZyNl5Nwxgmn2Ww6FguGtwA0HrxNrbav cAMcs6dngvNAuttt4GJE944hcylFY+DdnlrqYwqCfUePrIOoLRlAVY06yxwQMynYNf1a 710Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=p3L6KaFw; 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 u18-20020a1709063b9200b0093175b7c1e3si32317235ejf.870.2023.03.29.21.50.29; Wed, 29 Mar 2023 21:50: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=p3L6KaFw; 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 S229910AbjC3ElI (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35630 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229674AbjC3ElC (ORCPT ); Thu, 30 Mar 2023 00:41:02 -0400 Received: from mail-oa1-x2c.google.com (mail-oa1-x2c.google.com [IPv6:2001:4860:4864:20::2c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 19E5F35A2; Wed, 29 Mar 2023 21:40:50 -0700 (PDT) Received: by mail-oa1-x2c.google.com with SMTP id 586e51a60fabf-177b78067ffso18553689fac.7; Wed, 29 Mar 2023 21:40:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151249; 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=10KpFBgmcYjxGutew/HixzYci2huFC433d/siDnSI3w=; b=p3L6KaFwzj5ReZbQLFB/rh0O4XgPbhVbtIZMNsJ+R+HzG4sy+260NgHjyQk3e6uy48 fx4XHfoTtNqB6V0FS4d4Xs/UuXm5Nrtg16C4F6No21uHUbm2lxix3+k1kQ+dWrXfoxTu E/QoxxtRmQly/r6Tbz0zTk2Bp0KnNmfp7hK743WObspfwWIVeJb5CZgMN+O2yq8GSyNd 0ZPMOyzzYAZhPQ5fp2yZIVVedVt84oCEi79S/tpa0aMNOLt1bkQVJjzE1xYo679upaGn zNPFAqq3mNklonGw0OhQp6agTMFn8bapk92w9Y5kB8Zp5Gr7heErliGEELxorzn/CzCA PfZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151249; 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=10KpFBgmcYjxGutew/HixzYci2huFC433d/siDnSI3w=; b=XNeolKMhEy+IyVulUVzw1xJ8ak8TrXn6SqSWBbmq+kNVv3gv7Bnrsab3yT2oYIJfbQ BoaqZkCryhiYFNdiTCsD+Bc9u2V+uhMkUVc751hiIapgSQ31S52HqjukKSBfkESN1eTK /IBXJshjZpgDANjjG5MEgyYVpsZnbi/Z+fx/yermAF7r1rPtwdSVb0q7f26WWsLwtSk9 J1YsWhtgmYiNo9HG1Yf7WvnCx59zz4s0JZ4C7t88NkgQwOe8OSQZf4SRUm3DN2q+RBca q9J0Xa5BFoa57m0zKU5ehw0y3UFZTWuhWDwU5N7/spAqnOMbfDC/W6O8/+3bOX8yaDDF CVwQ== X-Gm-Message-State: AAQBX9f2aO+lsXfuAqQN51dXNHg18QiRlBQcANNnm3znloIhXeckp5PP Ms12igmoP6/D3jUA9VnLuCSBTYMgr+Nrdw== X-Received: by 2002:a05:6870:24a1:b0:177:9ede:bcc6 with SMTP id s33-20020a05687024a100b001779edebcc6mr13580475oaq.14.1680151249348; Wed, 29 Mar 2023 21:40:49 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.40.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:40:49 -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 02/13] rust: sync: introduce `Lock` and `Guard` Date: Thu, 30 Mar 2023 01:39:43 -0300 Message-Id: <20230330043954.562237-2-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761766911050355993?= X-GMAIL-MSGID: =?utf-8?q?1761766911050355993?= 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 --- 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 Thu Mar 30 04:39:44 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: 76894 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp879110vqo; Wed, 29 Mar 2023 22:05:00 -0700 (PDT) X-Google-Smtp-Source: AKy350bp0P6UZ7tbm2s94HrU6HBrIt6MlWRUfyzgTMTSEuw/Nwo2w7ZtFmJpWINVduGoSrSHkOju X-Received: by 2002:a17:906:7193:b0:931:7adf:547e with SMTP id h19-20020a170906719300b009317adf547emr23779712ejk.70.1680152700234; Wed, 29 Mar 2023 22:05:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680152700; cv=none; d=google.com; s=arc-20160816; b=LEnkgW0J096EQmSBQzxGMD4Fe4RUI0IMIPIEOmaYd6TpunTqgrLCYeOoAoE7RCEb07 ZCxOmmHx7iY9QH99J1NSivOzeDrMF8HBS3998EVO2rOoyT9IKnMvIctRfhVf6abXi1qY H3smmKeh185IA54nOls9FzQLFUlQ/Z295vWFLGzhvT0u9D0yld+dQcWif+IG2OWJNCwO qYXANRknCV6z2ZnElpxPwu7Ge2E4mdbiFOAqnJCn1FmgMPeb+hqOh4VFhqvSsfWr1gxs wf5586jzVgNwrf4oHIanGZ7lqbeO9xpAsuS/b/dSvvb4GnGLoNXg+3vo0PGDXde43/ux l2NA== 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=Rz/wA0EJV4qXfvvhu8fz27iXlBcuFSyg7BlqCeu9CZc=; b=akTP4biZu5nLIllwT127SOnzpDFuvnjXpbUwiRT73/dq2qMvbEtnpD7c3QUpfoy/Ir iH/6M/WyiDUeLOKcNCdSCVAwwfH53Eqq3Mmnoino6irEaEs9teN3uIhotaRxKk4+7xtt mD2OgDm5/v19wrNYUDBdFwX2pREzcDYZcSt9Ag+5wTEFe0Ir4tQNApsiab3T/9es6lnC dFJbbJxN8QdUSmV+VG3+vc2nZSwltZ7fivKmC9KkNoHzuLaP65r/G3viOZF0+2Yarnuv PzGGt/JtFEXIlGnZ5X6cy4fDmbJNpCWCKx19gDOZr7BxLvYjxuBXijwrgZGrfZwHIm+5 q3pw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=I+fkMkkx; 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 qk31-20020a1709077f9f00b0093ad46081fdsi25005999ejc.6.2023.03.29.22.04.35; Wed, 29 Mar 2023 22:05:00 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=I+fkMkkx; 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 S229884AbjC3ElQ (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229880AbjC3ElD (ORCPT ); Thu, 30 Mar 2023 00:41:03 -0400 Received: from mail-oa1-x2f.google.com (mail-oa1-x2f.google.com [IPv6:2001:4860:4864:20::2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E5645245; Wed, 29 Mar 2023 21:40:55 -0700 (PDT) Received: by mail-oa1-x2f.google.com with SMTP id 586e51a60fabf-17aceccdcf6so18533864fac.9; Wed, 29 Mar 2023 21:40:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151254; 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=Rz/wA0EJV4qXfvvhu8fz27iXlBcuFSyg7BlqCeu9CZc=; b=I+fkMkkxnBBRv2+/t8pOUUKk0cut4cRWJeetknDDR1iaYt4jnaOtVdIGjmRPpOsYNM +nQGpEMRDZY6CIzKcNDj5R+k8iH/qbgD++X0hsdNeD22E/p+EuLX0Ux6B7sc2gvU8v58 S1yVBRNn6GL9lgpAi1cTgG8+HWW31p1HeMJ3IJoinJiuOHp/kmDWt7lp0lTHgcV3yZAv I2X6RYhtBomXLlF33qAvYQXIqFWc1lmVq1McMb5D3GKFPYvmhfi6PJXu7XyM/fria4xE 0FC3+6Z7TXG1/ooQ6/uxGsNObFJxYJzspcU+4NBHvTRXqy31dRg6NbqqTkO55i6fdA1x 2KMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151254; 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=Rz/wA0EJV4qXfvvhu8fz27iXlBcuFSyg7BlqCeu9CZc=; b=R0XzU3X4J/XPVHrAZ4OSpiIBzsjinI3Ek3i3gHBJMS1J1Y4lh0NfLQf1+H7QJF4JnS C4na1cy71VzWac7toWOysnnu+HALh6QMQ2W5k8V/Ua3KfzmR5l1bsFHqEL3WMBQFTVq2 8fGeUCw8hX8weAY1lUGh0N6HYIH1MQi9cRaw1Gu7DZDAFaLOgMCqfkHrqkpc+1uJPgCf kA48EoC1QTrL/lRt6n8mFrlm+We7OV74mS2URlIyrhbcfKUAtHbAjghFtOIFJoIfdihd pcx8ZJxk7KV1Kcr7fpX8wJRhgEAjk2jifu7nvfGJZYGvlcWs3F8D2ayumeFK8bEt7pbN u0tA== X-Gm-Message-State: AO0yUKWxBAsjX2ck1kd9RhVNBJFDYI80gC58f3MPuuLREziZLWSvOz5S BpFDkQwej0qLQD79J9AMWHZtGnzOLeF3Qw== X-Received: by 2002:a05:6870:9113:b0:17e:a3d8:5a1b with SMTP id o19-20020a056870911300b0017ea3d85a1bmr13032336oae.31.1680151254456; Wed, 29 Mar 2023 21:40:54 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.40.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:40: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 03/13] rust: lock: introduce `Mutex` Date: Thu, 30 Mar 2023 01:39:44 -0300 Message-Id: <20230330043954.562237-3-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761767797654964883?= X-GMAIL-MSGID: =?utf-8?q?1761767797654964883?= 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 --- 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 Thu Mar 30 04:39:45 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: 76893 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp879104vqo; Wed, 29 Mar 2023 22:04:59 -0700 (PDT) X-Google-Smtp-Source: AKy350aBEnHVwK8fh7JQzOMw54AwrDqEb7AnMBU4GMcRoAIMTvj15/CXZzUalXhDlasPfpwcsolk X-Received: by 2002:a17:906:1e13:b0:92f:e40d:1489 with SMTP id g19-20020a1709061e1300b0092fe40d1489mr25296788ejj.61.1680152699429; Wed, 29 Mar 2023 22:04:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680152699; cv=none; d=google.com; s=arc-20160816; b=GTBzJ/jrHWq6/Dn+CLayj8IgXpjQ+6Irqmx1KUmoYnCb1dADmmR6AIBRhc0tYpCj8a 0Q6+x5E/96VO9iiJLEiyXDyftKXvHCz3wsFxixut4sY3fPAi0onalY6AGEmT5o7BnyLF bxoTQ6xyKfmm8dv2oonuSfjiNWX2orQLlAnq9H3+3h1Xfo1CCt1EGxW9DbMqb0/BxYEA C+sUk7fKQPKmNahOiUZTH0brFDqxv807AOjP9+we64+ionk6m8K2lnG1Aqs5nT4JRocn lIWzNQru0k3f2385FARihlNY47xENfi57fRgBnEluqSkHQlm6UxosZk3ox/pS8WmTgB5 Y11Q== 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=LkdOS4IPS6lAQ/+/R/HSZz8UmvvCCFlzt5mrQlViXVE=; b=wLVV/CUVr2xAMWUOKtLXysRr5VSy2W+DsVidm24F9+JTRUoXGaHYpFkBbpexQWA4Cb A7VApNRUgq0km4X1M012nfqbP1f4xLUmF/8oXEOQ7YSMRIhUXbl1ixGI9XV1pCXabKXh CmGPwLxy8rOEi7x4gVPo5GjFpkRmY/IGGA6VsWn1CDNg+0rycJrrZILh/q1mgFGh+UfH G5q7WDY8GImnYe+2KHi2vPtZzzqSzgr0PYZnKATdNFRfJ9GqWZYV6Xhl8IxBZ+8YRTXG vYnj1oWG3JfULd2iiq5pzF6ErYWLTxVqL00CNWNdiglElnfu076J3wicQAcRULpkD4Bp Dm1Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="Ad+K/21H"; 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 u17-20020a1709064ad100b0093c09a76ac9si17663986ejt.481.2023.03.29.22.04.35; Wed, 29 Mar 2023 22:04:59 -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="Ad+K/21H"; 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 S229932AbjC3ElY (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35756 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229890AbjC3ElG (ORCPT ); Thu, 30 Mar 2023 00:41:06 -0400 Received: from mail-oa1-x30.google.com (mail-oa1-x30.google.com [IPv6:2001:4860:4864:20::30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4CB9F55BF; Wed, 29 Mar 2023 21:41:00 -0700 (PDT) Received: by mail-oa1-x30.google.com with SMTP id 586e51a60fabf-17786581fe1so18528617fac.10; Wed, 29 Mar 2023 21:41:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151259; 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=LkdOS4IPS6lAQ/+/R/HSZz8UmvvCCFlzt5mrQlViXVE=; b=Ad+K/21HHHCmG+2LPPxPPbenT+S7mRF6t2x5naSZR5mN4ZY1Dfbmty4mIKdSUorQ6B 4Lypn5IuRidd1Yt/9Znw1lk52fLWKw24w6uFA57h5pqqOltAD4/DCJBzH9QBMiln7ZNg Si/xtk0Z/DxYhzavwXU6THjgtbrqrdlOArErbhS03WXthgfqVQRbiv2dqDKGfgUiFyon CH3nY9Bqhx5h5KJEjQ9Nnc6PnCxd9CojFBGTgv5TV4bGhkR1FQtnwZ+9XX7jfl1f3EPb dNqb67hhHjfgY5Dpa1D3CMTlYg8RYDWo8zNe8prw7KuAidz5xsX67zz2cmHFqmXceCa0 34hQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151259; 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=LkdOS4IPS6lAQ/+/R/HSZz8UmvvCCFlzt5mrQlViXVE=; b=Hr5dIAw5TJavasCdlg/ZPqXzqBAq/rxmXtp3Hz79R0DxTYy2NYoGnPmiVNtJorZ2g8 17vhwPQjvNftJIk9JHEslvHafVyteJ5VAOjFJABH6fyOgvfa8IVnA6chfyMzGkw6YPfW /5AycIaH7c5UnIRqTNGuczeYLw6wGlvpehnNH6009bbJcHyCbOIW2KLVyb04U7PO9jhq LntUCOYTInTYUr9m4a0lwxbzHN+KPcBhgDcEq6uyt2/X0+Jopf5LQBHEOHUQmqpSmvWh NZT6pR6pgmIV36rEs/JrTkM8xtL4KHA2lNXAkVmpWq3UrXe+szJxlnegGwP/n0B6Qfts jREg== X-Gm-Message-State: AO0yUKXngqOoOvH2WpdtdXI29mOBCVDqGcgvxX326cDUnPLwz4JEzz2m ePd9cAstGg/68qUQQ/cE8orct3uURqWnSw== X-Received: by 2002:a05:6870:b006:b0:17a:d2e0:1a14 with SMTP id y6-20020a056870b00600b0017ad2e01a14mr13809272oae.27.1680151259564; Wed, 29 Mar 2023 21:40:59 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.40.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:40:59 -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 04/13] locking/spinlock: introduce spin_lock_init_with_key Date: Thu, 30 Mar 2023 01:39:45 -0300 Message-Id: <20230330043954.562237-4-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761767797079553160?= X-GMAIL-MSGID: =?utf-8?q?1761767797079553160?= 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 --- 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 Thu Mar 30 04:39:46 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: 76890 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp875244vqo; Wed, 29 Mar 2023 21:56:23 -0700 (PDT) X-Google-Smtp-Source: AKy350bFgdqNYJzfmMNmq0zhNdVtC//UOhzN+cXfFfAK+Hh6roanFlbd/f9KXZiSE5FWsrGxuFfj X-Received: by 2002:a17:906:fb08:b0:8b1:2d0e:281 with SMTP id lz8-20020a170906fb0800b008b12d0e0281mr23533839ejb.18.1680152182963; Wed, 29 Mar 2023 21:56:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680152182; cv=none; d=google.com; s=arc-20160816; b=GEcfSo0H3f1pw0rV4Qsw1xTxMgls9L4PFUnZldw10jA8s9RmDPZFWbLojfEorQ8jsP q9Ls1BnLUGW3ACg747J/LvWSzyH4A+v2vJlO77E6t6VqAg8dUneGXiuKTQyJGnwl5bCo 96g+2gWUJm3HxD2BnAvvVR+1d+3uhm7YfbMdTzg55dNdWZU/XGjzGBU1Q5JNrpXK2YIh rSg9G8VIk4a674vT8FXg+flTER43ZMqQBB6g6d1W34H787pciT64PcKHTtCY6ktWMd7H y4iUKvgfm5mZSy6IpIhhdxAtFogbv/SPmsGaAO+1xDCGrPpvDHA6/awJgspCdDbWVAvT rkYA== 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=rwVPaXw5dJAdR236vc9B5esZBTUOYR4MIU5q912I8Co=; b=h54b4WgH+ggjK65en2StlbHVW1pOAb6lpXJw7lmxDVeClZ2dFfv3pFKv2fal+LFl37 rcBAAdJWOG2ORsRM15qb99Z0EhseU2zbY/CJxZU5oYOQF8dhLs88wyegnAHaYDa584mP yXKBiHc0G1774PxI2UxvglNz+c1Odiz60viB/y4HSFs1MkrlcM17bOuy8W17xRd+Zkel VQGy3scAouHedeZH/UQ0Ld/u7yCz3D49uXfUSgmiHHLW2Y+JE1B0k2Zafnm2cq0HIf8I 6u1wqqJ9PQLlE4ua1L2MZGvn68OTyzZSjHMIS1fnrlBc/UksdNAyh/oufEsYEcGdGl41 cHaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=YHZJ+DH+; 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 g9-20020a1709065d0900b0092be21ff08dsi33514573ejt.536.2023.03.29.21.55.58; Wed, 29 Mar 2023 21:56: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=YHZJ+DH+; 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 S229955AbjC3Elb (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35706 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229919AbjC3ElR (ORCPT ); Thu, 30 Mar 2023 00:41:17 -0400 Received: from mail-oa1-x2d.google.com (mail-oa1-x2d.google.com [IPv6:2001:4860:4864:20::2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B2705B8E; Wed, 29 Mar 2023 21:41:05 -0700 (PDT) Received: by mail-oa1-x2d.google.com with SMTP id 586e51a60fabf-177ca271cb8so18568051fac.2; Wed, 29 Mar 2023 21:41:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151264; 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=rwVPaXw5dJAdR236vc9B5esZBTUOYR4MIU5q912I8Co=; b=YHZJ+DH+gFhYhXOL4EpuCUuWZVtRNTCJph5XrenpP2LCq0jE9aH1dzWVPUbQjW7lmZ ZZuS2+JzZeof2xWJStF6El/p4Il6N6N88Ym/ij84pr7osfsFJ6RgkGsM1Srct/sE+dFm F1MbzymrD7D6fji7iLVw4NUYLHt9r3O1Cn6pMuTfDlu40Mlav+SWHvWcvIKjqucMaJf2 VNJXx9PT3pHzCCRlPYTspPyJKEzDziVSHhEo0i99FmSEk0IKbUdKx7INk2kLQkZeiLb0 jLOsIN4Qv+/JMj5nNdT/vSDconDDc0H/FAeh8hIGf0PLlG7i7uScQy0ZHVAgK+svvc5f DVfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151264; 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=rwVPaXw5dJAdR236vc9B5esZBTUOYR4MIU5q912I8Co=; b=BTgq6xNhaAH+3d6ffmDVSsKbuaRr6K+iuJcl7S3Fkiej5DCvWkWs0VfJvIMm2671pW UiOYzP3op4HzlvICSPUXeRuSn3cWIIqJsHdD7o9Cbm3yWrl/IbNlZQxMUXsTgpdwH1g0 UbYoEiTY0qG+S7ubeCKkD4TG7uTFFz/igJLwp3oCQkCHI9VHRn7zlnIwuIaSLoCW0Lh1 WLP2ANcTwZkErHbs3pymSiksJaM+nbFIIVBHCDx2KT149r03UqfToRaSd1E9SZ7+jjnO GeH2DNdcJ4PkuanqACIswQll5WoaX8x9/SpzqFwBvWWhmFxb6A+B+PbYpSNv0oYL1wGc Ot3w== X-Gm-Message-State: AAQBX9dDm3UEJVcp3bj/gyw+WEquudyb0wPRyEApaO7U18exz4hWClJz +vzZQEVJ9vPiSW34JA0JBg18ZDKbyYm+zg== X-Received: by 2002:a05:6870:d1c2:b0:177:b8a2:5854 with SMTP id b2-20020a056870d1c200b00177b8a25854mr15439158oac.45.1680151264383; Wed, 29 Mar 2023 21:41:04 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.40.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:04 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Peter Zijlstra , Ingo Molnar , Will Deacon , Waiman Long Subject: [PATCH 05/13] rust: lock: introduce `SpinLock` Date: Thu, 30 Mar 2023 01:39:46 -0300 Message-Id: <20230330043954.562237-5-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761767255443016728?= X-GMAIL-MSGID: =?utf-8?q?1761767255443016728?= 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 --- 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 Thu Mar 30 04:39:47 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: 76880 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp872407vqo; Wed, 29 Mar 2023 21:48:25 -0700 (PDT) X-Google-Smtp-Source: AKy350ZdjA9ksve1sq4vV1LG1UqFd13dqYW7GnJ3DJwzjrjfrICEk/BTc05zg5mcSBpbmd0lkhSL X-Received: by 2002:a17:90a:6805:b0:233:e305:f617 with SMTP id p5-20020a17090a680500b00233e305f617mr23207531pjj.32.1680151704731; Wed, 29 Mar 2023 21:48:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680151704; cv=none; d=google.com; s=arc-20160816; b=R4FPUzf7bqP/AUWHElDMXWe2XkGk3Qy5pG8HlGN+32nDhyNFJCyPbJ0pFs+Rmhd/AT x03C2pLadt5zSJeBX2/ewJdXoyOsV5xakVsqt+UxC9bn2hTBp1FXfkF3Q3V2XY/EsG7j eDWSdWzdk8l++pE0vpJhie1AzpustW42LIA12eaFCuWfZwlafvNkWDWhFq1t1Z6mA0g5 sKmJONaGH++ULL2TLborMohYszSsBiRU9PiwCnUOP2I72YifW4U4h3SUNJF51NkJ2gBu 6RzjKGMzBxzGzO1uwnP/STXDBcmK40Eajjer4A4U2ouE3mmS4KZ98TYp9Ien2JmeQ1Q/ 7SHw== 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=u/B9dFAeaUqrqqXcKIk+Y/eQ9yVG9iQNTR7il5e9jLs=; b=lR/0qZAnd7MeWhA9EYW3qeFFEJpl7zFQGcIiTi8xBdRgNrz9QUPabbem8C21/LIgzY oBc8tItuNWydMrfYs61W1tavzq4C5y29AXnQHZT2PHkCA7rfN/nz6M6U2tkFjsRCQQS9 UydKafjNvM6998fZBq2+pR5uNCW7LGbr3B7vfdSbLnAC6OtlNJMkiAbu+DjJgSN1TLZP K4QhQN3tOo+FV2Toq1veFf2ttecttU+cJw9i176Kv9jvHrWBZMEcY/88VGlI/rwrA1vl FhXd7vWxan+yqhrwgRVdFsGczVrtEuU4318ln2iI7iGpyfOI6aesr/6ATq4zUazUQwxZ 0Pew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=FBldUjeW; 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 ne17-20020a17090b375100b00233c73769dfsi3078142pjb.120.2023.03.29.21.48.09; Wed, 29 Mar 2023 21:48: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=FBldUjeW; 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 S229948AbjC3Elg (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229929AbjC3ElW (ORCPT ); Thu, 30 Mar 2023 00:41:22 -0400 Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9AD2255B5; Wed, 29 Mar 2023 21:41:08 -0700 (PDT) Received: by mail-ot1-x331.google.com with SMTP id d22-20020a9d5e16000000b0069b5252ced7so9390956oti.13; Wed, 29 Mar 2023 21:41:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151268; 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=u/B9dFAeaUqrqqXcKIk+Y/eQ9yVG9iQNTR7il5e9jLs=; b=FBldUjeWmTnMcGDYtqPGJOtkr5qqAbx5XiPvKUIklDArae9Xj9CeCHqo5AgHV6DmJ8 7VYNkFwXjHt4PiCnF+qGoy4piOQ79h/06J07fzF9g5FmSl5EQ8XijZ7ko5HcBgGDj9VN /4QFZCOftuHqdU3uFgL27j225r4bIsAFt1dSBzTyi08LjsDzas/byE1wbN1j+qk/reYm notFF2U2pairKLHR4xcS/GOOvf5ZRL5zq8oTEYoeXLobavX7T7GvXuk79j2KjtecFyVK OhnnTSq5hYySGzqeWDgy78MFf4lbW63A37vRGZWAKb+MzYToslbH527fdxj4M/YLnlNI QUJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151268; 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=u/B9dFAeaUqrqqXcKIk+Y/eQ9yVG9iQNTR7il5e9jLs=; b=ITvSaEUzvQD8Kt+lA8J1CruVuHlwy3d8+9NLWQGviMt91kGCYuyJJZuDiYaq8jqc8O lEaGEKKv8T6aMXqmOg1AyOEWp5VYYfyuotEyJrGdnAwFs6vLWgXWxcc1aogEZP0iR/j6 SKE8oiR8PbXMqBa/2RF5CnMI6jpvHXxEQi2VR9Ado/Gtj+C6y4yFtOMirOaclD6d5sSZ dNC0LyW7pIRzWVWQWXA9Bo/eLE/icN2oqbJRWSXwM6V4ni7lH0HluNfnrx5vC5tOIuh/ dB45BDyXDoCahXFKwYvHryZf8fqkoDrxHRew0dt7Dg0dZHZpGSKFjr8a7E6D8696wgk5 Br9Q== X-Gm-Message-State: AO0yUKWxTYVW7LUCqfo8xKwas6Q0qu2UM+i0vP4gRkfMZkOSC3vZxpG+ IPiu6KB675tq7iP8dPymiYTWEd44G+NswA== X-Received: by 2002:a9d:6854:0:b0:693:d998:f50c with SMTP id c20-20020a9d6854000000b00693d998f50cmr10533454oto.5.1680151267883; Wed, 29 Mar 2023 21:41:07 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:07 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH 06/13] rust: lock: add support for `Lock::lock_irqsave` Date: Thu, 30 Mar 2023 01:39:47 -0300 Message-Id: <20230330043954.562237-6-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761766754173428026?= X-GMAIL-MSGID: =?utf-8?q?1761766754173428026?= 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 --- 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 Thu Mar 30 04:39:48 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: 76892 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp878978vqo; Wed, 29 Mar 2023 22:04:42 -0700 (PDT) X-Google-Smtp-Source: AKy350ZgkIDhIjNJHiJo7HZTUbESCXYtjt4Z6roV7vS1w0EKyczHxy/K/XTh/rge2zryjJsreSsT X-Received: by 2002:a05:6402:48e:b0:4ad:7056:23a5 with SMTP id k14-20020a056402048e00b004ad705623a5mr21278795edv.14.1680152682733; Wed, 29 Mar 2023 22:04:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680152682; cv=none; d=google.com; s=arc-20160816; b=rg9fQ5NnT923B/Pvr9kRQlxTv8b4yXtDL/bh3jDX5q08YnNlQOMLzv+a65yLORY3j+ ezRb8aq+iWFN5fk2QEGTPPMOZlFZ7r73Qmj8RjKQE0lw9PPkrMuORn/6w3obD9UMpzcQ 7zJcDhjR+xZlcTOXC5c2wWt8ikB1OqyDceMW22gAukM2yFeHyfMK6QhhcDPjbMjTjL1a 4X7tiRmifmfrGEA2ezXfOEUkH+6gY1swm559UKxzZDVVEelSQ6afEy4hy4/85JhflgIa fUdX5kaK9wqNXCMMb52ZOr0wwtWhBUPG0CnSdfH4iLEnT5WCbB1WLxNjUP6NDs6k5a3Y sIsQ== 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=2cn5PpHPjbVKiTpn7S4FdRJhabCdix+uDXiUAvFeLWQ=; b=OQdzprNIX6nmUKS1O4ICayBhqVXFkyY+LmBR/2FfFpAJ0kStKuRrg1d24OteEPrQ+N E+JgtP6gmyyF3QrNSWraOTVOBzk3mQMsgZ8+NiQt7C6u8OryS/bycRpxiaaeW2uUffit HY74Coret+NUDt/hKswK7rtg40wx0zCl2O1oCeKsZwi40/3fQ9rGxRkcg9LsDTmhRiSM LYXpilbOl+o8E8Ja2IAmOLPDlcm3hRnEQN8mlAt3sI9BWNt0H5Uw2qRxAlMHDKuXL+x1 izivVJylzEqE1jPZIfLqBZ14BmYkZrBeM15SFxrYsGHe+HPbKQIwfvQE8wu/f6WM7lWI Gi5A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=MLmE4Qc5; 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 d12-20020a056402516c00b0048e82d753a3si35306534ede.227.2023.03.29.22.04.18; Wed, 29 Mar 2023 22:04:42 -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=MLmE4Qc5; 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 S230052AbjC3Els (ORCPT + 99 others); Thu, 30 Mar 2023 00:41:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36962 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229970AbjC3Elc (ORCPT ); Thu, 30 Mar 2023 00:41:32 -0400 Received: from mail-ot1-x336.google.com (mail-ot1-x336.google.com [IPv6:2607:f8b0:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF3D255AA; Wed, 29 Mar 2023 21:41:12 -0700 (PDT) Received: by mail-ot1-x336.google.com with SMTP id 6-20020a9d0106000000b006a177038dfeso230217otu.7; Wed, 29 Mar 2023 21:41:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151272; 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=2cn5PpHPjbVKiTpn7S4FdRJhabCdix+uDXiUAvFeLWQ=; b=MLmE4Qc5UnH4btH/GC2TwCy+UCPp008eyBc8f+wKjsnmwOFtSq6B7qKG9mikCeMp0N 5Ynr1qpJcjIRFvjedJwWLo58Y7ensDgVtTwk+0grH6s1r7EuT+t32S25JhRXMdpSz9Fx 4LaLflnqOYvzjIeSKa5VJ5LdfO+56X3X/gxwRbRDX/251LJQFxjVUKCU2cM4qslOfzHO MH9cGjfjS37ZQdQCOBpUeHDexsgexJJtNUr44DRxNhlIvwO/IxJgW3+d8tkmeZ0A6sDs fXCvPurehpapPUZO1E9Km3uO55GeHhUeH0tdAQltEQuVvhNTMoyXkZzaudaC19cJ0/In svXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151272; 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=2cn5PpHPjbVKiTpn7S4FdRJhabCdix+uDXiUAvFeLWQ=; b=Sdjv2PGcj44RO5p+lXIYpcQjV5zyc4zQSTTdKrCN7uFI8LQrYya6e3qsSX3hb+t5Po EiaikeAv51uWG2hbftGV+ffeO5Fm+JAaQqi9FJTyc3o7+xvxIWooMPwgPfPA9shHCwWc +F/Fups4gEXQxYI/iTlGn1KyZKUWsdxR//fN46PDSO7fUj/p7TOQ9wt7/D7J8E5grZkH +WI1QGchTyn1gJ9tAHc5b5pKrpUVowHbKAXA45besn1kP+Tk8GZvGRv5dZXF4xJ9YLqE CMgd/OkAM2jlOHpqGTeduDnTiIyvRiotj+re5T4OuZymOlhzCg2eeSKYkC5npClIxQZA F0XA== X-Gm-Message-State: AO0yUKV87asP5/2UNvaHlqmFXLaKbxByEJofLnLerQOssi5x5RbcJwL2 l32PImcALGMbhh3fkAJVIB7nPjgJr7fOtw== X-Received: by 2002:a05:6830:1602:b0:699:f81a:14bd with SMTP id g2-20020a056830160200b00699f81a14bdmr10935792otr.30.1680151272285; Wed, 29 Mar 2023 21:41:12 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41: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 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Date: Thu, 30 Mar 2023 01:39:48 -0300 Message-Id: <20230330043954.562237-7-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761767779446094635?= X-GMAIL-MSGID: =?utf-8?q?1761767779446094635?= 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 --- 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 Thu Mar 30 04:39:49 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: 76886 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp873374vqo; Wed, 29 Mar 2023 21:51:03 -0700 (PDT) X-Google-Smtp-Source: AKy350asF4upxx/FN/CuQYQGINprGZGYeRhCpvznnpFnAlvzIxyGiq+4NmaDgmvOJiS/qq8Dqv7j X-Received: by 2002:a05:6402:658:b0:4fb:6523:2b38 with SMTP id u24-20020a056402065800b004fb65232b38mr22905510edx.27.1680151863361; Wed, 29 Mar 2023 21:51:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680151863; cv=none; d=google.com; s=arc-20160816; b=MqZ4ezrOyT/GcXDbmPa/vW/v4NYw4LdhnjV+7YCMyyP811Fn+CFWfXnXXpufuFw3PP OA7MmLmXEs+YBqjA/QiyDceC86ZbVffnQKnBUcXruYyglARWEaVXW8278Zh/HFr1+Yrs aJlEmHTKNCeOrJJd16HHXlMVWJe4p6uD+fX/IMcrVBUI+/jPn8B6Sr4Se2YPI15Gdvwh Wh2rbt0ZqmC8AA7G7Z1r+nK9bq0+jwxPB8QGnAix8p7itd8YtwNzQ09bz1mK8dm3M+YN EmNAxDnDpIvmYlHGx5NvkaqdyKi/YsZTmBiiOPDbLDC+X7flXK+xuMjYYN0/A8PKFdZN cBgQ== 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=ZIKW7/0TFQl6GljEgB3wW2iOFuiG0GQhzQq6GUBT1ww=; b=nAw2v8i4ojNK6FUWNZwVK3cUnR3f1AzRiBF3a0DbmIUvGSuy5mQZ72IOqU4x4XxT6L ELCMJoGObG1Xb4Eh70pDs0g+0NZSgjpVKT5D9wcQ1egkn7R/dKfvyKJTHjEfqr6JbJJi oFcHwMFCrMPMJBiHx/y4ygjjBM5zBUpN5VE3f8tAX+yvcrmc/ewqW16uY99DOCZoQhU6 c9K56VVe7ZJ9bfzdLgyz/icJFOUc9ATTNobYlsg6qB+6qM93LvK4Kxw482TtWW7EwLXT gRObHMala2X5zlZOl+GCbUJF0rFdC4NCEUj4LoQu9ajI52lkfJB8Gx0D77QXrwnkHsZY EkSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=b9kU6CT3; 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 d19-20020a50fb13000000b004fd2b13b203si1345379edq.550.2023.03.29.21.50.38; Wed, 29 Mar 2023 21:51:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=b9kU6CT3; 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 S229951AbjC3EmB (ORCPT + 99 others); Thu, 30 Mar 2023 00:42:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37032 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230004AbjC3Ele (ORCPT ); Thu, 30 Mar 2023 00:41:34 -0400 Received: from mail-oa1-x30.google.com (mail-oa1-x30.google.com [IPv6:2001:4860:4864:20::30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AFE8A6A58; Wed, 29 Mar 2023 21:41:16 -0700 (PDT) Received: by mail-oa1-x30.google.com with SMTP id 586e51a60fabf-17aeb49429eso18554849fac.6; Wed, 29 Mar 2023 21:41:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151276; 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=ZIKW7/0TFQl6GljEgB3wW2iOFuiG0GQhzQq6GUBT1ww=; b=b9kU6CT36DIeFiFv2cLFVYwALpVHAH/iM/S1SgYTEqa+2W1Bii+11r9TC0fQ7CJgS9 u9VrmW/kP9KJ589PWODX8gDnc6xNODs8+pBNrwRwR3eTjeSxA+eJTcTI4nHV7ItQuQ6s ofIMO8Nv9EB79Q2CEm3Ie5y2UK48BIXn93J+sipvKOQA3eDNTqKwOGotAVeggVLpgIA9 5ByiXTB17NqhXHWkIOXmsNR+2dqopd+1+jJqjYeNCmQBqs/wamOZ2zwcbJ1zou+iRtcy mn7z2SCQMmAH8anq6fp4mp0/8aI/R21LeM/RQWYw3itaPYgIunK5RQ4b+5Bxmv186TXR Oalw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151276; 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=ZIKW7/0TFQl6GljEgB3wW2iOFuiG0GQhzQq6GUBT1ww=; b=4/T0jIpILRVAcucezL4ibUZ2seRVVSBtjW4acVIMVRyEkz3Mn8QKWweN2tkVCook3H m8RDgHHz2nid1yAWpbNgBgZ3tZ7ICbjkr37HLacqdxD6gWypqoKedDyB4ED+b5e7q5FQ rmU7Pmh0dZBoZsaOYlbeZxDbNhY8hvVhFX4SpvQaMRXZYBfvCaH76oqO4sqATFJvYG8P py+Dy2rsWjHZqJxxWddgY6goRgLeLbR2RfPh0xKnACOIj2jCTD/Vj3pVbqfCVdmQYvKX NKnuSCsnPmhMzq5YPwFe9kJ75GY4IFS5K6aRQ8Gvo9exHzeuW+W3rqCEaEYDVtU7o/VL sRZA== X-Gm-Message-State: AO0yUKWEzD8fFOaTKS79xplKJDfwUlyoTtr8oM3SOaOkOoyKdaTxaSyo Dpsc3tBTK/4Z4XJfWJGqTmZzfBdg8nKzug== X-Received: by 2002:a05:6870:4581:b0:17e:a4d6:5e0c with SMTP id y1-20020a056870458100b0017ea4d65e0cmr14683787oao.23.1680151275756; Wed, 29 Mar 2023 21:41:15 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:15 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho Subject: [PATCH 08/13] rust: introduce `ARef` Date: Thu, 30 Mar 2023 01:39:49 -0300 Message-Id: <20230330043954.562237-8-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761766920669332897?= X-GMAIL-MSGID: =?utf-8?q?1761766920669332897?= From: Wedson Almeida Filho This is an owned reference to an object that is always ref-counted. This is meant to be used in wrappers for C types that have their own ref counting functions, for example, tasks, files, inodes, dentries, etc. Signed-off-by: Wedson Almeida Filho Reviewed-by: Gary Guo --- 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 Thu Mar 30 04:39:50 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: 76888 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp874410vqo; Wed, 29 Mar 2023 21:53:54 -0700 (PDT) X-Google-Smtp-Source: AKy350Zz6LSmMJ1zxBNBFJkOYmhPwmGr1ro790uKrdl7zpns0XcB/ikxazw0uxq+r9YMN8/ib7RV X-Received: by 2002:a17:906:198e:b0:93d:770:25df with SMTP id g14-20020a170906198e00b0093d077025dfmr21739915ejd.37.1680152034310; Wed, 29 Mar 2023 21:53:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680152034; cv=none; d=google.com; s=arc-20160816; b=BSeGkpAiAx5KHWnK7D/KKHgvBgtqpBa2j4njjorlwU+ER0jQKMf+HygZCaWDqZGimG YAF6gugRC+qJAnk7f6n65WycZbrAGAzzAPTstoX5PPmyH4iYVuwjiEWb6S/XV6NJ96hu 1gllEPNR4Ml42rIffc/MPzmejgESkzKq8Io3cyOlo+d4f3/71e3CN9DT8Xa3xTUP3+01 rzVFx7mdeY92cu++ZEHytVR1F0l14k74UtOI6Oobfk4EaYm1vlq/LfPgbUXkuLZR6PRX 4tFLUpKniC1ex4zFN31KfsGqjCTQGTFjbhHRlNOGfUq8yuyQCLGkmuXur8otIHuS90bg DWfw== 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=zAQl24uzq/qZWkhqH1HEWNCra09kYwVNNfNYBWyzFHM=; b=F40El0kgJMTnGmPugh6qwER9IeCvVAlU0nY09yv4GBTcDqtKG27g8V/YnBFK+Szmdm fVn2mgX0rzvUQC5BXj7DZXvefaeQ9Uskb762Q1go3X5xeaKd9drDTk0X86yx67WFy4ZF BqDYYwFqa2I/y8wLuVgdfMw1QUUwybxoUgaR9RLl96AMF/IX/neg1BGmaaaDBh6a0bpk FATiYDhon6y1/aMuENuOHbgAoVpFcMZdPR05ewkEStNWii+vrvZSRZC0bRbYXusSM722 P8rH1g3GxlnZXFcwbRBn99ASWzVAmgPhD8E2rhM4xmqX4rUWwD9sGBmejboEzZ1o9Dq0 CDfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=c7DhaZZt; 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 q6-20020a1709060f8600b009318c913c59si32914607ejj.525.2023.03.29.21.53.29; Wed, 29 Mar 2023 21:53: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=c7DhaZZt; 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 S229525AbjC3EmH (ORCPT + 99 others); Thu, 30 Mar 2023 00:42:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229882AbjC3Elq (ORCPT ); Thu, 30 Mar 2023 00:41:46 -0400 Received: from mail-oa1-x36.google.com (mail-oa1-x36.google.com [IPv6:2001:4860:4864:20::36]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 234EB6E85; Wed, 29 Mar 2023 21:41:20 -0700 (PDT) Received: by mail-oa1-x36.google.com with SMTP id 586e51a60fabf-17e140619fdso18534384fac.11; Wed, 29 Mar 2023 21:41:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151280; 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=zAQl24uzq/qZWkhqH1HEWNCra09kYwVNNfNYBWyzFHM=; b=c7DhaZZtXvNu6XNyp2FpwbhUnTBCh5j2kl0MvRgvUaucf3SOtXT2Zso06U+9WU6N71 GutSJ/y0hGfHiHkX6C56QJx92QIqI6V87rjiKMMo+GVFyyxux9Mt9V7P9QA1Oa8tM5vB k6Ro6gFWBJLRI/TEdwkR9Og0XKpy++cn3rlXtXA5PSsHT8mQt8id1ByOBAl7ouBBLHET UEXog1W1s9WBJHFjZFnRytAznRonVGYRv4tA1+mIgai4Br5Ba5arMXxSUyfwH2v4N68T r/k2DKFipjJ5ScrTfRDd3TUdXzDXJoF+5eOjZwE8yBtXNAws0oCS3+0wqQEA/xqA4ym2 e7Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151280; 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=zAQl24uzq/qZWkhqH1HEWNCra09kYwVNNfNYBWyzFHM=; b=Y2FQAN02G5I3Pm4Y0fhVDnb9ckvk+4LNRNafkHEbylnShiLKLU4ktozoVU3QLGrGy5 e1VzDznAkb5qP7BT55mJ9cb4GWAyJjTjVsua4wx4rIXY4zLLloP++PUBgIvdq94wf/el v7bqgTH0/hsLuI/USmvQaoRe5SA35/k/OiZWblsUrBE9LeuUEK6qo6hEZpNKPZam65lj rE1V4mP+0aIRV23qK0FOg0KyyEroSp0BnlQD+H5YXdmSMUo1Tw1TDqCJQwsVeI5qe4gq j97SPDZKqznv4nIqT4QltVpyPSYugE7agKnFLKOcMIZw2JbQN8Xfmzpwibib5UHHUyPG IXsQ== X-Gm-Message-State: AAQBX9ecyGCLQmY9msBSCpiXJoklwEo2pS7pP+RPmG9EzqOsNp4YY+G7 dEb2rG+8EyP9p66J0aO/r0tgaC3gp16s3w== X-Received: by 2002:a05:6870:899c:b0:17b:1a4f:adfe with SMTP id f28-20020a056870899c00b0017b1a4fadfemr12302843oaq.10.1680151279864; Wed, 29 Mar 2023 21:41:19 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:19 -0700 (PDT) From: Wedson Almeida Filho To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?utf-8?q?B?= =?utf-8?q?j=C3=B6rn_Roy_Baron?= , linux-kernel@vger.kernel.org, Wedson Almeida Filho , Ingo Molnar , Peter Zijlstra Subject: [PATCH 09/13] rust: add basic `Task` Date: Thu, 30 Mar 2023 01:39:50 -0300 Message-Id: <20230330043954.562237-9-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761767099028732558?= X-GMAIL-MSGID: =?utf-8?q?1761767099028732558?= 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 --- 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 Thu Mar 30 04:39:51 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: 76884 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp873224vqo; Wed, 29 Mar 2023 21:50:40 -0700 (PDT) X-Google-Smtp-Source: AK7set9F2lTCEXOSMOz0aKg/ocr/Bs92aNHbV996Q2XQe1+qxtoOgSw0GTuYw18b1kpfYw0R5A0O X-Received: by 2002:a05:6a20:baa0:b0:d9:ecba:b9fc with SMTP id fb32-20020a056a20baa000b000d9ecbab9fcmr16859145pzb.54.1680151839815; Wed, 29 Mar 2023 21:50:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680151839; cv=none; d=google.com; s=arc-20160816; b=ytgXBa4iozeOsBOprtMCgjl2Ss3qevJ28QKBQ1dWEs0q1Gawm9Pt6CNTBlU3EnKtJr c7EGNoCxuKavV2GNLRp8fFByhXfymBLQA7esDoloDh9rHuCF03vLh3DCCodTROGogMMk lC5gi7rHllEKLlOMozIvJHH8ugvwUt9oI6XV374oi0koDMKrrtBkUvEh5qw6I+z2xPlE xq9fWI87qEGyIpxMy4NSmyt5fl69rzw1pnB0zTgMaDOZN8nHJ8Z4DmxQIqpCj0cuIaK6 OgbqVuk2xs7Zk606gn89QiapzlsEoFPvekYv6Z1zV5fPwCiD7r+UDiIugDSMBt+gUsl3 HmBA== 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=JaygZpxwnfzBcLtVwosxyCaJLz/HPg5F8ZKIQhWNoz4=; b=qJf/j4AB4t4Vxm2Z/0BZPL8lLUfFa5wk1sHWC4qYMuak3pD6Si6KK4sEqQFvtS+skv rR0IFVpREekpaiUlBy/fwtvebYixC9Tw5IlkbMOlvRzygGLDNw0Mtc/nDPsH6SkmI8O4 gp5/o2POJbQfS9ZvKWHjAqF0U6g+HZZsvCik7lC1ZPMxE82dAQUbcT9AiZd3MDsp+L2h gQZBju1FjNtbQo+Pe5gpL7mA0lJTaB1Gaqd39kFbzg9dEH48PgxIURT3UdB/f8bUt/G5 5IAzhdaRGnakafOrKdZOEq2+cLNE0xRZWbTWI+ClFgdI9TH7JseQnbB8lTz3rpFvvEtw zhTw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=FXwYLvrI; 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 bk13-20020a056a02028d00b0050300b179f3si31536833pgb.444.2023.03.29.21.50.26; Wed, 29 Mar 2023 21:50:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=FXwYLvrI; 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 S230114AbjC3EmU (ORCPT + 99 others); Thu, 30 Mar 2023 00:42:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230076AbjC3Elv (ORCPT ); Thu, 30 Mar 2023 00:41:51 -0400 Received: from mail-oa1-x2c.google.com (mail-oa1-x2c.google.com [IPv6:2001:4860:4864:20::2c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 408387295; Wed, 29 Mar 2023 21:41:25 -0700 (PDT) Received: by mail-oa1-x2c.google.com with SMTP id 586e51a60fabf-17683b570b8so18516016fac.13; Wed, 29 Mar 2023 21:41:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151284; 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=JaygZpxwnfzBcLtVwosxyCaJLz/HPg5F8ZKIQhWNoz4=; b=FXwYLvrIzNZooIRqEXJqa42IDRe+8JDe2VQoZkMZuHOEcfRdn08oqkv775h8AUEPhr VZOsHttuI0VIspAYJOPt+At7ZMsiWn6j0wNa43Av9xDCqbJet7GunO0Wa4jrQ4rm0mfP 4U7FZGZYhIBZCmpV8m108tEsQViHPoE+fUU7a5b1/B6/k5MQRcI+6GtnaFurUZA+AjBx JnEmRrtLnioJ51uu2QXp1WJ8ziQF53zY2xaCGEcOAAU5lwY2OXqWlVtpVjbfIfdIcynU CrT1EgHq9/TV1c8no5FMUS9cLfZLNDV10Wq2g2VJ0M9tK6NoQdzqmfoR1fyEf6/8x7hp BvWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151284; 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=JaygZpxwnfzBcLtVwosxyCaJLz/HPg5F8ZKIQhWNoz4=; b=llVRs/xwipp41Ff97GxmACqOzcnvkUqvj/RzRdw38IAR74HXyJ2qBzfsRSnFCH+fel sLDgKCxkmd14fcbuhyvvzboZ9hnxLPlZHY/Ypewbj2ztAAykteusvh2etXvrlNC1VR1W kW7EXLuKA+w8Cr8D/NhF19uy+PVSB0uT7BugLX6iwz7twbRcpuEVWbo7VEXLFykmmdP4 pg9Ku/4zKF87i6Ph4rJWqotdRTYcb21oqm58zwCORV+1SGtudkEERMFdf5uoVFEpuMNP wGXLfPE63lWJQ7CnzQkgQOZWB0vaSt2GP0Wlc6LrsySQGDOgijtVkKGjSHVBhJSETHVd f0Kw== X-Gm-Message-State: AO0yUKUFC65PnvCx0qN4lmiSagHswUuVBRFm89F3IQ364PG9RzZM8tqW hTkrCLt7gge4BWVegUiDAma+SknuEYcyJw== X-Received: by 2002:a05:6870:459f:b0:177:9b62:6b7e with SMTP id y31-20020a056870459f00b001779b626b7emr14014751oao.24.1680151284471; Wed, 29 Mar 2023 21:41:24 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:24 -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 10/13] rust: introduce `Task::current` Date: Thu, 30 Mar 2023 01:39:51 -0300 Message-Id: <20230330043954.562237-10-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761766895922170847?= X-GMAIL-MSGID: =?utf-8?q?1761766895922170847?= 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 --- rust/helpers.c | 6 ++++ rust/kernel/task.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 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/task.rs b/rust/kernel/task.rs index 8d7a8222990f..8b2b56ba9c6d 100644 --- a/rust/kernel/task.rs +++ b/rust/kernel/task.rs @@ -5,7 +5,7 @@ //! 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}; /// Wraps the kernel's `struct task_struct`. /// @@ -13,6 +13,46 @@ 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: +/// +/// ``` +/// use kernel::task::Task; +/// +/// let pid = Task::current().pid(); +/// ``` +/// +/// Getting the PID of the current process, also zero additional cost: +/// +/// ``` +/// use kernel::task::Task; +/// +/// let pid = Task::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, ARef}; +/// +/// struct State { +/// creator: ARef, +/// index: u32, +/// } +/// +/// impl State { +/// fn new() -> Self { +/// Self { +/// creator: Task::current().into(), +/// index: 0, +/// } +/// } +/// } +/// ``` #[repr(transparent)] pub struct Task(pub(crate) UnsafeCell); @@ -25,6 +65,20 @@ unsafe impl Sync for Task {} type Pid = bindings::pid_t; impl Task { + /// Returns a task reference for the currently executing task/thread. + pub 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 +123,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 Thu Mar 30 04:39:52 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: 76889 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp875098vqo; Wed, 29 Mar 2023 21:55:56 -0700 (PDT) X-Google-Smtp-Source: AKy350bUmVDNGD105UVkejc/gn5sZAI8yfKqGhRN1Lj91GnLb2DoWPdlT3gjo+zZNeIi1icp09H2 X-Received: by 2002:a17:906:85c2:b0:88d:ba89:1837 with SMTP id i2-20020a17090685c200b0088dba891837mr5211095ejy.8.1680152156421; Wed, 29 Mar 2023 21:55:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680152156; cv=none; d=google.com; s=arc-20160816; b=iooc1GqP8Ow+s2qV2P1jkCgoBurY4fCo6llXf36H8iAlWo7zjeXSMTuop7wtmSbEoy Z5lgLCdnTAH6fVnasGPRJpzeA5e2TwVLurZdSufbyiTjWambXYu1Y0+uSfMnhXVkwqcj 3Z9LmV8wBB5BgEfvF0CKPeN3SkGBjmPpIZnQ+FJHzdYYT4kpKMGvQKrFIskvF9p8MfLP A/21FYCvTx6HIwk+Mfgwi0WdtRfwSy9udvTWo6jhfUVewdUCi0tqMHjfKx4QeI/kRuNj h/wiExOivfXShfPjONF/QFoR/warRvVf0gre2xMhjwlY3KuKMPBajmbTY6lYzn0pBSmM mrLA== 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=+k9eisks9FcQh4zOi/rvuQMJbaN5Xl9dCC+VIC8uz5Y=; b=D47m1dtuC4qhdTTPGjP3TxVfg5o/eJFyQXucsiYBCt8s9Q4oN79AvQv3CCjKvIwFW9 Rmk5db7y24fGjIjPRxJIboAkk3vLE7tcF5LvICYx1xqFqLgt788fE1Aih+NGYvokGYCz ew4Qr5g0wTef6PX7A82QXb50aXbbwJaxO5pD6Be5czHHRI2dp7iAAzb1e156KnGC8Qkk D2WnGYhui9TQUGPnb7hFxaSD0ZCDhS4AIA5ywT5j5BMEz+6j/YX4eE/CbVGHQ3URH0TF bhPsMhyT9fnBP4FjILI2RBWJkcRtxw2Fgla49PGnCljqk4UQG3mUVwKPdaHvz86eB8sB vh0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=AP2q8+v3; 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 gt20-20020a170906f21400b00921412bd8c5si37102119ejb.750.2023.03.29.21.55.31; Wed, 29 Mar 2023 21:55:56 -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=AP2q8+v3; 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 S230133AbjC3Emo (ORCPT + 99 others); Thu, 30 Mar 2023 00:42:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229954AbjC3EmC (ORCPT ); Thu, 30 Mar 2023 00:42:02 -0400 Received: from mail-oa1-x2e.google.com (mail-oa1-x2e.google.com [IPv6:2001:4860:4864:20::2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C6C966EA1; Wed, 29 Mar 2023 21:41:30 -0700 (PDT) Received: by mail-oa1-x2e.google.com with SMTP id 586e51a60fabf-17ab3a48158so18578382fac.1; Wed, 29 Mar 2023 21:41:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151288; 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=+k9eisks9FcQh4zOi/rvuQMJbaN5Xl9dCC+VIC8uz5Y=; b=AP2q8+v38rA/2X+C0rrBDvQNOxnLbHu6WgNvw7sEmc7k/b8sHY2cCCGjLjRmYSqvyp a/NOcziUWUiGlDINrXyFR84YfH1G/ZHwzznNGTqq/64LFlg6qEbABmHoNpO3kYAYX2gQ iHZkDrg7+Mjrtf02NO6WzuSa3WjROyWYPX0sDkDC0PfFDnnJSe8ayYjwhPRtUCB0581A 1aQC8a910pwVPeO1cSPcJBD9hI/Lo3XRf8MVwQ2y2W5GnFm1fI8LGsrQeNC9oWejMJ1m Hil1MxYd1yJxzG/izFjy1Q63ucH/f4MbiqW5ll2nGbOgd+9iS67hREQCdL4/PxMM3fVP IjFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151288; 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=+k9eisks9FcQh4zOi/rvuQMJbaN5Xl9dCC+VIC8uz5Y=; b=q7GabMEnjZGIu6goyLGpZnhbkUBm29G2LFAH1sZeQYtNDj54ZVu3g60zWZVDz0C2mW 7lq4+VhN9P9DvivANvePoJAjqBqQZfdSLtWEdHCb6M7ml3IDyOk5Eet7K/OlxP3vouAl 6KMY41HnsEdCBsDkLgTWAp2eo1wcYJjTqcltnNyKeJHuGnTMp9+wpA9J9fcVROerl12O a2OtcKbNldCXBrdCtAxDquzjMcmN5JgrkzPsIAhJMIuV1aDcKjDkRni52Wi0Pl99DBgw lHEUkIZIjK7CeS9aiqbyr76paXOIZMc4+KU9wBGDzbTKVx7T4od8k16el4hlQomrx5u0 yhUA== X-Gm-Message-State: AO0yUKVGT8Vgd2U7EwmI3r+5fBqV5ltLnWu4EizGoh6YMsc6HAvfirlN nt+Oymh1erMYVe8GKCUYZ5vpmbuyKUxa4Q== X-Received: by 2002:a05:6870:32cd:b0:177:ac2e:fc5 with SMTP id r13-20020a05687032cd00b00177ac2e0fc5mr14654022oac.50.1680151288678; Wed, 29 Mar 2023 21:41:28 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:28 -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 11/13] rust: lock: add `Guard::do_unlocked` Date: Thu, 30 Mar 2023 01:39:52 -0300 Message-Id: <20230330043954.562237-11-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761767227452853568?= X-GMAIL-MSGID: =?utf-8?q?1761767227452853568?= 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 --- 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 Thu Mar 30 04:39:53 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: 76896 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp883085vqo; Wed, 29 Mar 2023 22:15:27 -0700 (PDT) X-Google-Smtp-Source: AKy350bGjGe10RW4TxBTjyOwcTWwIeFcY0Up23MXtjFivl0IkM2ytbFVwpa0o8LEkfgSbnRZxZA6 X-Received: by 2002:a17:907:70a:b0:946:bfb0:de85 with SMTP id xb10-20020a170907070a00b00946bfb0de85mr9776754ejb.70.1680153327167; Wed, 29 Mar 2023 22:15:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680153327; cv=none; d=google.com; s=arc-20160816; b=l7V8l+0JmixZn/xn7jt4LaLpMh3+om0nQjBbODmqi/ivFAwz6lY3E2t9Pvlg7PAcWH OKewvOoiX6S65IT4x7/D0I3gIGzWrtupY1udk5+6s0re4ZLspmWdx9EX+gm22MhLYjbI DzXKLKrw+je2QXz7Mu5UueyMeNhKy+y2T+eLlkm64BFQGwqLNhqmQFvbU1qKpzDf+7WE 8J/UlNrZL+X9p/PFKfzeEeQ91u855tLqSNovx7vJ57IUNmmmqy+JapPQkgVD8VvG5QkG D7XacRPeYqKkQWe/ObZICULW4cM7L/Rm+uZ3PHa48SobvztjmevusmIeRPtqWYKjE+HN 0Kbg== 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=jDQ1ux1FFIBKnkm5RT1u4Ss2PCKeYkPgmEuTF41v1l0=; b=KDXgNZ0PmlV8piBb+jiRrB/y9kk1NbNXaOerKxtfjCKCWvgSGZwI0YQMqqbHdIX82f PR0Vj/KR6pKDV3riuiMjX0C+Lu2Jtg0Rgsy8oRtWkb7LDJgqNCqBKpbuu0truzFpG3Sh HurIYDml0uncBOzb7varlJDlQwyKc4uiA/gIZ+4j3+UaeOTql7KsGvGYvgP6y88q5sIE B0JUorU8X2JJE/GlgtQsLCgOXQ5n4ysxeVz0WX5MKsFgZ0NapjVWiLZV9yz8FrGYQ8/3 pYUKZ1thlaEnDXcGKBsWHckJ3TqVpUXQ4NcgwbxrjgVnUQsZ55fjf/Gsl/UtSqem3BH+ AVJw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=DgeyASSU; 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 d17-20020a05640208d100b004fc2ee858f1si37801466edz.71.2023.03.29.22.15.01; Wed, 29 Mar 2023 22:15:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=DgeyASSU; 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 S230044AbjC3Emu (ORCPT + 99 others); Thu, 30 Mar 2023 00:42:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230021AbjC3EmE (ORCPT ); Thu, 30 Mar 2023 00:42:04 -0400 Received: from mail-oa1-x36.google.com (mail-oa1-x36.google.com [IPv6:2001:4860:4864:20::36]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 115A755B5; Wed, 29 Mar 2023 21:41:34 -0700 (PDT) Received: by mail-oa1-x36.google.com with SMTP id 586e51a60fabf-17e140619fdso18534762fac.11; Wed, 29 Mar 2023 21:41:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151293; 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=jDQ1ux1FFIBKnkm5RT1u4Ss2PCKeYkPgmEuTF41v1l0=; b=DgeyASSUgCjM7B4AF4Gy3TxTUn2cRFAxrwsWNWo/UfzJwf0k0+k+dc20KPZ8TkWs59 goYODEOXSs/MSO2xy/C9BSrGk7djZ51qqxIjXbB4UkysVENSsbon+jXm984jB9kvHbVB 2zhsFhkN7rSxlpOUeCXAvhscvtl1xM1yAlfr3czxXDd1bwHzao3VBoW+F2Oywspo68OP yXjp/s2tRogjJ9/7MVabmZmQNOZrvL4oeeaIlPEIhkrk2n+EPv3DgiNCK+XVxx+4+wFS tWHcmLT/CfxC2sj0cbJIQtXr6oDWFoCsUiA6yh+oqKajnRK2f4+GabA2oW/+eHn6XbGC +0Ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151293; 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=jDQ1ux1FFIBKnkm5RT1u4Ss2PCKeYkPgmEuTF41v1l0=; b=b05CQ22bif3tlY/Sct1nQiRg2eK3g5zWQK9Jo9nHC5mu5/cZ+8CfVoBCUMsbNrdwER kfnZyggGhaDd3WAGu93xcDak/6Q4R24c8t5ExZL0LF8f0JwIHUheh4ewOp/RSnmS55KA HFAtoorAQ/T3k6XHTXGf84JYnBFz4++w59q+rIb7ls7wNtdyDjdHI+e0mHtYWbD4UpsR nXHdjxj68LdkNraifWXp2iUJP93nLZFEInErf5D/0cSpI4XrvITdvRAZPA8bs7GqlQ1a BbPt6DK0dRrjfKDQIUdIh8HLSv3wYs7G967AAw4nKbQm+Qj/0z+ipRdo4+wLv9omVcu7 OYjw== X-Gm-Message-State: AAQBX9ftO9Rlcnj+A8tp5y19eC9Lps0htoHJYbnF+xWN4pms88mKIcqA bN9zBlg50GWf3eYQ0yhfGfjOtsEZWZ5BNg== X-Received: by 2002:a05:6870:e313:b0:180:1faa:7c1c with SMTP id z19-20020a056870e31300b001801faa7c1cmr60006oad.46.1680151293686; Wed, 29 Mar 2023 21:41:33 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41:33 -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 12/13] rust: sync: introduce `CondVar` Date: Thu, 30 Mar 2023 01:39:53 -0300 Message-Id: <20230330043954.562237-12-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761768455226242837?= X-GMAIL-MSGID: =?utf-8?q?1761768455226242837?= 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 --- 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..3f528fc7fa48 --- /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, task::Task, 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); + Task::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 Thu Mar 30 04:39:54 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: 76897 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp883798vqo; Wed, 29 Mar 2023 22:17:24 -0700 (PDT) X-Google-Smtp-Source: AKy350Y7nOFd8UvP000l5y/NJsAxemSwLZsE2Kqh0X4BfK3SNiqJs3wlpqbvjkoS2/WYbNByyiQV X-Received: by 2002:a17:906:1685:b0:930:660d:8f92 with SMTP id s5-20020a170906168500b00930660d8f92mr23697544ejd.52.1680153444058; Wed, 29 Mar 2023 22:17:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680153444; cv=none; d=google.com; s=arc-20160816; b=Nly6A8HMeM8IxkWBVx8AamasLATVsXe5lxdGnbwLJp6KZQYdYqvhoVnBww04mBK6LT /lKZLLuatdHfBIepgsv6BbtDAlmf2X5tHCnlrH/VjkT3w9btLUehZbAImYHlCZUXAnnV dtWHXuVinqQZi2vwLdf7wXAUAly6NIhmyV7wsMa8z01EEiZKslTK5NpU8uVy35Xpt6P7 qFIlkcPWLcfQJNlBg0qU6NG+LvaJJsW6hHBP6S5oFBDwBJggwzJ3vdo5yRXYLLj/1h8e wQzz0HHLV+TVx0URGkv0O4dGwb9eg7BA9NHUa3m/68qSgS04jpVHLbxFg04O3FcK65sE Nc1w== 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=ZtdTMwagWvTyqFDLE8n/H2MEvpwLqJxi8owZihcxfPE=; b=M4fS37ZjwX87EB5Kao038kwKN4vxDHt336xENttHmdV/jQyxdPOaP8eJkg3hWNRV3D 3vZhL0JQOOiAidwP0w5lGUQAOBQ4A8z2key9xy8C85Rua85hjqsa1FZeNV9+EZFJG2jv oNvusbgvBUKI/U7pRr7lUKnHuOOd/xAc3SX0NGS4kGRdCouP16mMke8aoZv56A790p8w bGkIQl/DgsdP6MjHAE9Y5U7J+CSlLzSqA48phwYiLfbBsT093SXAz71ZwTTbrMqGqgEF LXo5Sb6J/ieSZJfR/Lq+KolQM83RAn0wM47KMO0fju5Yk8xdKbdU7mJpaRrOwtefni3D 4/aQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=HAFHUZpW; 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 e6-20020a50ec86000000b00501dd471e58si24055813edr.37.2023.03.29.22.16.59; Wed, 29 Mar 2023 22:17: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=HAFHUZpW; 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 S230146AbjC3Emx (ORCPT + 99 others); Thu, 30 Mar 2023 00:42:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230041AbjC3EmQ (ORCPT ); Thu, 30 Mar 2023 00:42:16 -0400 Received: from mail-oa1-x30.google.com (mail-oa1-x30.google.com [IPv6:2001:4860:4864:20::30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 201F37690; Wed, 29 Mar 2023 21:41:39 -0700 (PDT) Received: by mail-oa1-x30.google.com with SMTP id 586e51a60fabf-17fcc07d6c4so4496091fac.8; Wed, 29 Mar 2023 21:41:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680151298; 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=ZtdTMwagWvTyqFDLE8n/H2MEvpwLqJxi8owZihcxfPE=; b=HAFHUZpWxT3qSD2wPnoPLCaZ5UDuTIvrCv1uNN1BeOYbL4/IS6Rlz485uErRKtu69b Sz7poGHEm212a83mkkSRMnMFB2CAa+zgu3IBD1ftjFiaUSG6DrP3aXAx8WonZFQeM6+k ElIpLFxVGHzLjNgNkSWHg1RrXofiOwzWF9OY3zIVS8oyZodOUlgK/WJXd8xBX/yDRqEk /W8I39ws/8jWZy4/eYe+URo+XmOisZ/FU/Wg1ZJxYWlTfbbr/Kif2mLtXxkvZTHyL0er 3/Jv0xvE6BGQRqXplmDWW2bjTEOodfySEnj0VAJ8fRdXvsBtThzK+HNQx1bG8dZ2WKQG OgDw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680151298; 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=ZtdTMwagWvTyqFDLE8n/H2MEvpwLqJxi8owZihcxfPE=; b=58zN0d5UBf9olSr+vPicz+4B3enqGIevWuxF84nfp5agmgTCA4kkeaBYXn6t4DdG8T Qy0ESHC/2hljOlD2O0Tmjn6ZXTejqSjQH7cLN4XDjR2rIw06STVba3ZbH3cBoUl5EdEt Rs38AwpuPm45uC+AYq0bLvSgNuoztKdS/XPFtrRvndxgHwjGlpdMl7SlNguBkmFL6tNd EgHl170FkJCZ3p2eQDk02OHde5Fyhv5Cben1UgQ+imQirg6fOM6u8foXm9vYKNbDx/vA /++3d4H0bQfWMX6W5to/g0ahWtZUIC3ulguMZWfNenf3fx35bo4qbP3weR0zpK/nlbxg 8MlQ== X-Gm-Message-State: AAQBX9eCZpfduexPBl8NfrN04bW71q3oq11WP4NESGBR62nJAgJ6yNMf peFH/xtxzd3/cze/zAJnLI/wn3X/1TTVvA== X-Received: by 2002:a05:6870:968b:b0:177:caaa:4cc8 with SMTP id o11-20020a056870968b00b00177caaa4cc8mr15409780oaq.20.1680151297693; Wed, 29 Mar 2023 21:41:37 -0700 (PDT) Received: from wedsonaf-dev.home.lan ([189.124.190.154]) by smtp.googlemail.com with ESMTPSA id ea43-20020a056870072b00b0017e0c13b29asm7518599oab.36.2023.03.29.21.41.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Mar 2023 21:41: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 13/13] rust: sync: introduce `LockedBy` Date: Thu, 30 Mar 2023 01:39:54 -0300 Message-Id: <20230330043954.562237-13-wedsonaf@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230330043954.562237-1-wedsonaf@gmail.com> References: <20230330043954.562237-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?1761768577979979805?= X-GMAIL-MSGID: =?utf-8?q?1761768577979979805?= 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 --- rust/kernel/sync.rs | 2 + rust/kernel/sync/lock.rs | 2 +- rust/kernel/sync/locked_by.rs | 126 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 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..cbfd4e84b770 --- /dev/null +++ b/rust/kernel/sync/locked_by.rs @@ -0,0 +1,126 @@ +// 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 { + 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 { + 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() } + } +}