Browse Source

Change to asynchronous lock structure trait style

luojia65 3 years ago
parent
commit
30c59042fe
6 changed files with 82 additions and 82 deletions
  1. 1 0
      CHANGELOG.md
  2. 12 12
      src/ipi.rs
  3. 21 22
      src/pmu.rs
  4. 13 14
      src/reset.rs
  5. 23 23
      src/rfence.rs
  6. 12 11
      src/timer.rs

+ 1 - 0
CHANGELOG.md

@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Modify second parameter of `enter_privileged` to `opaque` other than `dtb_pa`
 - Dump all trap frame registers when exception happened in reference implementations
 - Downgrade `embedded-hal` to version `0.2.6`
+- Change to asynchronous lock structure trait style
 
 ### Fixed
 - Test kernel console now will lock before `println` line is finished

+ 12 - 12
src/ipi.rs

@@ -1,5 +1,7 @@
 use crate::hart_mask::HartMask;
 use crate::ecall::SbiRet;
+use crate::util::OnceFatBox;
+use alloc::boxed::Box;
 
 /// Inter-processor interrupt support
 pub trait Ipi: Send {
@@ -12,28 +14,26 @@ pub trait Ipi: Send {
     /// # Return value
     /// 
     /// Should return error code `SBI_SUCCESS` if IPI was sent to all the targeted harts successfully.
-    fn send_ipi_many(&mut self, hart_mask: HartMask) -> SbiRet;
+    fn send_ipi_many(&self, hart_mask: HartMask) -> SbiRet;
 }
 
-use alloc::boxed::Box;
-use spin::Mutex;
-
-lazy_static::lazy_static! {
-    static ref IPI: Mutex<Option<Box<dyn Ipi>>> = Mutex::new(None);
-}
+static IPI: OnceFatBox<dyn Ipi + Sync + 'static> = OnceFatBox::new();
 
 #[doc(hidden)] // use through a macro
-pub fn init_ipi<T: Ipi + Send + 'static>(ipi: T) {
-    *IPI.lock() = Some(Box::new(ipi));
+pub fn init_ipi<T: Ipi + Sync + 'static>(ipi: T) {
+    let result = IPI.set(Box::new(ipi));
+    if result.is_err() {
+        panic!("load sbi module when already loaded")
+    }
 }
 
 #[inline]
 pub(crate) fn probe_ipi() -> bool {
-    IPI.lock().as_ref().is_some()
+    IPI.get().is_some()
 }
 
 pub(crate) fn send_ipi_many(hart_mask: HartMask) -> SbiRet {
-    if let Some(ipi) = IPI.lock().as_mut() {
+    if let Some(ipi) = IPI.get() {
         ipi.send_ipi_many(hart_mask)
     } else {
         SbiRet::not_supported()
@@ -41,7 +41,7 @@ pub(crate) fn send_ipi_many(hart_mask: HartMask) -> SbiRet {
 }
 
 pub(crate) fn max_hart_id() -> Option<usize> { 
-    if let Some(ipi) = IPI.lock().as_ref() {
+    if let Some(ipi) = IPI.get() {
         Some(ipi.max_hart_id())
     } else {
         None

+ 21 - 22
src/pmu.rs

@@ -1,4 +1,6 @@
 use crate::ecall::SbiRet;
+use crate::util::OnceFatBox;
+use alloc::boxed::Box;
 
 /// Performance Monitoring Unit Extension
 ///
@@ -38,7 +40,7 @@ use crate::ecall::SbiRet;
 pub trait Pmu: Send {
     /// Returns the number of counters (both hardware and firmware) in return `SbiRet.value`
     /// and always returns SBI_SUCCESS in `SbiRet.error`.
-    fn num_counters(&mut self) -> SbiRet;
+    fn num_counters(&self) -> SbiRet;
     /// Get details about the specified counter such as underlying CSR number, width of the counter, 
     /// type of counter hardware/firmware, etc.
     ///
@@ -62,7 +64,7 @@ pub trait Pmu: Send {
     /// |:------------------------|:----------------------------------------------
     /// | SBI_SUCCESS             | `counter_info` read successfully.
     /// | SBI_ERR_INVALID_PARAM   | `counter_idx` points to an invalid counter.
-    fn counter_get_info(&mut self, counter_idx: usize) -> SbiRet;
+    fn counter_get_info(&self, counter_idx: usize) -> SbiRet;
     /// Find and configure a counter from a set of counters which is not started (or enabled) 
     /// and can monitor the specified event. 
     /// 
@@ -110,7 +112,7 @@ pub trait Pmu: Send {
     /// | SBI_ERR_INVALID_PARAM | set of counters has an invalid counter.
     /// | SBI_ERR_NOT_SUPPORTED | none of the counters can monitor specified event.
     fn counter_config_matching(
-        &mut self,
+        &self,
         counter_idx_base: usize,
         counter_idx_mask: usize,
         config_flags: usize,
@@ -144,7 +146,7 @@ pub trait Pmu: Send {
     /// | SBI_ERR_INVALID_PARAM   | some of the counters specified in parameters are invalid.
     /// | SBI_ERR_ALREADY_STARTED | some of the counters specified in parameters are already started.
     fn counter_start(
-        &mut self, 
+        &self, 
         counter_idx_base: usize, 
         counter_idx_mask: usize, 
         start_flags: usize, 
@@ -171,7 +173,7 @@ pub trait Pmu: Send {
     /// | SBI_SUCCESS             | counter stopped successfully.
     /// | SBI_ERR_INVALID_PARAM   | some of the counters specified in parameters are invalid.
     /// | SBI_ERR_ALREADY_STOPPED | some of the counters specified in parameters are already stopped.
-    fn counter_stop(&mut self, counter_idx_base: usize, counter_idx_mask: usize, stop_flags: usize) -> SbiRet;
+    fn counter_stop(&self, counter_idx_base: usize, counter_idx_mask: usize, stop_flags: usize) -> SbiRet;
     /// Provide the current value of a firmware counter in `SbiRet.value`.
     ///
     /// # Parameters
@@ -187,32 +189,29 @@ pub trait Pmu: Send {
     /// |:------------------------|:----------------------------------------------
     /// | SBI_SUCCESS             | firmware counter read successfully.
     /// | SBI_ERR_INVALID_PARAM   | `counter_idx` points to a hardware counter or an invalid counter.
-    fn counter_fw_read(&mut self, counter_idx: usize) -> SbiRet;
+    fn counter_fw_read(&self, counter_idx: usize) -> SbiRet;
 }
 
 // TODO: all the events here
 
-use alloc::boxed::Box;
-use spin::Mutex;
-
-lazy_static::lazy_static! {
-    static ref PMU: Mutex<Option<Box<dyn Pmu>>> =
-        Mutex::new(None);
-}
+static PMU: OnceFatBox<dyn Pmu + Sync + 'static> = OnceFatBox::new();
 
 #[doc(hidden)] // use through a macro or a call from implementation
-pub fn init_pmu<T: Pmu + Send + 'static>(hsm: T) {
-    *PMU.lock() = Some(Box::new(hsm));
+pub fn init_pmu<T: Pmu + Sync + 'static>(pmu: T) {
+    let result = PMU.set(Box::new(pmu));
+    if result.is_err() {
+        panic!("load sbi module when already loaded")
+    }
 }
 
 #[inline]
 pub(crate) fn probe_pmu() -> bool {
-    PMU.lock().as_ref().is_some()
+    PMU.get().is_some()
 }
 
 #[inline] 
 pub(crate) fn num_counters() -> SbiRet {
-    if let Some(obj) = &mut *PMU.lock() {
+    if let Some(obj) = PMU.get() {
         return obj.num_counters();
     }
     SbiRet::not_supported()
@@ -220,7 +219,7 @@ pub(crate) fn num_counters() -> SbiRet {
 
 #[inline] 
 pub(crate) fn counter_get_info(counter_idx: usize) -> SbiRet {
-    if let Some(obj) = &mut *PMU.lock() {
+    if let Some(obj) = PMU.get() {
         return obj.counter_get_info(counter_idx);
     }
     SbiRet::not_supported()
@@ -234,7 +233,7 @@ pub(crate) fn counter_config_matching(
     event_idx: usize,
     event_data: u64
 ) -> SbiRet {
-    if let Some(obj) = &mut *PMU.lock() {
+    if let Some(obj) = PMU.get() {
         return obj.counter_config_matching(
             counter_idx_base,
             counter_idx_mask,
@@ -253,7 +252,7 @@ pub(crate) fn counter_start(
     start_flags: usize, 
     initial_value: u64
 ) -> SbiRet {
-    if let Some(obj) = &mut *PMU.lock() {
+    if let Some(obj) = PMU.get() {
         return obj.counter_start(
             counter_idx_base, 
             counter_idx_mask,
@@ -266,7 +265,7 @@ pub(crate) fn counter_start(
 
 #[inline] 
 pub(crate) fn counter_stop(counter_idx_base: usize, counter_idx_mask: usize, stop_flags: usize) -> SbiRet {
-    if let Some(obj) = &mut *PMU.lock() {
+    if let Some(obj) = PMU.get() {
         return obj.counter_stop(counter_idx_base, counter_idx_mask, stop_flags);
     }
     SbiRet::not_supported()
@@ -274,7 +273,7 @@ pub(crate) fn counter_stop(counter_idx_base: usize, counter_idx_mask: usize, sto
 
 #[inline] 
 pub(crate) fn counter_fw_read(counter_idx: usize) -> SbiRet {
-    if let Some(obj) = &mut *PMU.lock() {
+    if let Some(obj) = PMU.get() {
         return obj.counter_fw_read(counter_idx);
     }
     SbiRet::not_supported()

+ 13 - 14
src/reset.rs

@@ -1,3 +1,7 @@
+use alloc::boxed::Box;
+use crate::util::OnceFatBox;
+use crate::ecall::SbiRet;
+
 /// System Reset Extension
 ///
 /// Provides a function that allow the supervisor software to request system-level reboot or shutdown.
@@ -47,15 +51,7 @@ pub trait Reset: Send {
     }
 }
 
-use alloc::boxed::Box;
-use spin::Mutex;
-
-use crate::ecall::SbiRet;
-
-lazy_static::lazy_static! {
-    static ref RESET: Mutex<Option<Box<dyn Reset>>> =
-        Mutex::new(None);
-}
+static RESET: OnceFatBox<dyn Reset + Sync + 'static> = OnceFatBox::new();
 
 #[doc(hidden)] #[allow(unused)]
 pub const RESET_TYPE_SHUTDOWN: usize = 0x0000_0000;
@@ -70,24 +66,27 @@ pub const RESET_REASON_NO_REASON: usize = 0x0000_0000;
 pub const RESET_REASON_SYSTEM_FAILURE: usize = 0x0000_0001;
 
 #[doc(hidden)] // use through a macro
-pub fn init_reset<T: Reset + Send + 'static>(reset: T) {
-    *RESET.lock() = Some(Box::new(reset));
+pub fn init_reset<T: Reset + Sync + 'static>(reset: T) {
+    let result = RESET.set(Box::new(reset));
+    if result.is_err() {
+        panic!("load sbi module when already loaded")
+    }
 }
 
 #[inline]
 pub(crate) fn probe_reset() -> bool {
-    RESET.lock().as_ref().is_some()
+    RESET.get().is_some()
 }
 
 pub(crate) fn system_reset(reset_type: usize, reset_reason: usize) -> SbiRet {
-    if let Some(obj) = &*RESET.lock() {
+    if let Some(obj) = RESET.get() {
         return obj.system_reset(reset_type, reset_reason);
     }
     SbiRet::not_supported()
 }
 
 pub(crate) fn legacy_reset() -> ! {
-    if let Some(obj) = &*RESET.lock() {
+    if let Some(obj) = RESET.get() {
         obj.legacy_reset()
     }
     unreachable!("no reset handler available; this is okay if your platform didn't declare a legacy reset handler")

+ 23 - 23
src/rfence.rs

@@ -1,5 +1,7 @@
 use crate::hart_mask::HartMask;
 use crate::ecall::SbiRet;
+use alloc::boxed::Box;
+use crate::util::OnceFatBox;
 
 /// Remote fence support
 ///
@@ -16,7 +18,7 @@ pub trait Rfence: Send {
     /// # Return value
     ///
     /// Returns `SBI_SUCCESS` when remote fence was sent to all the targeted harts successfully.
-    fn remote_fence_i(&mut self, hart_mask: HartMask) -> SbiRet;
+    fn remote_fence_i(&self, hart_mask: HartMask) -> SbiRet;
     /// Instructs the remote harts to execute one or more `SFENCE.VMA` instructions, 
     /// covering the range of virtual addresses between start and size.
     /// 
@@ -28,7 +30,7 @@ pub trait Rfence: Send {
     /// |:--------------------------|:----------------------------------------------
     /// | SBI_SUCCESS               | Remote fence was sent to all the targeted harts successfully.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` or `size` is not valid.
-    fn remote_sfence_vma(&mut self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet;
+    fn remote_sfence_vma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet;
     /// Instruct the remote harts to execute one or more `SFENCE.VMA` instructions, 
     /// covering the range of virtual addresses between start and size. This covers only the given `ASID`.
     ///
@@ -40,7 +42,7 @@ pub trait Rfence: Send {
     /// |:--------------------------|:----------------------------------------------
     /// | SBI_SUCCESS               | Remote fence was sent to all the targeted harts successfully.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` or `size` is not valid.
-    fn remote_sfence_vma_asid(&mut self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet;
+    fn remote_sfence_vma_asid(&self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet;
     /// Instruct the remote harts to execute one or more `HFENCE.GVMA` instructions, 
     /// covering the range of guest physical addresses between start and size only for the given `VMID`. 
     /// 
@@ -55,7 +57,7 @@ pub trait Rfence: Send {
     /// | SBI_SUCCESS               | Remote fence was sent to all the targeted harts successfully.
     /// | SBI_ERR_NOT_SUPPORTED     | This function is not supported as it is not implemented or one of the target hart doesn’t support hypervisor extension.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` or `size` is not valid.
-    fn remote_hfence_gvma_vmid(&mut self, hart_mask: HartMask, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
+    fn remote_hfence_gvma_vmid(&self, hart_mask: HartMask, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
         drop((hart_mask, start_addr, size, vmid));
         SbiRet::not_supported()
     }
@@ -73,7 +75,7 @@ pub trait Rfence: Send {
     /// | SBI_SUCCESS               | Remote fence was sent to all the targeted harts successfully.
     /// | SBI_ERR_NOT_SUPPORTED     | This function is not supported as it is not implemented or one of the target hart doesn’t support hypervisor extension.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` or `size` is not valid.
-    fn remote_hfence_gvma(&mut self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
+    fn remote_hfence_gvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
         drop((hart_mask, start_addr, size));
         SbiRet::not_supported()
     }
@@ -92,7 +94,7 @@ pub trait Rfence: Send {
     /// | SBI_SUCCESS               | Remote fence was sent to all the targeted harts successfully.
     /// | SBI_ERR_NOT_SUPPORTED     | This function is not supported as it is not implemented or one of the target hart doesn’t support hypervisor extension.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` or `size` is not valid.
-    fn remote_hfence_vvma_asid(&mut self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
+    fn remote_hfence_vvma_asid(&self, hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
         drop((hart_mask, start_addr, size, asid));
         SbiRet::not_supported()
     }
@@ -111,31 +113,29 @@ pub trait Rfence: Send {
     /// | SBI_SUCCESS               | Remote fence was sent to all the targeted harts successfully.
     /// | SBI_ERR_NOT_SUPPORTED     | This function is not supported as it is not implemented or one of the target hart doesn’t support hypervisor extension.
     /// | SBI_ERR_INVALID_ADDRESS   | `start_addr` or `size` is not valid.
-    fn remote_hfence_vvma(&mut self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
+    fn remote_hfence_vvma(&self, hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
         drop((hart_mask, start_addr, size));
         SbiRet::not_supported()
     }
 }
 
-use alloc::boxed::Box;
-use spin::Mutex;
-
-lazy_static::lazy_static! {
-    static ref RFENCE: Mutex<Option<Box<dyn Rfence>>> = Mutex::new(None);
-}
+static RFENCE: OnceFatBox<dyn Rfence + Sync + 'static> = OnceFatBox::new();
 
 #[doc(hidden)] // use through a macro
-pub fn init_rfence<T: Rfence + Send + 'static>(rfence: T) {
-    *RFENCE.lock() = Some(Box::new(rfence));
+pub fn init_rfence<T: Rfence + Sync + 'static>(rfence: T) {
+    let result = RFENCE.set(Box::new(rfence));
+    if result.is_err() {
+        panic!("load sbi module when already loaded")
+    }
 }
 
 #[inline]
 pub(crate) fn probe_rfence() -> bool {
-    RFENCE.lock().as_ref().is_some()
+    RFENCE.get().is_some()
 }
 
 pub(crate) fn remote_fence_i(hart_mask: HartMask) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_fence_i(hart_mask)
     } else {
         SbiRet::not_supported()
@@ -143,7 +143,7 @@ pub(crate) fn remote_fence_i(hart_mask: HartMask) -> SbiRet {
 }
 
 pub(crate) fn remote_sfence_vma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_sfence_vma(hart_mask, start_addr, size)
     } else {
         SbiRet::not_supported()
@@ -151,7 +151,7 @@ pub(crate) fn remote_sfence_vma(hart_mask: HartMask, start_addr: usize, size: us
 }
 
 pub(crate) fn remote_sfence_vma_asid(hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_sfence_vma_asid(hart_mask, start_addr, size, asid)
     } else {
         SbiRet::not_supported()
@@ -159,7 +159,7 @@ pub(crate) fn remote_sfence_vma_asid(hart_mask: HartMask, start_addr: usize, siz
 }
 
 pub(crate) fn remote_hfence_gvma_vmid(hart_mask: HartMask, start_addr: usize, size: usize, vmid: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_hfence_gvma_vmid(hart_mask, start_addr, size, vmid)
     } else {
         SbiRet::not_supported()
@@ -167,7 +167,7 @@ pub(crate) fn remote_hfence_gvma_vmid(hart_mask: HartMask, start_addr: usize, si
 }
 
 pub(crate) fn remote_hfence_gvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_hfence_gvma(hart_mask, start_addr, size)
     } else {
         SbiRet::not_supported()
@@ -175,7 +175,7 @@ pub(crate) fn remote_hfence_gvma(hart_mask: HartMask, start_addr: usize, size: u
 }
 
 pub(crate) fn remote_hfence_vvma_asid(hart_mask: HartMask, start_addr: usize, size: usize, asid: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_hfence_vvma_asid(hart_mask, start_addr, size, asid)
     } else {
         SbiRet::not_supported()
@@ -183,7 +183,7 @@ pub(crate) fn remote_hfence_vvma_asid(hart_mask: HartMask, start_addr: usize, si
 }
 
 pub(crate) fn remote_hfence_vvma(hart_mask: HartMask, start_addr: usize, size: usize) -> SbiRet {
-    if let Some(rfence) = RFENCE.lock().as_mut() {
+    if let Some(rfence) = RFENCE.get() {
         rfence.remote_hfence_vvma(hart_mask, start_addr, size)
     } else {
         SbiRet::not_supported()

+ 12 - 11
src/timer.rs

@@ -1,3 +1,6 @@
+use alloc::boxed::Box;
+use crate::util::OnceFatBox;
+
 /// Timer programmer support
 pub trait Timer: Send {
     /// Programs the clock for next event after `stime_value` time.
@@ -7,29 +10,27 @@ pub trait Timer: Send {
     /// If the supervisor wishes to clear the timer interrupt without scheduling the next timer event,
     /// it can either request a timer interrupt infinitely far into the future (i.e., (uint64_t)-1),
     /// or it can instead mask the timer interrupt by clearing `sie.STIE` CSR bit.
-    fn set_timer(&mut self, stime_value: u64);
+    fn set_timer(&self, stime_value: u64);
 }
 
-use alloc::boxed::Box;
-use spin::Mutex;
-
-lazy_static::lazy_static! {
-    static ref TIMER: Mutex<Option<Box<dyn Timer>>> = Mutex::new(None);
-}
+static TIMER: OnceFatBox<dyn Timer + Sync + 'static> = OnceFatBox::new();
 
 #[doc(hidden)] // use through a macro
-pub fn init_timer<T: Timer + Send + 'static>(ipi: T) {
-    *TIMER.lock() = Some(Box::new(ipi));
+pub fn init_timer<T: Timer + Sync + 'static>(timer: T) {
+    let result = TIMER.set(Box::new(timer));
+    if result.is_err() {
+        panic!("load sbi module when already loaded")
+    }
 }
 
 #[inline]
 pub(crate) fn probe_timer() -> bool {
-    TIMER.lock().as_ref().is_some()
+    TIMER.get().is_some()
 }
 
 #[inline]
 pub(crate) fn set_timer(time_value: u64) -> bool {
-    if let Some(timer) = TIMER.lock().as_mut() {
+    if let Some(timer) = TIMER.get() {
         timer.set_timer(time_value);
         true
     } else {