Skip to content

Commit

Permalink
support signal and compelte setitimer, alarm, etc
Browse files Browse the repository at this point in the history
  • Loading branch information
AuYang261 committed Oct 10, 2023
1 parent c55c30c commit 13bc960
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 0 deletions.
34 changes: 34 additions & 0 deletions modules/axruntime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern crate axlog;

#[cfg(all(target_os = "none", not(test)))]
mod lang_items;
mod signal;
mod trap;

#[cfg(feature = "smp")]
Expand All @@ -41,6 +42,8 @@ mod mp;
#[cfg(feature = "smp")]
pub use self::mp::rust_main_secondary;

pub use self::signal::{k_sigaction, Signal};

#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "alloc")]
Expand Down Expand Up @@ -355,8 +358,39 @@ fn init_interrupt() {
axhal::time::set_oneshot_timer(deadline);
}

fn do_signal() {
let now_ns = axhal::time::current_time_nanos();
// timer signal num
let timer = [14, 26, 27];
for which in 0..3 {
let mut ddl = Signal::timer_deadline(which, None).unwrap();
let interval = Signal::timer_interval(which, None).unwrap();
if ddl != 0 && now_ns >= ddl {
Signal::signal(timer[which], true);
if interval == 0 {
ddl = 0;
} else {
ddl += interval;
}
Signal::timer_deadline(which, Some(ddl));
}
}
let signal = Signal::signal(-1, true).unwrap();
for signum in 0..32 {
if signal & (1 << signum) != 0
/* TODO: && support mask */
{
Signal::sigaction(signum as u8, None, None);
Signal::signal(signum as i8, false);
}
}
}

axhal::irq::register_handler(TIMER_IRQ_NUM, || {
update_timer();
if axhal::cpu::this_cpu_is_bsp() {
do_signal();
}
#[cfg(feature = "multitask")]
axtask::on_timer_tick();
});
Expand Down
161 changes: 161 additions & 0 deletions modules/axruntime/src/signal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Rukos] is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#[cfg(feature = "irq")]
use core::sync::atomic::AtomicI64;
use core::{ffi::c_int, time::Duration};

#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
struct itimerval {
it_interval: Duration,
it_value: Duration,
}

/// sigset_t in kernel
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
pub struct __sigset_t {
__bits: [core::ffi::c_ulong; 16usize],
}

/// sigaction in kernel
#[allow(non_camel_case_types)]
#[allow(dead_code)]
#[derive(Copy, Clone, Debug, Default)]
pub struct k_sigaction {
/// signal handler
pub sa_handler: Option<unsafe extern "C" fn(c_int)>,
/// signal mask
pub sa_mask: __sigset_t,
/// signal flags
pub sa_flags: i32,
/// signal restorer
pub sa_restorer: Option<unsafe extern "C" fn()>,
}

/// Signal struct
pub struct Signal {
#[cfg(feature = "irq")]
signal: AtomicI64,
sigaction: [k_sigaction; 32],
timer: [itimerval; 3],
}

unsafe extern "C" fn default_handler(signum: c_int) {
panic!("default_handler, signum: {}", signum);
}

static mut SIGNAL_IF: Signal = Signal {
#[cfg(feature = "irq")]
signal: AtomicI64::new(0),
sigaction: [k_sigaction {
sa_handler: Some(default_handler),
sa_mask: __sigset_t { __bits: [0; 16] },
sa_flags: 0,
sa_restorer: None,
}; 32],
// Default::default() is not const
timer: [itimerval {
it_interval: Duration::new(0, 0),
it_value: Duration::new(0, 0),
}; 3],
};

impl Signal {
/// Set signal
/// signum: signal number, if signum < 0, just return current signal
/// on: true: enable signal, false: disable signal
#[cfg(feature = "irq")]
pub fn signal(signum: i8, on: bool) -> Option<u32> {
use core::sync::atomic::Ordering;
if signum >= 32 {
return None;
}
let mut old = unsafe { SIGNAL_IF.signal.load(Ordering::Acquire) };
if signum >= 0 {
loop {
let new;
if on {
new = old | (1 << signum);
} else {
new = old & !(1 << signum);
}

match unsafe {
SIGNAL_IF.signal.compare_exchange_weak(
old,
new,
Ordering::AcqRel,
Ordering::Acquire,
)
} {
Ok(_) => break,
Err(x) => old = x,
}
}
}
Some(old.try_into().unwrap())
}
/// Set signal action
/// signum: signal number
/// sigaction: signal action, if sigaction == None, call the handler
pub fn sigaction(
signum: u8,
sigaction: Option<&k_sigaction>,
oldact: Option<&mut k_sigaction>,
) {
if signum >= unsafe { SIGNAL_IF.sigaction }.len() as u8 {
return;
}
if let Some(oldact) = oldact {
*oldact = unsafe { SIGNAL_IF.sigaction[signum as usize] };
}
match sigaction {
Some(s) => unsafe {
SIGNAL_IF.sigaction[signum as usize] = *s;
},
None => unsafe {
SIGNAL_IF.sigaction[signum as usize].sa_handler.unwrap()(signum as c_int)
},
}
}
/// Set timer
/// which: timer type
/// new_value: new timer value
/// old_value: old timer value
pub fn timer_deadline(which: usize, new_deadline: Option<u64>) -> Option<u64> {
if which >= unsafe { SIGNAL_IF.timer }.len() {
return None;
}
let old = unsafe { SIGNAL_IF.timer }[which].it_value;
if let Some(s) = new_deadline {
unsafe {
SIGNAL_IF.timer[which].it_value = Duration::from_nanos(s);
}
}
Some(old.as_nanos() as u64)
}
/// Set timer interval
/// which: timer type
/// new_interval: new timer interval
/// old_interval: old timer interval
pub fn timer_interval(which: usize, new_interval: Option<u64>) -> Option<u64> {
if which >= unsafe { SIGNAL_IF.timer }.len() {
return None;
}
let old = unsafe { SIGNAL_IF.timer }[which].it_interval;
if let Some(s) = new_interval {
unsafe {
SIGNAL_IF.timer[which].it_interval = Duration::from_nanos(s);
}
}
Some(old.as_nanos() as u64)
}
}

0 comments on commit 13bc960

Please sign in to comment.