qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC 07/13] rust: add bindings for timer


From: Zhao Liu
Subject: Re: [RFC 07/13] rust: add bindings for timer
Date: Tue, 14 Jan 2025 23:36:48 +0800

Hi Paolo,

Thanks for your FnCall and the guidance below...

> This gets tricky when you have more than one timer per device.  With the right
> infrastructure we can make this something like
> 
>     fn timer_init_full<'a, 'b: 'a, T, F: 'b Fn(&'b T)>(
>         &'a mut self,
>         timer_list_group: Option<&mut QEMUTimerListGroup>,
>         clk_type: QEMUClockType,
>         scale: u32,
>         attributes: u32,
>         f: &F,
>         opaque: &'b T) {
>         // SAFETY: the opaque outlives the timer
>         unsafe {
>             timer_init_full(...)
>         }
>     }

...

> pub struct Clock {
>     id: QEMUClockType
> }
> 
> impl Clock {
>     pub fn get_ns() -> u64 {
>         // SAFETY: cannot be created outside this module, therefore id
>         // is valid
>         (unsafe { qemu_clock_get_ns(self.id) }) as u64
>     }
> }
> 
> pub static CLOCK_VIRTUAL: Clock = Clock { id: 
> QEMUClockType::QEMU_CLOCK_VIRTUAL };
> // etc.
> 
> and then the user can do timer::CLOCK_VIRTUAL::get_ns().
>

...Now I have a draft for timer binding:

* timer binding:

impl QEMUTimer {
    pub fn new() -> Self {
        Zeroable::ZERO
    }

    pub fn timer_init_full<'a, 'b: 'a, T, F>(
        &'a mut self,
        timer_list_group: Option<&mut QEMUTimerListGroup>,
        clk_type: QEMUClockType,
        scale: u32,
        attributes: u32,
        _f: &F,
        opaque: &'b T,
    ) where
        F: for<'c> FnCall<(&'c T,)> + 'b,
    {
        let timer_cb: unsafe extern "C" fn(*mut c_void) = 
rust_timer_handler::<T, F>;

        // SAFETY: the opaque outlives the timer
        unsafe {
            timer_init_full(
                self,
                if let Some(g) = timer_list_group {
                    g
                } else {
                    ::core::ptr::null_mut()
                },
                clk_type,
                scale as c_int,
                attributes as c_int,
                Some(timer_cb),
                opaque as *const T as *const c_void as *mut c_void,
            )
        }
    }

    pub fn timer_mod(&mut self, expire_time: u64) {
        unsafe { timer_mod(self as *mut QEMUTimer, expire_time as i64) }
    }
}


* use of timer binding:

fn timer_handler(timer_cell: &BqlRefCell<HPETTimer>) {
    timer_cell.borrow_mut().callback()
}

impl HPETTimer {
    ...

    fn init_timer_with_state(&mut self) {
        let index = self.index;
        let cb = |cell: &BqlRefCell<HPETTimer>| {
            timer_handler(cell);
        };

        self.qemu_timer = Some(Box::new({
            let mut t = QEMUTimer::new();
            t.timer_init_full(
                None,
                CLOCK_VIRTUAL.id,
                SCALE_NS,
                0,
                &cb,
                &self.get_state().timer[index],
            );
            t
        }));
    }
    ...
}

---

Is this timer binding as you expected? Hope I am on the right track. :-)

Thanks,
Zhao





reply via email to

[Prev in Thread] Current Thread [Next in Thread]