Received: by 2002:ab2:7b86:0:b0:1f7:5705:b850 with SMTP id q6csp1282935lqh; Mon, 6 May 2024 02:57:37 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXnIOzA6sSCPEmowYEN637xy1rX5L0Ujyt7FeZpXa5GkrEkp9h7vxuo74mMUBal/k0ncFA6b44py7aHIm98+LYcFV7TLice4xEpYjGPLA== X-Google-Smtp-Source: AGHT+IG9Jmxxv2AsIegQxBjKCtjXBracOBOxUouXVbOGJWg8i6MjS/z1HhALioZ45kSh9ptkG24D X-Received: by 2002:a17:90a:8d07:b0:2b3:d512:d487 with SMTP id c7-20020a17090a8d0700b002b3d512d487mr8567670pjo.39.1714989457555; Mon, 06 May 2024 02:57:37 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1714989457; cv=pass; d=google.com; s=arc-20160816; b=IjV1Rg5auyC3SUUQ2l7t1OLy1Zx8vVZmg0EIRjMKQwfBcJ63x9Zjrv1cu/Ud8ae73I VP1nUo8rv9UGq+p+SM8S8neYWq+C4wRoeE83jKJ/U9eDPE84LVD7CYEclAqjRLh+nhWb ryaSgrfFJwGI9LKsOhPx42fRxLj4VtFSp4sCcroNTdDXr7Kl5cib/vdTl6H5gx6EK+yR SQVAWwmAlQyX9Yqpt9rI4h0v5EIiO6/+1nJsAevwKSHoANon78MVjJwuOqaFNGt0yERY +pkTtYiKCprh/MIwaefhv1Oxf0OUpXQcF0/cOXcCEkVWvfjbbO8bLXwS3/Ahm7vEZefJ jrJg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=ga8rU6TTAMlW0eYro+OQUU98vsuNjWANwmXQ6mKFv4I=; fh=ej71ZiTazHCXhh1tRgQ0U0GSk97EIstHmUV06HT/uxY=; b=uVXhyN/xNiv/hvO5YK4ByLC218xQekvtAeTtLACNuSW2chcjLTGoOqoZdFXVe/VCa3 8RaLuJA+3mhuE3TpdBDc2s+UAi3sk26XIKbir8gTomck0ubyNtx/KktWwkBgJBvadNUX +HImNpD0eT/AbyF5dA9h5uMleq2pl3xd4ErL6exSCEdx2AHIe3oQAIxWfwWoZKZI//RY JeeoXEqhgM+YmGP374lV60nFVoAyohbRMqeZLCayk2N5csGciqFzyWsONVmwrldV8F7y hKu08EeGzYsZQoZReYCFFcgrsv++FXSVQa1F7GYEZ14R4RLGxpnzz4FCNzo9rH448LoY x/SA==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=gqzn0fww; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-169625-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-169625-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id u21-20020a17090abb1500b002b1a587f549si7750575pjr.128.2024.05.06.02.57.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 May 2024 02:57:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-169625-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=gqzn0fww; arc=pass (i=1 spf=pass spfdomain=flex--aliceryhl.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-169625-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-169625-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 53242B22BB9 for ; Mon, 6 May 2024 09:56:06 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7A8CC142E69; Mon, 6 May 2024 09:54:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gqzn0fww" Received: from mail-lj1-f202.google.com (mail-lj1-f202.google.com [209.85.208.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 965AA1448E2 for ; Mon, 6 May 2024 09:54:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.202 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714989247; cv=none; b=qSFzDjGwNOhI2kNIE/KUXR9RFco1NDtfppxS6DJXq/wgU4arbJqzdlNED0qwvKNx7uhZOB41GoALZDp/C6S3Y9FXx7cSG+YSA4r3EDCnk9mnu5lrwj5AINWE6jq0oPJnHVZcQ6cVVFjsHCSIIfR+8bG/xbs3AKFCMKIDtUrVS7I= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714989247; c=relaxed/simple; bh=TputigRZUR00q1xN1sbsYsPUvr9lDRrYeB9O4vnOPD0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=r2s+ss3O6YiQvSrZhfgUNtL5MzZuNTtjud1zYK/dyzRf97jMLmbP3U6PVa/R8A6TIIC4JH/rRw/aT/dnaR7jGxQBl29me2czjvojtKhnIXtFlwSQHDk2Dhu27SzdGKoyQmvkp8j9yKwfg4vhUhtUvyv6s5fcvso+afn65PXXMyE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gqzn0fww; arc=none smtp.client-ip=209.85.208.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Received: by mail-lj1-f202.google.com with SMTP id 38308e7fff4ca-2e31652ed62so5509821fa.0 for ; Mon, 06 May 2024 02:54:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1714989244; x=1715594044; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ga8rU6TTAMlW0eYro+OQUU98vsuNjWANwmXQ6mKFv4I=; b=gqzn0fwwCVnBIasKIp6/KwRLc9njsxfxmfI7U2ZbFYJ3d4nqRfN9+qIVnwXRZPJV9W 0Rh9m8Dmac0hUG7leJ0937MIvBVsihNqDaLvHhJdO4HKPuYTRkyG4vlJXAkAnjPtNb/Q J3TSm2ShUCEkSkWUoa0TMxYD+4nPxnjozZRBesuy5GdYKLR6NCnjcquyk1VCmqUc6rp5 +sDn9d4QYaF/tdv+3ToJe1sk+PAhX+dzYKB2C3f2oDsRiTED4LTojgyj+Ex2rYWydyBe g/kwWSG7NrPWZIKL5WpIadrMxQWgCcA9ueXUNtA31D0rNphZUYx3jrz3OYI/6stS0763 6lPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1714989244; x=1715594044; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ga8rU6TTAMlW0eYro+OQUU98vsuNjWANwmXQ6mKFv4I=; b=DI+L7xQ2VUEF5IkpOLuJkvneMe/Ir/DrrUD75nUhUvL5vIl/4B7dc+osqV39FxHpQ9 XIxCk4m+OVSJjBYz6oQmyzT6BzhnHMNx766EsY/WbNRPTzKYtlkfqOvGKSq3Ww+IKiDZ 054ilyezECMK1LyYapr/flELdsMUl94MT9Y4bWQH1l0reVflN9sRMdh012jokBX37Sfr f8Hq7C2RRbWGpqokk2sPtQgRX7c1QFLpQqH3XSKvP1jzYp6RAyuFU5eeZRMyf1UWi3z2 OkeIpzz2uQouzAg6eBA2bPLAkrVTmXZ9sDxg2muf7z2lirqeqa+0NgOMjNHVlyjkarDU W0JA== X-Forwarded-Encrypted: i=1; AJvYcCXKXskV2G1OgFDnijZ86TYd6Otd8WdKixSbOhM85rF7mWA1PrqDZAyNMNgk+e5nQ95lvK1T61RRMX4206EGwjDmRXuSuthAtEK5YiDZ X-Gm-Message-State: AOJu0YxB2RCwoL5W6hvN6aUYON/TA9AVa3MRBputehajElrivduJGgKz 0/gNtaOueL1FDveGaG6RbP3l1oL5HXR4TWs6AEynZQbx05NjxGX/k+xRNWJguHAtxsgiPWpp4Kd MBZEsMQthTG+gcg== X-Received: from aliceryhl2.c.googlers.com ([fda3:e722:ac3:cc00:68:949d:c0a8:572]) (user=aliceryhl job=sendgmr) by 2002:a2e:bcc3:0:b0:2e3:6e32:7a31 with SMTP id z3-20020a2ebcc3000000b002e36e327a31mr2111ljp.0.1714989243811; Mon, 06 May 2024 02:54:03 -0700 (PDT) Date: Mon, 06 May 2024 09:53:27 +0000 In-Reply-To: <20240506-linked-list-v2-0-7b910840c91f@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20240506-linked-list-v2-0-7b910840c91f@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=4976; i=aliceryhl@google.com; h=from:subject:message-id; bh=TputigRZUR00q1xN1sbsYsPUvr9lDRrYeB9O4vnOPD0=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBmOKilpgrg2auL4BQjpffqhEAv7iAtgfTAjZkfx 0OxrRlZXACJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZjiopQAKCRAEWL7uWMY5 Rkr+EACWvky+6jgSOyKwmOCDFtl45pa6K6XUS0Ui/1xL619TmIohZRkC8/Q4pp+For0qr0Czs2i H+Gxc+VmLaxNJKqz7bzo8Egd1cLGuxH58jYd5fp7ZVG4lZcDMDiuQgL33U7ntJxEn0iDfyRY5Vd r0I647mwFEDv09XJvKR641WdhLMkfU5UpFa65feb2wJQS0J3xCvBWsin7WKUJrhveVazV58fANN v+3Ati/rTgrwYM5bKqvRNpLtjG1Z+3v5mtaD7v6dmrF3BUBcsQGQFaXLD2y+b8vQG86Y5ghECYv t5J+pJIqCSZfQAXHpnWtJaXWQLYHmr1psZ0+A9G0qAW7Yt84sRG9HuoTFOCeyopkpm9wmpux5Ew TNPbbpfba3/6LqnCiyCnsknrY3ZMZ/LHQ3NxtbuB9zmTHTO/eRB7jHX8HiSmWMAZ7AGU3GhRc7e t++bhn1UX0DGbB4UzcFrsdL9+DINaSItUCqf7+wytGMXNfY6RtfKqeyYaPA1VG10MCXsX1pIavL 3QOWaSr7lfOZMSJrIFZ0lhqLK6DE3qL7J4CiG3lF+bNjgt77eIWUGhf4NoD/Xu7t8ya11hYvjD0 8Pua9x+rhgnTzOqwWkTM40agJ3XEg9M8nAO5UQifCq8yQKAb2ZOsdO9J8+6lehcdZYeglBtcocQ 24d3V3TFgZ021bw== X-Mailer: b4 0.13-dev-26615 Message-ID: <20240506-linked-list-v2-6-7b910840c91f@google.com> Subject: [PATCH v2 6/9] rust: list: add iterators From: Alice Ryhl To: Miguel Ojeda , Andrew Morton Cc: Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , Andreas Hindborg , Marco Elver , Kees Cook , Coly Li , Paolo Abeni , Pierre Gondois , Ingo Molnar , Jakub Kicinski , Wei Yang , Matthew Wilcox , linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, Alice Ryhl Content-Type: text/plain; charset="utf-8" Rust Binder has lists containing stuff such as all contexts or all processes, and sometimes need to iterate over them. This patch enables Rust Binder to do that using a normal for loop. The iterator returns the ArcBorrow type, so it is possible to grab a refcount to values while iterating. Signed-off-by: Alice Ryhl --- rust/kernel/list.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs index d0ff29a3e5d1..e36afc7ee44a 100644 --- a/rust/kernel/list.rs +++ b/rust/kernel/list.rs @@ -5,7 +5,9 @@ //! A linked list implementation. use crate::init::PinInit; +use crate::sync::ArcBorrow; use crate::types::Opaque; +use core::iter::{DoubleEndedIterator, FusedIterator}; use core::marker::PhantomData; use core::ptr; @@ -435,6 +437,17 @@ pub fn push_all_back(&mut self, other: &mut List) { // INVARIANT: The other list is now empty, so update its pointer. other.first = ptr::null_mut(); } + + /// Creates an iterator over the list. + pub fn iter(&self) -> Iter<'_, T, ID> { + // INVARIANT: If the list is empty, both pointers are null. Otherwise, both pointers point + // at the first element of the same list. + Iter { + current: self.first, + stop: self.first, + _ty: PhantomData, + } + } } impl, const ID: u64> Default for List { @@ -450,3 +463,92 @@ fn drop(&mut self) { } } } + +/// An iterator into a [`List`]. +/// +/// # Invariants +/// +/// * There must be a [`List`] that is immutably borrowed for the duration of `'a`. +/// * The `current` pointer is null or points at a value in that [`List`]. +/// * The `stop` pointer is equal to the `first` field of the [`List`]. +#[derive(Clone)] +pub struct Iter<'a, T: ?Sized + ListItem, const ID: u64 = 0> { + current: *mut ListLinksFields, + stop: *mut ListLinksFields, + _ty: PhantomData<&'a ListArc>, +} + +impl<'a, T: ?Sized + ListItem, const ID: u64> Iterator for Iter<'a, T, ID> { + type Item = ArcBorrow<'a, T>; + + fn next(&mut self) -> Option> { + if self.current.is_null() { + return None; + } + + let current = self.current; + + // SAFETY: We just checked that `current` is not null, so it is in a list, and hence not + // dangling. There's no race because the iterator holds an immutable borrow to the list. + let next = unsafe { (*current).next }; + // INVARIANT: If `current` was the last element of the list, then this updates it to null. + // Otherwise, we update it to the next element. + self.current = if next != self.stop { + next + } else { + ptr::null_mut() + }; + + // SAFETY: The `current` pointer points at a value in the list. + let item = unsafe { T::view_value(ListLinks::from_fields(current)) }; + // SAFETY: + // * All values in a list are stored in an `Arc`. + // * The value cannot be removed from the list for the duration of the lifetime annotated + // on the returned `ArcBorrow`, because removing it from the list would require mutable + // access to the list. However, the `ArcBorrow` is annotated with the iterator's + // lifetime, and the list is immutably borrowed for that lifetime. + // * Values in a list never have a `UniqueArc` reference. + Some(unsafe { ArcBorrow::from_raw(item) }) + } +} + +impl<'a, T: ?Sized + ListItem, const ID: u64> FusedIterator for Iter<'a, T, ID> {} + +impl<'a, T: ?Sized + ListItem, const ID: u64> IntoIterator for &'a List { + type IntoIter = Iter<'a, T, ID>; + type Item = ArcBorrow<'a, T>; + + fn into_iter(self) -> Iter<'a, T, ID> { + self.iter() + } +} + +/// An owning iterator into a [`List`]. +pub struct IntoIter, const ID: u64 = 0> { + list: List, +} + +impl, const ID: u64> Iterator for IntoIter { + type Item = ListArc; + + fn next(&mut self) -> Option> { + self.list.pop_front() + } +} + +impl, const ID: u64> FusedIterator for IntoIter {} + +impl, const ID: u64> DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option> { + self.list.pop_back() + } +} + +impl, const ID: u64> IntoIterator for List { + type IntoIter = IntoIter; + type Item = ListArc; + + fn into_iter(self) -> IntoIter { + IntoIter { list: self } + } +} -- 2.45.0.rc1.225.g2a3ae87e7f-goog