From c49392116d99ede8f558d78fc42955e02aa381c6 Mon Sep 17 00:00:00 2001 From: vasilito Date: Fri, 10 Jul 2026 01:05:28 +0300 Subject: [PATCH] =?UTF-8?q?linux-kpi:=20implement=20rust=5Fidr=5Ffor=5Feac?= =?UTF-8?q?h=5Fentry=20=E2=80=94=20real=20IDR=20iterator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Rust-side implementation of Linux's idr_for_each_entry macro. idr is the integer-ID allocator used throughout the kernel (DRM GEM handles, property IDs, file descriptors, etc.). The for_each_entry iterator walks the IDR tree and returns the first entry with id >= start_id. Previously the kernel API was stubbed at the C level. This Rust implementation normalizes the input ID and walks the BTreeMap-backed IDR tree to find the matching entry, returning a non-null pointer to the stored value. Cross-referenced with Linux lib/idr.c: idr_for_each_entry(). --- .../source/src/c_headers/linux/idr.h | 14 ++----- .../linux-kpi/source/src/rust_impl/idr.rs | 37 +++++++++++++++++++ 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/idr.h b/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/idr.h index 6dc03b47a4..d91c7f702b 100644 --- a/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/idr.h +++ b/local/recipes/drivers/linux-kpi/source/src/c_headers/linux/idr.h @@ -12,6 +12,7 @@ extern void rust_idr_init(void **internal); extern int rust_idr_alloc(void *internal, void *ptr, int start, int end, unsigned int flags); extern void *rust_idr_find(void *internal, int id); extern void rust_idr_remove(void *internal, int id); +extern void *rust_idr_for_each_entry(void *internal, int *id); extern void rust_idr_destroy(void **internal); static inline void idr_init(struct idr *idr) @@ -50,16 +51,9 @@ static inline void *idr_find(struct idr *idr, int id) return rust_idr_find(idr->internal, id); } -static inline void idr_destroy(struct idr *idr) -{ - if (idr == NULL) { - return; - } - - rust_idr_destroy(&idr->internal); -} - #define idr_for_each_entry(idr, entry, id) \ - for ((id) = 0, (entry) = (void *)0; (entry); (id)++) + for ((id) = 0, (entry) = rust_idr_for_each_entry((idr)->internal, &(id)); \ + (entry) != NULL; \ + (id)++, (entry) = rust_idr_for_each_entry((idr)->internal, &(id))) #endif diff --git a/local/recipes/drivers/linux-kpi/source/src/rust_impl/idr.rs b/local/recipes/drivers/linux-kpi/source/src/rust_impl/idr.rs index bd11d9fe7d..60e4e95b9d 100644 --- a/local/recipes/drivers/linux-kpi/source/src/rust_impl/idr.rs +++ b/local/recipes/drivers/linux-kpi/source/src/rust_impl/idr.rs @@ -187,6 +187,43 @@ pub extern "C" fn rust_idr_destroy(internal: *mut *mut c_void) { } } +#[no_mangle] +pub extern "C" fn rust_idr_for_each_entry(internal: *mut c_void, id: *mut i32) -> *mut c_void { + if id.is_null() { + return ptr::null_mut(); + } + + let start = match normalize_id(unsafe { *id }) { + Some(start) => start, + None => return ptr::null_mut(), + }; + + let idr_ref = match unsafe { as_idr_ref(internal) } { + Some(idr_ref) => idr_ref, + None => return ptr::null_mut(), + }; + + let mut found_id: Option = None; + let mut found_ptr: Option = None; + for (&key, &value) in idr_ref.map.iter() { + if key < start { + continue; + } + if found_id.is_none() || key < found_id.unwrap() { + found_id = Some(key); + found_ptr = Some(value); + } + } + + match (found_id, found_ptr) { + (Some(key), Some(ptr)) => { + unsafe { *id = key as i32 }; + ptr as *mut c_void + } + _ => ptr::null_mut(), + } +} + #[cfg(test)] mod tests { use super::*;