Skip to content

Commit

Permalink
Moves obj_list, list_main and list_global out of RTLD (obhq#790)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Apr 1, 2024
1 parent 44e79e2 commit b0db7bf
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 126 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"lldb.launch.initCommands": [
"settings set target.x86-disassembly-flavor intel"
],
"rust-analyzer.imports.granularity.group": "module",
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
Expand Down
58 changes: 52 additions & 6 deletions src/gmtx/src/guard.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{GroupGuard, Gutex};
use std::fmt::{Display, Formatter};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};

/// RAII structure used to release the shared read access of a lock when dropped.
Expand Down Expand Up @@ -40,33 +41,78 @@ unsafe impl<'a, T: Sync> Sync for GutexReadGuard<'a, T> {}
/// RAII structure used to release the exclusive write access of a lock when dropped.
#[allow(dead_code)]
pub struct GutexWriteGuard<'a, T> {
mtx: &'a Gutex<T>,
active: *mut usize,
value: *mut T,
lock: GroupGuard<'a>,
}

impl<'a, T> GutexWriteGuard<'a, T> {
pub(crate) fn new(lock: GroupGuard<'a>, mtx: &'a Gutex<T>) -> Self {
Self { lock, mtx }
/// # Safety
/// `active` and `value` must be protected by `lock`.
pub(crate) unsafe fn new(active: *mut usize, value: *mut T, lock: GroupGuard<'a>) -> Self {
Self {
active,
value,
lock,
}
}

pub fn map<O, F: FnOnce(&mut T) -> &mut O>(self, f: F) -> GutexWriteGuard<'a, O> {
let active = self.active;
let value = f(unsafe { &mut *self.value });
let lock = GroupGuard {
group: self.lock.group,
phantom: PhantomData,
};

std::mem::forget(self);

GutexWriteGuard {
active,
value,
lock,
}
}
}

impl<'a, T> GutexWriteGuard<'a, Option<T>> {
pub fn ok_or<E>(self, err: E) -> Result<GutexWriteGuard<'a, T>, E> {
match unsafe { (*self.value).as_mut() } {
Some(v) => {
let v = GutexWriteGuard {
active: self.active,
value: v as *mut T,
lock: GroupGuard {
group: self.lock.group,
phantom: PhantomData,
},
};

std::mem::forget(self);
Ok(v)
}
None => Err(err),
}
}
}

impl<'a, T> Drop for GutexWriteGuard<'a, T> {
fn drop(&mut self) {
unsafe { *self.mtx.active.get() = 0 };
unsafe { *self.active = 0 };
}
}

impl<'a, T> Deref for GutexWriteGuard<'a, T> {
type Target = T;

fn deref(&self) -> &Self::Target {
unsafe { &*self.mtx.value.get() }
unsafe { &*self.value }
}
}

impl<'a, T> DerefMut for GutexWriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.mtx.value.get() }
unsafe { &mut *self.value }
}
}

Expand Down
9 changes: 5 additions & 4 deletions src/gmtx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ impl<T> Gutex<T> {
let lock = self.group.lock();
let active = self.active.get();

// SAFETY: This is safe because we own the lock that protect both active and value.
unsafe {
if *active != 0 {
panic!(
Expand All @@ -95,9 +96,9 @@ impl<T> Gutex<T> {
}

*active = usize::MAX;
}

GutexWriteGuard::new(lock, self)
GutexWriteGuard::new(&mut *active, &mut *self.value.get(), lock)
}
}
}

Expand Down Expand Up @@ -211,8 +212,8 @@ unsafe impl Sync for GutexGroup {}
/// An RAII object used to release the lock on [`GutexGroup`]. This type cannot be send because it
/// will cause data race on the group when dropping if more than one [`GroupGuard`] are active.
struct GroupGuard<'a> {
group: &'a GutexGroup,
phantom: PhantomData<Rc<i32>>, // For !Send and !Sync.
pub group: &'a GutexGroup,
pub phantom: PhantomData<Rc<i32>>, // For !Send and !Sync.
}

impl<'a> GroupGuard<'a> {
Expand Down
4 changes: 2 additions & 2 deletions src/kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ fn run() -> Result<(), KernelError> {

info!("Loading {path}.");

let libkernel = ld
let (libkernel, _) = ld
.load(path, flags, false, true, &main)
.map_err(|e| KernelError::FailedToLoadLibkernel(e.into()))?;

Expand All @@ -440,7 +440,7 @@ fn run() -> Result<(), KernelError> {

info!("Loading {path}.");

let libc = ld
let (libc, _) = ld
.load(path, flags, false, true, &main)
.map_err(|e| KernelError::FailedToLoadLibSceLibcInternal(e.into()))?;

Expand Down
41 changes: 39 additions & 2 deletions src/kernel/src/process/binary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,52 @@ use std::sync::Arc;
/// that field.
#[derive(Debug)]
pub struct Binaries {
app: Arc<Module>, // obj_main
list: Vec<Arc<Module>>, // obj_list + obj_tail
mains: Vec<Arc<Module>>, // list_main
globals: Vec<Arc<Module>>, // list_global
app: Arc<Module>, // obj_main
}

impl Binaries {
pub fn new(app: Arc<Module>) -> Self {
Self { app }
Self {
list: vec![app.clone()],
mains: vec![app.clone()],
globals: Vec::new(),
app,
}
}

/// The returned iterator will never be empty and the first item is always the application
/// itself.
pub fn list(&self) -> impl ExactSizeIterator<Item = &Arc<Module>> {
self.list.iter()
}

/// The returned iterator will never be empty and the first item is always the application
/// itself.
pub fn mains(&self) -> impl Iterator<Item = &Arc<Module>> {
self.mains.iter()
}

pub fn globals(&self) -> impl Iterator<Item = &Arc<Module>> {
self.globals.iter()
}

pub fn app(&self) -> &Arc<Module> {
&self.app
}

pub fn push(&mut self, md: Arc<Module>, main: bool) {
if main {
self.list.push(md.clone());
self.mains.push(md);
} else {
self.list.push(md);
}
}

pub fn push_global(&mut self, md: Arc<Module>) {
self.globals.push(md);
}
}
Loading

0 comments on commit b0db7bf

Please sign in to comment.