Fixed compilation error
[bochs-mirror.git] / iodev / virt_timer.cc
blob6ae7fefc78000fde91d52dfddfd07e23832f9346
1 ////////////////////////////////////////////////////////////////////////
2 // $Id: virt_timer.cc,v 1.37 2008/02/15 22:05:43 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ////////////////////////////////////////////////////////////////////////
28 /////////////////////////////////////////////////////////////////////////
30 //Realtime Algorithm (with gettimeofday)
31 // HAVE:
32 // Real number of usec.
33 // Emulated number of usec.
34 // WANT:
35 // Number of ticks to use.
36 // Number of emulated usec to wait until next try.
38 // ticks=number of ticks needed to match total real usec.
39 // if(desired ticks > max ticks for elapsed real time)
40 // ticks = max ticks for elapsed real time.
41 // if(desired ticks > max ticks for elapsed emulated usec)
42 // ticks = max ticks for emulated usec.
43 // next wait ticks = number of ticks until next event.
44 // next wait real usec = (current ticks + next wait ticks) * usec per ticks
45 // next wait emulated usec = next wait real usec * emulated usec / real usec
46 // if(next wait emulated usec < minimum emulated usec for next wait ticks)
47 // next wait emulated usec = minimum emulated usec for next wait ticks.
48 // if(next wait emulated usec > max emulated usec wait)
49 // next wait emulated usec = max emulated usec wait.
51 // How to calculate elapsed real time:
52 // store an unused time value whenever no ticks are used in a given time.
53 // add this to the current elapsed time.
54 // How to calculate elapsed emulated time:
55 // same as above.
56 // Above can be done by not updating last_usec and last_sec.
58 // How to calculate emulated usec/real usec:
59 // Each time there are actual ticks:
60 // Alpha_product(old emulated usec, emulated usec);
61 // Alpha_product(old real usec, real usec);
62 // Divide resulting values.
64 /////////////////////////////////////////////////////////////////////////
66 #include "bochs.h"
67 #include "virt_timer.h"
69 #define BX_USE_VIRTUAL_TIMERS 1
70 #define BX_VIRTUAL_TIMERS_REALTIME 1
72 //Important constant #defines:
73 #define USEC_PER_SECOND (1000000)
76 // define a macro to convert floating point numbers into 64-bit integers.
77 // In MSVC++ you can convert a 64-bit float into a 64-bit signed integer,
78 // but it will not convert a 64-bit float into a 64-bit unsigned integer.
79 // This macro works around that.
80 #define F2I(x) ((Bit64u)(Bit64s) (x))
81 #define I2F(x) ((double)(Bit64s) (x))
83 //CONFIGURATION #defines:
86 //MAINLINE Configuration (For realtime PIT):
88 //How much faster than real time we can go:
89 #define MAX_MULT (1.25)
91 //Minimum number of emulated useconds per second.
92 // Now calculated using BX_MIN_IPS, the minimum number of
93 // instructions per second.
94 #define MIN_USEC_PER_SECOND (((((Bit64u)USEC_PER_SECOND)*((Bit64u)BX_MIN_IPS))/((Bit64u)(SIM->get_param_num(BXPN_IPS)->get())))+(Bit64u)1)
97 //DEBUG configuration:
99 //Debug with printf options.
100 #define DEBUG_REALTIME_WITH_PRINTF 0
102 //Use to test execution at multiples of real time.
103 #define TIME_DIVIDER (1)
104 #define TIME_MULTIPLIER (1)
105 #define TIME_HEADSTART (0)
108 #define GET_VIRT_REALTIME64_USEC() (((bx_get_realtime64_usec()*(Bit64u)TIME_MULTIPLIER/(Bit64u)TIME_DIVIDER)))
109 //Set up Logging.
110 #define LOG_THIS bx_virt_timer.
112 //A single instance.
113 bx_virt_timer_c bx_virt_timer;
116 //Generic MAX and MIN Functions
117 #define BX_MAX(a,b) ( ((a)>(b))?(a):(b) )
118 #define BX_MIN(a,b) ( ((a)>(b))?(b):(a) )
121 //USEC_ALPHA is multiplier for the past.
122 //USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present.
123 #define USEC_ALPHA ((double)(.8))
124 #define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA))
125 #define USEC_ALPHA2 ((double)(.5))
126 #define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2))
127 #define ALPHA_LOWER(old,new) ((Bit64u)((old<new)?((USEC_ALPHA*(I2F(old)))+(USEC_ALPHA_B*(I2F(new)))):((USEC_ALPHA2*(I2F(old)))+(USEC_ALPHA2_B*(I2F(new))))))
130 //Conversion between emulated useconds and optionally realtime ticks.
131 #define TICKS_TO_USEC(a) (((a)*usec_per_second)/ticks_per_second)
132 #define USEC_TO_TICKS(a) (((a)*ticks_per_second)/usec_per_second)
134 bx_virt_timer_c::bx_virt_timer_c()
136 put("VTIMER");
137 settype(VTIMERLOG);
139 setup();
142 const Bit64u bx_virt_timer_c::NullTimerInterval = BX_MAX_VIRTUAL_TIME;
144 void bx_virt_timer_c::nullTimer(void* this_ptr)
146 UNUSED(this_ptr);
149 void bx_virt_timer_c::periodic(Bit64u time_passed)
151 //Assert that we haven't skipped any events.
152 BX_ASSERT (time_passed <= timers_next_event_time);
153 BX_ASSERT(!in_timer_handler);
155 //Update time variables.
156 timers_next_event_time -= time_passed;
157 current_timers_time += time_passed;
159 //If no events are occurring, just pass the time and we're done.
160 if(time_passed < timers_next_event_time) return;
162 //Starting timer handler calls.
163 in_timer_handler = 1;
164 //Otherwise, cause any events to occur that should.
165 unsigned i;
166 for(i=0;i<numTimers;i++) {
167 if(timer[i].inUse && timer[i].active) {
168 //Assert that we haven't skipped any timers.
169 BX_ASSERT(current_timers_time <= timer[i].timeToFire);
170 if(timer[i].timeToFire == current_timers_time) {
171 if(timer[i].continuous) {
172 timer[i].timeToFire+=timer[i].period;
173 } else {
174 timer[i].active = 0;
176 //This function MUST return, or the timer mechanism
177 // will be broken.
178 timer[i].funct(timer[i].this_ptr);
182 //Finished timer handler calls.
183 in_timer_handler = 0;
184 //Use a second FOR loop so that a timer function call can
185 // change the behavior of another timer.
186 //timers_next_event_time normally contains a cycle count, not a cycle time.
187 // here we use it as a temporary variable that IS a cycle time,
188 // but then convert it back to a cycle count afterwards.
189 timers_next_event_time = current_timers_time + BX_MAX_VIRTUAL_TIME;
190 for(i=0;i<numTimers;i++) {
191 if(timer[i].inUse && timer[i].active && ((timer[i].timeToFire)<timers_next_event_time)) {
192 timers_next_event_time = timer[i].timeToFire;
195 timers_next_event_time-=current_timers_time;
196 next_event_time_update();
197 //FIXME
201 //Get the current virtual time.
202 // This may return the same value on subsequent calls.
203 Bit64u bx_virt_timer_c::time_usec(void)
205 if(!use_virtual_timers) {
206 return bx_pc_system.time_usec();
209 //Update the time here only if we're not in a timer handler.
210 //If we're in a timer handler we're up-to-date, and otherwise
211 // this prevents call stack loops.
212 if(!in_timer_handler) {
213 timer_handler();
216 return current_timers_time;
219 //Get the current virtual time.
220 // This will return a monotonically increasing value.
221 // MUST NOT be called from within a timer interrupt.
222 Bit64u bx_virt_timer_c::time_usec_sequential(void)
224 if(!use_virtual_timers) {
225 return bx_pc_system.time_usec_sequential();
228 //Can't prevent call stack loops here, so this
229 // MUST NOT be called from within a timer handler.
230 BX_ASSERT(timers_next_event_time>0);
231 BX_ASSERT(!in_timer_handler);
233 if(last_sequential_time >= current_timers_time) {
234 periodic(1);
235 last_sequential_time = current_timers_time;
237 return current_timers_time;
241 //Register a timer handler to go off after a given interval.
242 //Register a timer handler to go off with a periodic interval.
243 int bx_virt_timer_c::register_timer(void *this_ptr, bx_timer_handler_t handler,
244 Bit32u useconds,
245 bx_bool continuous, bx_bool active,
246 const char *id)
248 if(!use_virtual_timers) {
249 return bx_pc_system.register_timer(this_ptr, handler, useconds,
250 continuous, active, id);
253 //We don't like starting with a zero period timer.
254 BX_ASSERT((!active) || (useconds>0));
256 //Search for an unused timer.
257 unsigned int i;
258 for (i=0; i < numTimers; i++) {
259 if (timer[i].inUse == 0 || i==numTimers)
260 break;
262 // If we didn't find a free slot, increment the bound, numTimers.
263 if (i==numTimers)
264 numTimers++; // One new timer installed.
265 BX_ASSERT(numTimers<BX_MAX_VIRTUAL_TIMERS);
267 timer[i].inUse = 1;
268 timer[i].period = useconds;
269 timer[i].timeToFire = current_timers_time + (Bit64u)useconds;
270 timer[i].active = active;
271 timer[i].continuous = continuous;
272 timer[i].funct = handler;
273 timer[i].this_ptr = this_ptr;
274 strncpy(timer[i].id, id, BxMaxTimerIDLen);
275 timer[i].id[BxMaxTimerIDLen-1]=0; //I like null terminated strings.
277 if(useconds < timers_next_event_time) {
278 timers_next_event_time = useconds;
279 next_event_time_update();
280 //FIXME
282 return i;
285 //unregister a previously registered timer.
286 bx_bool bx_virt_timer_c::unregisterTimer(unsigned timerID)
288 if(!use_virtual_timers)
289 return bx_pc_system.unregisterTimer(timerID);
291 BX_ASSERT(timerID < BX_MAX_VIRTUAL_TIMERS);
293 if (timer[timerID].active) {
294 BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[timerID].id));
295 return(0); // Fail.
298 //No need to prevent doing this to unused timers.
299 timer[timerID].inUse = 0;
300 if (timerID == (numTimers-1)) numTimers--;
301 return(1);
304 void bx_virt_timer_c::start_timers(void)
306 if(!use_virtual_timers) {
307 bx_pc_system.start_timers();
308 return;
310 //FIXME
313 //activate a deactivated but registered timer.
314 void bx_virt_timer_c::activate_timer(unsigned timer_index, Bit32u useconds,
315 bx_bool continuous)
317 if(!use_virtual_timers) {
318 bx_pc_system.activate_timer(timer_index, useconds, continuous);
319 return;
322 BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS);
324 BX_ASSERT(timer[timer_index].inUse);
325 BX_ASSERT(useconds>0);
327 timer[timer_index].period=useconds;
328 timer[timer_index].timeToFire = current_timers_time + (Bit64u)useconds;
329 timer[timer_index].active=1;
330 timer[timer_index].continuous=continuous;
332 if(useconds < timers_next_event_time) {
333 timers_next_event_time = useconds;
334 next_event_time_update();
335 //FIXME
339 //deactivate (but don't unregister) a currently registered timer.
340 void bx_virt_timer_c::deactivate_timer(unsigned timer_index)
342 if(!use_virtual_timers) {
343 bx_pc_system.deactivate_timer(timer_index);
344 return;
347 BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS);
349 //No need to prevent doing this to unused/inactive timers.
350 timer[timer_index].active = 0;
353 void bx_virt_timer_c::advance_virtual_time(Bit64u time_passed)
355 BX_ASSERT(time_passed <= virtual_next_event_time);
357 current_virtual_time += time_passed;
358 virtual_next_event_time -= time_passed;
360 if(current_virtual_time > current_timers_time) {
361 periodic(current_virtual_time - current_timers_time);
365 //Called when next_event_time changes.
366 void bx_virt_timer_c::next_event_time_update(void)
368 virtual_next_event_time = timers_next_event_time + current_timers_time - current_virtual_time;
369 if(init_done) {
370 bx_pc_system.deactivate_timer(system_timer_id);
371 BX_ASSERT(virtual_next_event_time);
372 bx_pc_system.activate_timer(system_timer_id,
373 (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))),
378 void bx_virt_timer_c::setup(void)
380 numTimers = 0;
381 current_timers_time = 0;
382 timers_next_event_time = BX_MAX_VIRTUAL_TIME;
383 last_sequential_time = 0;
384 in_timer_handler = 0;
385 virtual_next_event_time = BX_MAX_VIRTUAL_TIME;
386 current_virtual_time = 0;
388 use_virtual_timers = BX_USE_VIRTUAL_TIMERS;
389 init_done = 0;
392 void bx_virt_timer_c::init(void)
394 if ((SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()!=BX_CLOCK_SYNC_REALTIME) &&
395 (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()!=BX_CLOCK_SYNC_BOTH))
396 virtual_timers_realtime = 0;
397 else
398 virtual_timers_realtime = 1;
400 if (virtual_timers_realtime) {
401 BX_INFO(("using 'realtime pit' synchronization method"));
404 register_timer(this, nullTimer, (Bit32u)NullTimerInterval, 1, 1, "Null Timer");
406 system_timer_id = bx_pc_system.register_timer(this, pc_system_timer_handler,
407 (Bit32u)virtual_next_event_time, 0, 1, "Virtual Timer");
409 //Real time variables:
410 #if BX_HAVE_REALTIME_USEC
411 last_real_time=GET_VIRT_REALTIME64_USEC()+(Bit64u)TIME_HEADSTART*(Bit64u)USEC_PER_SECOND;
412 #endif
413 total_real_usec=0;
414 last_realtime_delta=0;
415 //System time variables:
416 last_usec = 0;
417 usec_per_second = USEC_PER_SECOND;
418 stored_delta=0;
419 last_system_usec=0;
420 em_last_realtime=0;
421 //Virtual timer variables:
422 total_ticks=0;
423 last_realtime_ticks=0;
424 ticks_per_second = USEC_PER_SECOND;
426 init_done = 1;
429 void bx_virt_timer_c::register_state(void)
431 bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "virt_timer", "Virtual Timer State", 17);
432 bx_list_c *vtimers = new bx_list_c(list, "timer", numTimers);
433 for (unsigned i = 0; i < numTimers; i++) {
434 char name[4];
435 sprintf(name, "%d", i);
436 bx_list_c *bxtimer = new bx_list_c(vtimers, name, 5);
437 BXRS_PARAM_BOOL(bxtimer, inUse, timer[i].inUse);
438 BXRS_DEC_PARAM_FIELD(bxtimer, period, timer[i].period);
439 BXRS_DEC_PARAM_FIELD(bxtimer, timeToFire, timer[i].timeToFire);
440 BXRS_PARAM_BOOL(bxtimer, active, timer[i].active);
441 BXRS_PARAM_BOOL(bxtimer, continuous, timer[i].continuous);
443 BXRS_DEC_PARAM_SIMPLE(list, current_timers_time);
444 BXRS_DEC_PARAM_SIMPLE(list, timers_next_event_time);
445 BXRS_DEC_PARAM_SIMPLE(list, last_sequential_time);
446 BXRS_DEC_PARAM_SIMPLE(list, virtual_next_event_time);
447 BXRS_DEC_PARAM_SIMPLE(list, current_virtual_time);
448 BXRS_DEC_PARAM_SIMPLE(list, last_real_time);
449 BXRS_DEC_PARAM_SIMPLE(list, total_real_usec);
450 BXRS_DEC_PARAM_SIMPLE(list, last_realtime_delta);
451 BXRS_DEC_PARAM_SIMPLE(list, last_usec);
452 BXRS_DEC_PARAM_SIMPLE(list, usec_per_second);
453 BXRS_DEC_PARAM_SIMPLE(list, stored_delta);
454 BXRS_DEC_PARAM_SIMPLE(list, last_system_usec);
455 BXRS_DEC_PARAM_SIMPLE(list, em_last_realtime);
456 BXRS_DEC_PARAM_SIMPLE(list, total_ticks);
457 BXRS_DEC_PARAM_SIMPLE(list, last_realtime_ticks);
458 BXRS_DEC_PARAM_SIMPLE(list, ticks_per_second);
462 void bx_virt_timer_c::timer_handler(void)
464 if(!virtual_timers_realtime) {
465 Bit64u temp_final_time = bx_pc_system.time_usec();
466 temp_final_time-=current_virtual_time;
467 while(temp_final_time) {
468 if((temp_final_time)>(virtual_next_event_time)) {
469 temp_final_time-=virtual_next_event_time;
470 advance_virtual_time(virtual_next_event_time);
471 } else {
472 advance_virtual_time(temp_final_time);
473 temp_final_time-=temp_final_time;
476 bx_pc_system.activate_timer(system_timer_id,
477 (Bit32u)BX_MIN(0x7FFFFFFF,(virtual_next_event_time>2)?(virtual_next_event_time-2):1),
479 return;
482 Bit64u usec_delta = bx_pc_system.time_usec()-last_usec;
484 if (usec_delta) {
485 #if BX_HAVE_REALTIME_USEC
486 Bit64u ticks_delta = 0;
487 Bit64u real_time_delta = GET_VIRT_REALTIME64_USEC() - last_real_time;
488 Bit64u real_time_total = real_time_delta + total_real_usec;
489 Bit64u system_time_delta = (Bit64u)usec_delta + (Bit64u)stored_delta;
490 if(real_time_delta) {
491 last_realtime_delta = real_time_delta;
492 last_realtime_ticks = total_ticks;
494 ticks_per_second = USEC_PER_SECOND;
496 //Start out with the number of ticks we would like
497 // to have to line up with real time.
498 ticks_delta = real_time_total - total_ticks;
499 if(real_time_total < total_ticks) {
500 //This slows us down if we're already ahead.
501 // probably only an issue on startup, but it solves some problems.
502 ticks_delta = 0;
504 if(ticks_delta + total_ticks - last_realtime_ticks > (F2I(MAX_MULT * I2F(last_realtime_delta)))) {
505 //This keeps us from going too fast in relation to real time.
506 #if 0
507 ticks_delta = (F2I(MAX_MULT * I2F(last_realtime_delta))) + last_realtime_ticks - total_ticks;
508 #endif
509 ticks_per_second = F2I(MAX_MULT * I2F(USEC_PER_SECOND));
511 if(ticks_delta > system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND) {
512 //This keeps us from having too few instructions between ticks.
513 ticks_delta = system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND;
515 if(ticks_delta > virtual_next_event_time) {
516 //This keeps us from missing ticks.
517 ticks_delta = virtual_next_event_time;
520 if(ticks_delta) {
522 # if DEBUG_REALTIME_WITH_PRINTF
523 //Every second print some info.
524 if(((last_real_time + real_time_delta) / USEC_PER_SECOND) > (last_real_time / USEC_PER_SECOND)) {
525 Bit64u temp1, temp2, temp3, temp4;
526 temp1 = (Bit64u) total_real_usec;
527 temp2 = (total_real_usec);
528 temp3 = (Bit64u)total_ticks;
529 temp4 = (Bit64u)((total_real_usec) - total_ticks);
530 printf("useconds: " FMT_LL "u, ", temp1);
531 printf("expect ticks: " FMT_LL "u, ", temp2);
532 printf("ticks: " FMT_LL "u, ", temp3);
533 printf("diff: "FMT_LL "u\n", temp4);
535 # endif
537 last_real_time += real_time_delta;
538 total_real_usec += real_time_delta;
539 last_system_usec += system_time_delta;
540 stored_delta = 0;
541 total_ticks += ticks_delta;
542 } else {
543 stored_delta = system_time_delta;
546 Bit64u a = usec_per_second, b;
547 if(real_time_delta) {
548 //FIXME
549 Bit64u em_realtime_delta = last_system_usec + stored_delta - em_last_realtime;
550 b=((Bit64u)USEC_PER_SECOND * em_realtime_delta / real_time_delta);
551 em_last_realtime = last_system_usec + stored_delta;
552 } else {
553 b=a;
555 usec_per_second = ALPHA_LOWER(a,b);
556 #else
557 BX_ASSERT(0);
558 #endif
559 #if BX_HAVE_REALTIME_USEC
560 advance_virtual_time(ticks_delta);
561 #endif
564 last_usec=last_usec + usec_delta;
565 bx_pc_system.deactivate_timer(system_timer_id);
566 BX_ASSERT(virtual_next_event_time);
567 bx_pc_system.activate_timer(system_timer_id,
568 (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))),
572 void bx_virt_timer_c::pc_system_timer_handler(void* this_ptr)
574 ((bx_virt_timer_c *)this_ptr)->timer_handler();