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:42:07 +0800

On Tue, Jan 14, 2025 at 11:36:48PM +0800, Zhao Liu wrote:
> Date: Tue, 14 Jan 2025 23:36:48 +0800
> From: Zhao Liu <zhao1.liu@intel.com>
> Subject: Re: [RFC 07/13] rust: add bindings for timer
> 
> 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:

Missed rust_timer_handler, which follows the good example of FnCall doc:

unsafe extern "C" fn rust_timer_handler<T, F: for<'a> FnCall<(&'a T,)>>(opaque: 
*mut c_void) {
    // SAFETY: the opaque was passed as a reference to `T`.
    F::call((unsafe { &*(opaque.cast::<T>()) },))
}

 
> 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]