2023-05-02 13:16:48 +02:00
|
|
|
//! Unsafe linked list.
|
|
|
|
//! Translated from ST's C by `c2rust` tool.
|
|
|
|
|
|
|
|
#![allow(
|
|
|
|
dead_code,
|
|
|
|
mutable_transmutes,
|
|
|
|
non_camel_case_types,
|
|
|
|
non_snake_case,
|
|
|
|
non_upper_case_globals,
|
|
|
|
unused_assignments,
|
|
|
|
unused_mut
|
|
|
|
)]
|
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
use core::ptr;
|
|
|
|
|
2023-05-02 13:16:48 +02:00
|
|
|
use cortex_m::interrupt;
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
#[repr(C, packed(4))]
|
|
|
|
pub struct LinkedListNode {
|
|
|
|
pub next: *mut LinkedListNode,
|
|
|
|
pub prev: *mut LinkedListNode,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for LinkedListNode {
|
|
|
|
fn default() -> Self {
|
|
|
|
LinkedListNode {
|
|
|
|
next: core::ptr::null_mut(),
|
|
|
|
prev: core::ptr::null_mut(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-20 17:11:29 +02:00
|
|
|
impl LinkedListNode {
|
2023-06-14 00:12:34 +02:00
|
|
|
pub unsafe fn init_head(mut p_list_head: *mut LinkedListNode) {
|
|
|
|
ptr::write_volatile(
|
|
|
|
p_list_head,
|
|
|
|
LinkedListNode {
|
|
|
|
next: p_list_head,
|
|
|
|
prev: p_list_head,
|
|
|
|
},
|
|
|
|
);
|
2023-05-20 17:11:29 +02:00
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
pub unsafe fn is_empty(mut p_list_head: *mut LinkedListNode) -> bool {
|
|
|
|
interrupt::free(|_| ptr::read_volatile(p_list_head).next == p_list_head)
|
2023-05-20 17:11:29 +02:00
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
/// Insert `node` after `list_head` and before the next node
|
|
|
|
pub unsafe fn insert_head(mut p_list_head: *mut LinkedListNode, mut p_node: *mut LinkedListNode) {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
2023-06-14 00:12:34 +02:00
|
|
|
let mut list_head = ptr::read_volatile(p_list_head);
|
|
|
|
let mut node_next = ptr::read_volatile(list_head.next);
|
|
|
|
let node = LinkedListNode {
|
|
|
|
next: list_head.next,
|
|
|
|
prev: p_list_head,
|
|
|
|
};
|
|
|
|
|
|
|
|
list_head.next = p_node;
|
|
|
|
node_next.prev = p_node;
|
|
|
|
|
|
|
|
// All nodes must be written because they will all be seen by another core
|
|
|
|
ptr::write_volatile(p_node, node);
|
|
|
|
ptr::write_volatile(node.next, node_next);
|
|
|
|
ptr::write_volatile(p_list_head, list_head);
|
2023-05-20 17:11:29 +02:00
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
/// Insert `node` before `list_tail` and after the second-to-last node
|
|
|
|
pub unsafe fn insert_tail(mut p_list_tail: *mut LinkedListNode, mut p_node: *mut LinkedListNode) {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
2023-06-14 00:12:34 +02:00
|
|
|
let mut list_tail = ptr::read_volatile(p_list_tail);
|
|
|
|
let mut node_prev = ptr::read_volatile(list_tail.prev);
|
|
|
|
let node = LinkedListNode {
|
|
|
|
next: p_list_tail,
|
|
|
|
prev: list_tail.prev,
|
|
|
|
};
|
|
|
|
|
|
|
|
list_tail.prev = p_node;
|
|
|
|
node_prev.next = p_node;
|
|
|
|
|
|
|
|
// All nodes must be written because they will all be seen by another core
|
|
|
|
ptr::write_volatile(p_node, node);
|
|
|
|
ptr::write_volatile(node.prev, node_prev);
|
|
|
|
ptr::write_volatile(p_list_tail, list_tail);
|
2023-05-20 17:11:29 +02:00
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
/// Remove `node` from the linked list
|
2023-06-14 00:12:34 +02:00
|
|
|
// pub unsafe fn remove_node(mut node: *mut LinkedListNode) {
|
|
|
|
// interrupt::free(|_| {
|
|
|
|
// (*(*node).prev).next = (*node).next;
|
|
|
|
// (*(*node).next).prev = (*node).prev;
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
/// Remove `node` from the linked list
|
|
|
|
pub unsafe fn remove_node(mut p_node: *mut LinkedListNode) {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
2023-06-14 00:12:34 +02:00
|
|
|
let node = ptr::read_volatile(p_node);
|
|
|
|
let mut node_prev = ptr::read_volatile(node.prev);
|
|
|
|
let mut node_next = ptr::read_volatile(node.next);
|
|
|
|
|
|
|
|
node_prev.next = node.next;
|
|
|
|
node_next.prev = node.prev;
|
|
|
|
|
|
|
|
ptr::write_volatile(node.prev, node_prev);
|
|
|
|
ptr::write_volatile(node.next, node_next);
|
2023-05-20 17:11:29 +02:00
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
/// Remove `list_head` into `node`
|
2023-06-14 00:12:34 +02:00
|
|
|
pub unsafe fn remove_head(mut p_list_head: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
2023-06-14 00:12:34 +02:00
|
|
|
let list_head = ptr::read_volatile(p_list_head);
|
|
|
|
|
|
|
|
// Allowed because a removed node is not seen by another core
|
|
|
|
*p_node = list_head.next;
|
|
|
|
Self::remove_node(list_head.next);
|
2023-05-20 17:11:29 +02:00
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-12 13:27:51 +02:00
|
|
|
/// Remove `list_tail` into `node`
|
2023-06-14 00:12:34 +02:00
|
|
|
pub unsafe fn remove_tail(mut p_list_tail: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
2023-06-14 00:12:34 +02:00
|
|
|
let list_tail = ptr::read_volatile(p_list_tail);
|
|
|
|
|
|
|
|
// Allowed because a removed node is not seen by another core
|
|
|
|
*p_node = list_tail.prev;
|
|
|
|
Self::remove_node(list_tail.prev);
|
2023-05-20 17:11:29 +02:00
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-20 17:11:29 +02:00
|
|
|
pub unsafe fn insert_node_after(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
|
|
|
|
interrupt::free(|_| {
|
|
|
|
(*node).next = (*ref_node).next;
|
|
|
|
(*node).prev = ref_node;
|
|
|
|
(*ref_node).next = node;
|
|
|
|
(*(*node).next).prev = node;
|
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-20 17:11:29 +02:00
|
|
|
pub unsafe fn insert_node_before(mut node: *mut LinkedListNode, mut ref_node: *mut LinkedListNode) {
|
|
|
|
interrupt::free(|_| {
|
|
|
|
(*node).next = ref_node;
|
|
|
|
(*node).prev = (*ref_node).prev;
|
|
|
|
(*ref_node).prev = node;
|
|
|
|
(*(*node).prev).next = node;
|
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-20 17:20:35 +02:00
|
|
|
pub unsafe fn get_size(mut list_head: *mut LinkedListNode) -> usize {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
|
|
|
let mut size = 0;
|
|
|
|
let mut temp: *mut LinkedListNode = core::ptr::null_mut::<LinkedListNode>();
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-20 17:20:35 +02:00
|
|
|
temp = (*list_head).next;
|
|
|
|
while temp != list_head {
|
2023-05-20 17:11:29 +02:00
|
|
|
size += 1;
|
|
|
|
temp = (*temp).next
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-20 17:11:29 +02:00
|
|
|
size
|
|
|
|
})
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-06-14 00:12:34 +02:00
|
|
|
pub unsafe fn get_next_node(mut p_ref_node: *mut LinkedListNode, mut p_node: *mut *mut LinkedListNode) {
|
2023-05-20 17:11:29 +02:00
|
|
|
interrupt::free(|_| {
|
2023-06-14 00:12:34 +02:00
|
|
|
let ref_node = ptr::read_volatile(p_ref_node);
|
|
|
|
|
|
|
|
// Allowed because a removed node is not seen by another core
|
|
|
|
*p_node = ref_node.next;
|
2023-05-20 17:11:29 +02:00
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
|
2023-05-20 17:11:29 +02:00
|
|
|
pub unsafe fn get_prev_node(mut ref_node: *mut LinkedListNode, mut node: *mut *mut LinkedListNode) {
|
|
|
|
interrupt::free(|_| {
|
|
|
|
*node = (*ref_node).prev;
|
|
|
|
});
|
|
|
|
}
|
2023-05-02 13:16:48 +02:00
|
|
|
}
|