Skip to content

Commit 998c657

Browse files
Darksonnojeda
authored andcommitted
rust: list: extract common code for insertion
To prepare for a new cursor API that has the ability to insert elements into the list, extract the common code needed for this operation into a new `insert_inner` method. Both `push_back` and `push_front` are updated to use the new function. Reviewed-by: Andreas Hindborg <[email protected]> Reviewed-by: Boqun Feng <[email protected]> Signed-off-by: Alice Ryhl <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 6ad64bf commit 998c657

File tree

1 file changed

+32
-38
lines changed

1 file changed

+32
-38
lines changed

rust/kernel/list.rs

+32-38
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,20 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
245245
self.first.is_null()
246246
}
247247

248-
/// Add the provided item to the back of the list.
249-
pub fn push_back(&mut self, item: ListArc<T, ID>) {
248+
/// Inserts `item` before `next` in the cycle.
249+
///
250+
/// Returns a pointer to the newly inserted element. Never changes `self.first` unless the list
251+
/// is empty.
252+
///
253+
/// # Safety
254+
///
255+
/// * `next` must be an element in this list or null.
256+
/// * if `next` is null, then the list must be empty.
257+
unsafe fn insert_inner(
258+
&mut self,
259+
item: ListArc<T, ID>,
260+
next: *mut ListLinksFields,
261+
) -> *mut ListLinksFields {
250262
let raw_item = ListArc::into_raw(item);
251263
// SAFETY:
252264
// * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
@@ -259,16 +271,16 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
259271
// SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
260272
let item = unsafe { ListLinks::fields(list_links) };
261273

262-
if self.first.is_null() {
263-
self.first = item;
274+
// Check if the list is empty.
275+
if next.is_null() {
264276
// SAFETY: The caller just gave us ownership of these fields.
265277
// INVARIANT: A linked list with one item should be cyclic.
266278
unsafe {
267279
(*item).next = item;
268280
(*item).prev = item;
269281
}
282+
self.first = item;
270283
} else {
271-
let next = self.first;
272284
// SAFETY: By the type invariant, this pointer is valid or null. We just checked that
273285
// it's not null, so it must be valid.
274286
let prev = unsafe { (*next).prev };
@@ -282,45 +294,27 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
282294
(*next).prev = item;
283295
}
284296
}
297+
298+
item
299+
}
300+
301+
/// Add the provided item to the back of the list.
302+
pub fn push_back(&mut self, item: ListArc<T, ID>) {
303+
// SAFETY:
304+
// * `self.first` is null or in the list.
305+
// * `self.first` is only null if the list is empty.
306+
unsafe { self.insert_inner(item, self.first) };
285307
}
286308

287309
/// Add the provided item to the front of the list.
288310
pub fn push_front(&mut self, item: ListArc<T, ID>) {
289-
let raw_item = ListArc::into_raw(item);
290311
// SAFETY:
291-
// * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
292-
// * If this requirement is violated, then the previous caller of `prepare_to_insert`
293-
// violated the safety requirement that they can't give up ownership of the `ListArc`
294-
// until they call `post_remove`.
295-
// * We own the `ListArc`.
296-
// * Removing items] from this list is always done using `remove_internal_inner`, which
297-
// calls `post_remove` before giving up ownership.
298-
let list_links = unsafe { T::prepare_to_insert(raw_item) };
299-
// SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
300-
let item = unsafe { ListLinks::fields(list_links) };
312+
// * `self.first` is null or in the list.
313+
// * `self.first` is only null if the list is empty.
314+
let new_elem = unsafe { self.insert_inner(item, self.first) };
301315

302-
if self.first.is_null() {
303-
// SAFETY: The caller just gave us ownership of these fields.
304-
// INVARIANT: A linked list with one item should be cyclic.
305-
unsafe {
306-
(*item).next = item;
307-
(*item).prev = item;
308-
}
309-
} else {
310-
let next = self.first;
311-
// SAFETY: We just checked that `next` is non-null.
312-
let prev = unsafe { (*next).prev };
313-
// SAFETY: Pointers in a linked list are never dangling, and the caller just gave us
314-
// ownership of the fields on `item`.
315-
// INVARIANT: This correctly inserts `item` between `prev` and `next`.
316-
unsafe {
317-
(*item).next = next;
318-
(*item).prev = prev;
319-
(*prev).next = item;
320-
(*next).prev = item;
321-
}
322-
}
323-
self.first = item;
316+
// INVARIANT: `new_elem` is in the list because we just inserted it.
317+
self.first = new_elem;
324318
}
325319

326320
/// Removes the last item from this list.

0 commit comments

Comments
 (0)