Skip to content

Commit 53536a5

Browse files
authored
Merge pull request #1843 from hermit-os/non_async-object_map
feat(scheduler): don't lock `Task::object_map` asynchronously
2 parents d1c760b + fbc6044 commit 53536a5

File tree

4 files changed

+93
-129
lines changed

4 files changed

+93
-129
lines changed

src/arch/x86_64/kernel/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,9 @@ pub unsafe fn jump_to_user_land(entry_point: usize, code_size: usize, arg: &[&st
298298
use x86_64::structures::paging::{PageSize, Size4KiB as BasePageSize};
299299

300300
use crate::arch::x86_64::kernel::scheduler::TaskStacks;
301-
use crate::executor::block_on;
302301

303302
info!("Create new file descriptor table");
304-
block_on(core_scheduler().recreate_objmap(), None).unwrap();
303+
core_scheduler().recreate_objmap().unwrap();
305304

306305
let entry_point: usize = LOADER_START | entry_point;
307306
let stack_pointer: usize = LOADER_START

src/fd/mod.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ async fn poll_fds(fds: &mut [PollFd]) -> io::Result<u64> {
307307
for i in &mut *fds {
308308
let fd = i.fd;
309309
i.revents = PollEvent::empty();
310-
let mut pinned_obj = core::pin::pin!(core_scheduler().get_object(fd));
311-
if let Ready(Ok(obj)) = pinned_obj.as_mut().poll(cx) {
310+
if let Ok(obj) = core_scheduler().get_object(fd) {
312311
let mut pinned = core::pin::pin!(obj.poll(i.events));
313312
if let Ready(Ok(e)) = pinned.as_mut().poll(cx)
314313
&& !e.is_empty()
@@ -374,33 +373,33 @@ pub fn fstat(fd: FileDescriptor) -> io::Result<FileAttr> {
374373
pub fn eventfd(initval: u64, flags: EventFlags) -> io::Result<FileDescriptor> {
375374
let obj = self::eventfd::EventFd::new(initval, flags);
376375

377-
let fd = block_on(core_scheduler().insert_object(Arc::new(obj)), None)?;
376+
let fd = core_scheduler().insert_object(Arc::new(obj))?;
378377

379378
Ok(fd)
380379
}
381380

382381
pub(crate) fn get_object(fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
383-
block_on(core_scheduler().get_object(fd), None)
382+
core_scheduler().get_object(fd)
384383
}
385384

386385
pub(crate) fn insert_object(obj: Arc<dyn ObjectInterface>) -> io::Result<FileDescriptor> {
387-
block_on(core_scheduler().insert_object(obj), None)
386+
core_scheduler().insert_object(obj)
388387
}
389388

390389
// The dup system call allocates a new file descriptor that refers
391390
// to the same open file description as the descriptor oldfd. The new
392391
// file descriptor number is guaranteed to be the lowest-numbered
393392
// file descriptor that was unused in the calling process.
394393
pub(crate) fn dup_object(fd: FileDescriptor) -> io::Result<FileDescriptor> {
395-
block_on(core_scheduler().dup_object(fd), None)
394+
core_scheduler().dup_object(fd)
396395
}
397396

398397
pub(crate) fn dup_object2(fd1: FileDescriptor, fd2: FileDescriptor) -> io::Result<FileDescriptor> {
399-
block_on(core_scheduler().dup_object2(fd1, fd2), None)
398+
core_scheduler().dup_object2(fd1, fd2)
400399
}
401400

402401
pub(crate) fn remove_object(fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
403-
block_on(core_scheduler().remove_object(fd), None)
402+
core_scheduler().remove_object(fd)
404403
}
405404

406405
pub(crate) fn isatty(fd: FileDescriptor) -> io::Result<bool> {

src/scheduler/mod.rs

Lines changed: 79 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@ use alloc::sync::Arc;
77
#[cfg(feature = "smp")]
88
use alloc::vec::Vec;
99
use core::cell::RefCell;
10-
use core::future::{self, Future};
1110
use core::ptr;
1211
#[cfg(all(target_arch = "x86_64", feature = "smp"))]
1312
use core::sync::atomic::AtomicBool;
1413
use core::sync::atomic::{AtomicI32, AtomicU32, Ordering};
15-
use core::task::Poll::Ready;
16-
use core::task::ready;
1714

1815
use ahash::RandomState;
1916
use crossbeam_utils::Backoff;
@@ -223,8 +220,7 @@ struct NewTask {
223220
prio: Priority,
224221
core_id: CoreId,
225222
stacks: TaskStacks,
226-
object_map:
227-
Arc<async_lock::RwLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
223+
object_map: Arc<RwSpinLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
228224
}
229225

230226
impl From<NewTask> for Task {
@@ -461,157 +457,130 @@ impl PerCoreScheduler {
461457
#[inline]
462458
pub fn get_current_task_object_map(
463459
&self,
464-
) -> Arc<async_lock::RwLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>> {
460+
) -> Arc<RwSpinLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>> {
465461
without_interrupts(|| self.current_task.borrow().object_map.clone())
466462
}
467463

468464
/// Map a file descriptor to their IO interface and returns
469465
/// the shared reference
470466
#[inline]
471-
pub async fn get_object(&self, fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
472-
future::poll_fn(|cx| {
473-
without_interrupts(|| {
474-
let borrowed = self.current_task.borrow();
475-
let mut pinned_obj = core::pin::pin!(borrowed.object_map.read());
476-
477-
let guard = ready!(pinned_obj.as_mut().poll(cx));
478-
Ready(guard.get(&fd).cloned().ok_or(Errno::Badf))
479-
})
480-
})
481-
.await
467+
pub fn get_object(&self, fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
468+
let current_task = self.current_task.borrow();
469+
let object_map = current_task.object_map.read();
470+
object_map.get(&fd).cloned().ok_or(Errno::Badf)
482471
}
483472

484473
/// Creates a new map between file descriptor and their IO interface and
485474
/// clone the standard descriptors.
486-
#[allow(dead_code)]
487-
pub async fn recreate_objmap(&self) -> io::Result<()> {
475+
#[cfg(feature = "common-os")]
476+
#[cfg_attr(not(target_arch = "x86_64"), expect(dead_code))]
477+
pub fn recreate_objmap(&self) -> io::Result<()> {
488478
let mut map = HashMap::<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>::with_hasher(
489479
RandomState::with_seeds(0, 0, 0, 0),
490480
);
491481

492-
future::poll_fn(|cx| {
493-
without_interrupts(|| {
494-
let borrowed = self.current_task.borrow();
495-
let mut pinned_obj = core::pin::pin!(borrowed.object_map.read());
496-
497-
let guard = ready!(pinned_obj.as_mut().poll(cx));
498-
// clone standard file descriptors
499-
for i in 0..3 {
500-
if let Some(obj) = guard.get(&i) {
501-
map.insert(i, obj.clone());
502-
}
503-
}
482+
without_interrupts(|| {
483+
let mut current_task = self.current_task.borrow_mut();
484+
let object_map = current_task.object_map.read();
504485

505-
Ready(io::Result::Ok(()))
506-
})
507-
})
508-
.await?;
486+
// clone standard file descriptors
487+
for i in 0..3 {
488+
if let Some(obj) = object_map.get(&i) {
489+
map.insert(i, obj.clone());
490+
}
491+
}
509492

510-
without_interrupts(|| {
511-
self.current_task.borrow_mut().object_map = Arc::new(async_lock::RwLock::new(map));
493+
drop(object_map);
494+
current_task.object_map = Arc::new(RwSpinLock::new(map));
512495
});
513496

514497
Ok(())
515498
}
516499

517500
/// Insert a new IO interface and returns a file descriptor as
518501
/// identifier to this object
519-
pub async fn insert_object(&self, obj: Arc<dyn ObjectInterface>) -> io::Result<FileDescriptor> {
520-
future::poll_fn(|cx| {
521-
without_interrupts(|| {
522-
let borrowed = self.current_task.borrow();
523-
let mut pinned_obj = core::pin::pin!(borrowed.object_map.write());
524-
525-
let mut guard = ready!(pinned_obj.as_mut().poll(cx));
526-
let new_fd = || -> io::Result<FileDescriptor> {
527-
let mut fd: FileDescriptor = 0;
528-
loop {
529-
if !guard.contains_key(&fd) {
530-
break Ok(fd);
531-
} else if fd == FileDescriptor::MAX {
532-
break Err(Errno::Overflow);
533-
}
534-
535-
fd = fd.saturating_add(1);
502+
pub fn insert_object(&self, obj: Arc<dyn ObjectInterface>) -> io::Result<FileDescriptor> {
503+
without_interrupts(|| {
504+
let current_task = self.current_task.borrow();
505+
let mut object_map = current_task.object_map.write();
506+
507+
let new_fd = || -> io::Result<FileDescriptor> {
508+
let mut fd: FileDescriptor = 0;
509+
loop {
510+
if !object_map.contains_key(&fd) {
511+
break Ok(fd);
512+
} else if fd == FileDescriptor::MAX {
513+
break Err(Errno::Overflow);
536514
}
537-
};
538515

539-
let fd = new_fd()?;
540-
let _ = guard.insert(fd, obj.clone());
541-
Ready(Ok(fd))
542-
})
516+
fd = fd.saturating_add(1);
517+
}
518+
};
519+
520+
let fd = new_fd()?;
521+
let _ = object_map.insert(fd, obj.clone());
522+
Ok(fd)
543523
})
544-
.await
545524
}
546525

547526
/// Duplicate a IO interface and returns a new file descriptor as
548527
/// identifier to the new copy
549-
pub async fn dup_object(&self, fd: FileDescriptor) -> io::Result<FileDescriptor> {
550-
future::poll_fn(|cx| {
551-
without_interrupts(|| {
552-
let borrowed = self.current_task.borrow();
553-
let mut pinned_obj = core::pin::pin!(borrowed.object_map.write());
554-
555-
let mut guard = ready!(pinned_obj.as_mut().poll(cx));
556-
let obj = (*(guard.get(&fd).ok_or(Errno::Inval)?)).clone();
557-
558-
let new_fd = || -> io::Result<FileDescriptor> {
559-
let mut fd: FileDescriptor = 0;
560-
loop {
561-
if !guard.contains_key(&fd) {
562-
break Ok(fd);
563-
} else if fd == FileDescriptor::MAX {
564-
break Err(Errno::Overflow);
565-
}
566-
567-
fd = fd.saturating_add(1);
528+
pub fn dup_object(&self, fd: FileDescriptor) -> io::Result<FileDescriptor> {
529+
without_interrupts(|| {
530+
let current_task = self.current_task.borrow();
531+
let mut object_map = current_task.object_map.write();
532+
533+
let obj = (*(object_map.get(&fd).ok_or(Errno::Inval)?)).clone();
534+
535+
let new_fd = || -> io::Result<FileDescriptor> {
536+
let mut fd: FileDescriptor = 0;
537+
loop {
538+
if !object_map.contains_key(&fd) {
539+
break Ok(fd);
540+
} else if fd == FileDescriptor::MAX {
541+
break Err(Errno::Overflow);
568542
}
569-
};
570543

571-
let fd = new_fd()?;
572-
if guard.try_insert(fd, obj).is_err() {
573-
Ready(Err(Errno::Mfile))
574-
} else {
575-
Ready(Ok(fd))
544+
fd = fd.saturating_add(1);
576545
}
577-
})
546+
};
547+
548+
let fd = new_fd()?;
549+
if object_map.try_insert(fd, obj).is_err() {
550+
Err(Errno::Mfile)
551+
} else {
552+
Ok(fd)
553+
}
578554
})
579-
.await
580555
}
581556

582-
pub async fn dup_object2(
557+
pub fn dup_object2(
583558
&self,
584559
fd1: FileDescriptor,
585560
fd2: FileDescriptor,
586561
) -> io::Result<FileDescriptor> {
587-
future::poll_fn(|cx| {
588-
without_interrupts(|| {
589-
let borrowed = self.current_task.borrow();
590-
let mut pinned_obj = core::pin::pin!(borrowed.object_map.write());
591-
let mut guard = ready!(pinned_obj.as_mut().poll(cx));
592-
let obj = guard.get(&fd1).cloned().ok_or(Errno::Badf)?;
562+
without_interrupts(|| {
563+
let current_task = self.current_task.borrow();
564+
let mut object_map = current_task.object_map.write();
593565

594-
if guard.try_insert(fd2, obj).is_err() {
595-
Ready(Err(Errno::Mfile))
596-
} else {
597-
Ready(Ok(fd2))
598-
}
599-
})
566+
let obj = object_map.get(&fd1).cloned().ok_or(Errno::Badf)?;
567+
568+
if object_map.try_insert(fd2, obj).is_err() {
569+
Err(Errno::Mfile)
570+
} else {
571+
Ok(fd2)
572+
}
600573
})
601-
.await
602574
}
603575

604576
/// Remove a IO interface, which is named by the file descriptor
605-
pub async fn remove_object(&self, fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
606-
future::poll_fn(|cx| {
607-
without_interrupts(|| {
608-
let borrowed = self.current_task.borrow();
609-
let mut pinned_obj = core::pin::pin!(borrowed.object_map.write());
610-
let mut guard = ready!(pinned_obj.as_mut().poll(cx));
611-
Ready(guard.remove(&fd).ok_or(Errno::Badf))
612-
})
577+
pub fn remove_object(&self, fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
578+
without_interrupts(|| {
579+
let current_task = self.current_task.borrow();
580+
let mut object_map = current_task.object_map.write();
581+
582+
object_map.remove(&fd).ok_or(Errno::Badf)
613583
})
614-
.await
615584
}
616585

617586
#[inline]

src/scheduler/task.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use core::{cmp, fmt};
1212
use ahash::RandomState;
1313
use crossbeam_utils::CachePadded;
1414
use hashbrown::HashMap;
15-
use hermit_sync::OnceCell;
15+
use hermit_sync::{OnceCell, RwSpinLock};
1616
use memory_addresses::VirtAddr;
1717

1818
use crate::arch::core_local::*;
@@ -390,8 +390,7 @@ pub(crate) struct Task {
390390
/// Stack of the task
391391
pub stacks: TaskStacks,
392392
/// Mapping between file descriptor and the referenced IO interface
393-
pub object_map:
394-
Arc<async_lock::RwLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
393+
pub object_map: Arc<RwSpinLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
395394
/// Task Thread-Local-Storage (TLS)
396395
#[cfg(not(feature = "common-os"))]
397396
pub tls: Option<Box<TaskTLS>>,
@@ -412,9 +411,7 @@ impl Task {
412411
task_status: TaskStatus,
413412
task_prio: Priority,
414413
stacks: TaskStacks,
415-
object_map: Arc<
416-
async_lock::RwLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>,
417-
>,
414+
object_map: Arc<RwSpinLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
418415
) -> Task {
419416
debug!("Creating new task {tid} on core {core_id}");
420417

@@ -440,12 +437,12 @@ impl Task {
440437

441438
/// All cores use the same mapping between file descriptor and the referenced object
442439
static OBJECT_MAP: OnceCell<
443-
Arc<async_lock::RwLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
440+
Arc<RwSpinLock<HashMap<FileDescriptor, Arc<dyn ObjectInterface>, RandomState>>>,
444441
> = OnceCell::new();
445442

446443
if core_id == 0 {
447444
OBJECT_MAP
448-
.set(Arc::new(async_lock::RwLock::new(HashMap::<
445+
.set(Arc::new(RwSpinLock::new(HashMap::<
449446
FileDescriptor,
450447
Arc<dyn ObjectInterface>,
451448
RandomState,
@@ -455,7 +452,7 @@ impl Task {
455452
.unwrap();
456453
let objmap = OBJECT_MAP.get().unwrap().clone();
457454
let _ = poll_on(async {
458-
let mut guard = objmap.write().await;
455+
let mut guard = objmap.write();
459456
if env::is_uhyve() {
460457
guard
461458
.try_insert(STDIN_FILENO, Arc::new(UhyveStdin::new()))

0 commit comments

Comments
 (0)