Use LinkedList to store WorkItem to avoid additional heap allocation

This commit is contained in:
Chen Chengjun
2024-11-01 10:14:28 +08:00
committed by Tate, Hongliang Tian
parent 2ac6e0e126
commit 846b3ba169
5 changed files with 28 additions and 18 deletions

View File

@ -92,11 +92,11 @@ impl LineDiscipline {
pub fn new(send_signal: LdiscSignalSender) -> Arc<Self> { pub fn new(send_signal: LdiscSignalSender) -> Arc<Self> {
Arc::new_cyclic(move |line_ref: &Weak<LineDiscipline>| { Arc::new_cyclic(move |line_ref: &Weak<LineDiscipline>| {
let line_discipline = line_ref.clone(); let line_discipline = line_ref.clone();
let work_item = Arc::new(WorkItem::new(Box::new(move || { let work_item = WorkItem::new(Box::new(move || {
if let Some(line_discipline) = line_discipline.upgrade() { if let Some(line_discipline) = line_discipline.upgrade() {
line_discipline.send_signal_after(); line_discipline.send_signal_after();
} }
}))); }));
Self { Self {
current_line: SpinLock::new(CurrentLine::default()), current_line: SpinLock::new(CurrentLine::default()),
read_buffer: SpinLock::new(RingBuffer::new(BUFFER_CAPACITY)), read_buffer: SpinLock::new(RingBuffer::new(BUFFER_CAPACITY)),

View File

@ -106,7 +106,7 @@ fn create_process_timer_callback(process_ref: &Weak<Process>) -> impl Fn() + Clo
}; };
let work_func = Box::new(sent_signal); let work_func = Box::new(sent_signal);
let work_item = Arc::new(WorkItem::new(work_func)); let work_item = WorkItem::new(work_func);
move || { move || {
submit_work_item( submit_work_item(

View File

@ -95,7 +95,7 @@ pub fn sys_timer_create(
}; };
let work_func = sent_signal; let work_func = sent_signal;
let work_item = Arc::new(WorkItem::new(work_func)); let work_item = WorkItem::new(work_func);
let func = move || { let func = move || {
submit_work_item( submit_work_item(
work_item.clone(), work_item.clone(),

View File

@ -64,9 +64,10 @@
//! //!
//! ``` //! ```
use intrusive_collections::linked_list::LinkedList;
use ostd::cpu::{CpuId, CpuSet}; use ostd::cpu::{CpuId, CpuSet};
use spin::Once; use spin::Once;
use work_item::WorkItem; use work_item::{WorkItem, WorkItemAdapter};
use worker_pool::WorkerPool; use worker_pool::WorkerPool;
use crate::prelude::*; use crate::prelude::*;
@ -86,7 +87,7 @@ pub fn submit_work_func<F>(work_func: F, work_priority: WorkPriority)
where where
F: Fn() + Send + Sync + 'static, F: Fn() + Send + Sync + 'static,
{ {
let work_item = Arc::new(WorkItem::new(Box::new(work_func))); let work_item = WorkItem::new(Box::new(work_func));
submit_work_item(work_item, work_priority); submit_work_item(work_item, work_priority);
} }
@ -112,7 +113,7 @@ pub struct WorkQueue {
} }
struct WorkQueueInner { struct WorkQueueInner {
pending_work_items: Vec<Arc<WorkItem>>, pending_work_items: LinkedList<WorkItemAdapter>,
} }
impl WorkQueue { impl WorkQueue {
@ -122,7 +123,7 @@ impl WorkQueue {
let queue = Arc::new(WorkQueue { let queue = Arc::new(WorkQueue {
worker_pool: worker_pool.clone(), worker_pool: worker_pool.clone(),
inner: SpinLock::new(WorkQueueInner { inner: SpinLock::new(WorkQueueInner {
pending_work_items: Vec::new(), pending_work_items: LinkedList::new(WorkItemAdapter::NEW),
}), }),
}); });
worker_pool worker_pool
@ -141,7 +142,7 @@ impl WorkQueue {
.disable_irq() .disable_irq()
.lock() .lock()
.pending_work_items .pending_work_items
.push(work_item); .push_back(work_item);
true true
} }
@ -150,12 +151,16 @@ impl WorkQueue {
/// the calling worker is located. /// the calling worker is located.
fn dequeue(&self, request_cpu: CpuId) -> Option<Arc<WorkItem>> { fn dequeue(&self, request_cpu: CpuId) -> Option<Arc<WorkItem>> {
let mut inner = self.inner.disable_irq().lock(); let mut inner = self.inner.disable_irq().lock();
let index = inner let mut cursor = inner.pending_work_items.front_mut();
.pending_work_items while let Some(item) = cursor.get() {
.iter() if item.is_valid_cpu(request_cpu) {
.position(|item| item.is_valid_cpu(request_cpu))?; return cursor.remove();
let item = inner.pending_work_items.remove(index); }
Some(item)
cursor.move_next();
}
None
} }
fn has_pending_work_items(&self, request_cpu: CpuId) -> bool { fn has_pending_work_items(&self, request_cpu: CpuId) -> bool {

View File

@ -4,6 +4,7 @@
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use intrusive_collections::{intrusive_adapter, LinkedListAtomicLink};
use ostd::cpu::{CpuId, CpuSet}; use ostd::cpu::{CpuId, CpuSet};
use crate::prelude::*; use crate::prelude::*;
@ -13,16 +14,20 @@ pub struct WorkItem {
work_func: Box<dyn Fn() + Send + Sync>, work_func: Box<dyn Fn() + Send + Sync>,
cpu_affinity: CpuSet, cpu_affinity: CpuSet,
was_pending: AtomicBool, was_pending: AtomicBool,
link: LinkedListAtomicLink,
} }
intrusive_adapter!(pub(super) WorkItemAdapter = Arc<WorkItem>: WorkItem { link: LinkedListAtomicLink });
impl WorkItem { impl WorkItem {
pub fn new(work_func: Box<dyn Fn() + Send + Sync>) -> WorkItem { pub fn new(work_func: Box<dyn Fn() + Send + Sync>) -> Arc<WorkItem> {
let cpu_affinity = CpuSet::new_full(); let cpu_affinity = CpuSet::new_full();
WorkItem { Arc::new(WorkItem {
work_func, work_func,
cpu_affinity, cpu_affinity,
was_pending: AtomicBool::new(false), was_pending: AtomicBool::new(false),
} link: LinkedListAtomicLink::new(),
})
} }
pub fn cpu_affinity(&self) -> &CpuSet { pub fn cpu_affinity(&self) -> &CpuSet {