rust_rsm/rsm/
os_timer.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(dead_code)]
5
6use super::*;
7use core::ffi::c_void;
8use crate::common::{self,tsidallocator::TsIdAllocator,tsmap::TsHashMap};
9use std::mem;
10#[cfg(windows)]
11use windows_sys::Win32::Foundation::FILETIME;
12#[cfg(windows)]
13use windows_sys::Win32::System::Threading::{self,TP_CALLBACK_INSTANCE,TP_TIMER};
14
15#[cfg(unix)]
16use libc;
17
18pub type timer_call_back = fn(timer_id:i32,timer_data:usize);
19
20#[cfg(windows)]
21type os_callback_fn = unsafe extern "system" fn(instance: *mut TP_CALLBACK_INSTANCE, context: *mut c_void, timer: *mut TP_TIMER);
22#[cfg(windows)]
23#[no_mangle]
24unsafe extern "system" fn os_timer_callback(_instance: *mut TP_CALLBACK_INSTANCE, 
25        context: *mut c_void, _timer: *mut TP_TIMER) {
26    if context.is_null() {
27        return
28    }
29    
30    let tid = *(context as *const i32);
31    //println!("recv timer,os_timer={:?},data={:?},timer_id={},current={}", timer,
32    //    context,tid,common::format_datetime(&std::time::SystemTime::now()));    
33    let t= match get_timer_by_id(tid) {
34        None=>return,
35        Some(t)=>t,
36    };
37    (t.app_callback)(t.timer_id,t.timer_data);
38}
39
40#[cfg(unix)]
41type os_callback_fn = unsafe extern fn(ev:libc::sigval);
42#[cfg(unix)]
43#[no_mangle]
44unsafe extern "C" fn os_timer_callback(ev:libc::sigval) {
45    let tev = &ev;
46    if tev.sival_ptr.is_null() {
47        return
48    }
49    let tid = *(tev.sival_ptr as *const i32);
50    //println!("recv timer,timer id={:},current={}", tid,
51    //    common::format_datetime(&std::time::SystemTime::now()));    
52    let t= match get_timer_by_id(tid) {
53        None=>return,
54        Some(t)=>t,
55    };
56    (t.app_callback)(t.timer_id,t.timer_data);
57}
58
59#[derive(Clone,Debug)]
60pub struct os_timer_t {
61    dur_msec:u64,    
62    timer_data:usize,
63    timer_id:i32,
64    pub(crate) app_callback:timer_call_back,
65    #[cfg(unix)]
66    os_timer_id:libc::timer_t,
67    #[cfg(windows)]
68    os_timer_id:*mut TP_TIMER,
69}
70
71
72impl os_timer_t {
73    pub fn new(dur_msec:u64,timer_data:usize,callbackfn:timer_call_back)->Option<Self> {
74        let tid = match unsafe { &mut gOsTimerAlloc} {
75            None=>return None,
76            Some(a)=>{
77                let id = a.allocate_id();
78                if id==TsIdAllocator::INVALID_ID {
79                    return None;
80                }
81                id
82            },
83        };
84        unsafe {
85            gTimerData[tid as usize]=tid;
86        }
87        let os_tid = match unsafe {
88            set_os_timer(dur_msec, std::ptr::addr_of!(gTimerData[tid as usize]) as *mut u8, os_timer_callback)
89        } {
90            None=>return None,
91            Some(t)=>t,
92        };
93
94        let tm = Self {
95            dur_msec:dur_msec,    
96            timer_data:timer_data,
97            timer_id:tid,
98            os_timer_id:os_tid,
99            app_callback:callbackfn,
100        };
101        if insert_timer(tid, tm.clone()) != errcode::RESULT_SUCCESS {
102            return None
103        }
104        return Some(tm);
105    }
106
107    pub fn close(&mut self) {
108
109    }
110}
111
112const MAX_OS_TIMER_COUNT:usize = 1024;
113static mut gOsTimerAlloc:Option<TsIdAllocator> = None;
114static mut gOsTimerMap:Option<TsHashMap<i32,os_timer_t>> = None;
115static mut gTimerData:[i32;MAX_OS_TIMER_COUNT+1]=[0;MAX_OS_TIMER_COUNT+1];
116
117pub fn init_os_timer() {
118    unsafe {
119        if gOsTimerAlloc.is_none() {
120            gOsTimerAlloc = Some(TsIdAllocator::new(1, MAX_OS_TIMER_COUNT as i32));
121        }
122        if gOsTimerMap.is_none() {
123            gOsTimerMap = Some(TsHashMap::new(MAX_OS_TIMER_COUNT));
124        }
125    }    
126}
127
128fn insert_timer(tid:i32,timer:os_timer_t)->errcode::RESULT {
129    let tm = match unsafe {&mut gOsTimerMap} {
130        None=>return errcode::ERROR_NOT_INITIALIZED,
131        Some(m)=>m,
132    };
133    return tm.insert(tid,timer);
134}
135fn get_timer_by_id(tid:i32)->Option<&'static mut os_timer_t> {
136    let tm = match unsafe {&mut gOsTimerMap} {
137        None=>return None,
138        Some(m)=>m,
139    };
140    let t = tm.get_mut(&tid);
141    return t;
142}
143
144#[cfg(unix)]
145#[link(name = "os_linux", kind = "static")]
146extern "C"  {
147    fn c_create_timer(ptr_data:*mut u8,call_back:os_callback_fn,timer_id:*mut libc::timer_t)->i32;
148}
149
150#[cfg(unix)]
151unsafe fn set_os_timer(dur_msec:u64,data_ptr:*mut u8,call_back:os_callback_fn)->Option<libc::timer_t> {
152 
153    let mut timer_id=mem::zeroed::<libc::timer_t>();
154    /* create timer */
155    let res = c_create_timer(data_ptr, call_back,&mut timer_id as *mut libc::timer_t);
156    if res<0 {
157        println!("error create time,ret={}",res);
158        return None;
159    }
160
161    let tv_sec = dur_msec as i64 / 1000;
162    let tv_nsec=(dur_msec as i64 % 1000)*1000*1000;
163    let mut its = libc::itimerspec  {
164        it_interval:libc::timespec {
165                tv_sec:tv_sec,
166                tv_nsec:tv_nsec,
167            },
168            it_value:libc::timespec {
169                tv_sec:tv_sec,
170                tv_nsec:tv_nsec,
171            },
172    };
173    let res = libc::timer_settime(timer_id,0,&its as *const libc::itimerspec,std::ptr::null_mut());
174    if res<0 {
175        println!("error create time,ret={}",res);
176    }
177    
178    return Some(timer_id);
179
180}
181
182
183#[cfg(windows)]
184unsafe fn set_os_timer(dur_msec:u64,pdata:*mut u8,call_back:os_callback_fn)->Option<*mut TP_TIMER> {
185    let timer = Threading::CreateThreadpoolTimer(Some(call_back), pdata as *mut c_void,std::ptr::null());
186    if timer.is_null() {
187        println!("windows set timer failed,err={}",std::io::Error::last_os_error());
188        return None;
189    }
190
191    println!("windows set timer success,timer={:?}",timer);
192    let ftime = FILETIME {
193        dwLowDateTime:0xFFFFFFFF,
194        dwHighDateTime:0xFFFFFFFF,
195    };
196    Threading::SetThreadpoolTimer(timer,std::ptr::addr_of!(ftime),dur_msec as u32,0);
197    return Some(timer);
198}