Skip to content

Commit e87e672

Browse files
committed
Implement and use ModuleCell
1 parent 4ceecc3 commit e87e672

File tree

2 files changed

+83
-20
lines changed

2 files changed

+83
-20
lines changed

grub_rust_core/src/lib.rs

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@
88

99
extern crate alloc;
1010

11+
use alloc::boxed::Box;
1112
use alloc::vec::Vec;
1213
use alloc::vec;
1314
use alloc::string::String;
1415
use alloc::string::ToString;
16+
use alloc::ffi::CString;
17+
1518
use core::alloc::{GlobalAlloc, Layout};
19+
use core::cell::Cell;
20+
use core::cell::RefCell;
1621
use core::ffi::c_char;
1722
use core::ffi::c_int;
1823
use core::ffi::c_void;
19-
use core::fmt::{self, Arguments, Write};
20-
21-
use alloc::ffi::CString;
2224
use core::ffi::CStr;
23-
use core::panic::PanicInfo;
25+
use core::fmt::{self, Arguments, Write};
2426
use core::num::TryFromIntError;
27+
use core::panic::PanicInfo;
2528

2629
#[unsafe(link_section = ".module_license")]
2730
pub static LICENSE: [u8; 15] = *b"LICENSE=GPLv3+\0";
@@ -363,11 +366,9 @@ pub struct Command {
363366
cmd: *mut GrubCommand,
364367
}
365368

366-
static mut commands: Vec<Command> = vec![];
367-
368369
impl Command {
369370
pub fn register(name: &str, cb: fn (argv: &[&str]) -> Result<(), GrubError>,
370-
summary: &str, description: &str) {
371+
summary: &str, description: &str) -> Self {
371372
let mut ret = Command {
372373
name: CString::new(name).unwrap(),
373374
summary: CString::new(summary).unwrap(),
@@ -381,15 +382,15 @@ impl Command {
381382
ret.description.as_ptr(),
382383
0);
383384
(*ret.cmd).data = cb as *mut c_void;
384-
commands.push(ret);
385385
}
386+
return ret;
386387
}
388+
}
387389

388-
pub fn unregister_all() {
390+
impl Drop for Command {
391+
fn drop(&mut self) {
389392
unsafe {
390-
for cmd in commands.iter() {
391-
grub_unregister_command(cmd.cmd);
392-
}
393+
grub_unregister_command(self.cmd);
393394
}
394395
}
395396
}
@@ -470,3 +471,58 @@ impl Drop for File {
470471
unsafe { grub_file_close(self.file); }
471472
}
472473
}
474+
475+
pub trait ModuleFini {
476+
fn module_fini(&self);
477+
}
478+
479+
pub struct ModuleCell<T> {
480+
inner: Cell<Option<T>>,
481+
}
482+
483+
pub struct ModuleRefHolder {
484+
val: Cell<*const c_void>,
485+
destructors: RefCell<Vec<Box<dyn ModuleFini>>>,
486+
}
487+
488+
impl<T> ModuleCell<T> {
489+
pub fn set(&'static self, dl: &ModuleRefHolder, value: T) {
490+
self.inner.set(Some(value));
491+
dl.destructors.borrow_mut().push(Box::new(self));
492+
}
493+
494+
pub const fn new() -> Self {
495+
Self{inner: Cell::new(None)}
496+
}
497+
}
498+
499+
impl<T> ModuleFini for &ModuleCell<T> {
500+
fn module_fini(&self) {
501+
self.inner.set(None);
502+
}
503+
}
504+
505+
// SAFETY: We're single-threaded with disabled interrupts
506+
unsafe impl<T> Sync for ModuleCell<T> {
507+
}
508+
509+
impl ModuleRefHolder {
510+
pub fn init(&self, value: *const c_void) {
511+
self.val.set(value);
512+
}
513+
514+
pub fn fini(&self) {
515+
for d in self.destructors.borrow().iter() {
516+
d.module_fini();
517+
}
518+
self.destructors.borrow_mut().clear();
519+
}
520+
521+
pub const fn new() -> Self {
522+
Self{val: Cell::new(core::ptr::null()), destructors: RefCell::new(vec![])}
523+
}
524+
}
525+
526+
// SAFETY: We're single-threaded with disabled interrupts
527+
unsafe impl Sync for ModuleRefHolder {
528+
}

grub_rust_example/src/lib.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use core::cmp::min;
1111
use core::convert::TryFrom;
1212

1313
use alloc::format;
14+
use core::ffi::c_void;
1415

1516
use grub::dprintln;
1617
use grub::println;
@@ -116,17 +117,23 @@ fn rust_hexdump (args: &[&str]) -> Result<(), grub::GrubError> {
116117
return Ok(());
117118
}
118119

120+
static HELLO_CMD: grub::ModuleCell<grub::Command> = grub::ModuleCell::new();
121+
static ERR_CMD: grub::ModuleCell<grub::Command> = grub::ModuleCell::new();
122+
static HEXDUMP_CMD: grub::ModuleCell<grub::Command> = grub::ModuleCell::new();
123+
static MODULE: grub::ModuleRefHolder = grub::ModuleRefHolder::new();
124+
119125
#[unsafe(no_mangle)]
120-
pub extern "C" fn grub_mod_init() {
121-
grub::Command::register("rust_hello", rust_hello,
122-
"Rust hello", "Say hello from Rust.");
123-
grub::Command::register("rust_err", rust_err,
124-
"Rust error", "Error out from Rust.");
125-
grub::Command::register("rust_hexdump", rust_hexdump,
126-
"Rust hexdump", "Hexdump a file from Rust.");
126+
pub extern "C" fn grub_mod_init(module: *const c_void) {
127+
MODULE.init(module);
128+
HELLO_CMD.set(&MODULE, grub::Command::register("rust_hello", rust_hello,
129+
"Rust hello", "Say hello from Rust."));
130+
ERR_CMD.set(&MODULE, grub::Command::register("rust_err", rust_err,
131+
"Rust error", "Error out from Rust."));
132+
HEXDUMP_CMD.set(&MODULE, grub::Command::register("rust_hexdump", rust_hexdump,
133+
"Rust hexdump", "Hexdump a file from Rust."));
127134
}
128135

129136
#[unsafe(no_mangle)]
130137
pub extern "C" fn grub_mod_fini() {
131-
grub::Command::unregister_all();
138+
MODULE.fini();
132139
}

0 commit comments

Comments
 (0)