1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/////////////////////////////////////////////////////////////////////////
// $Id: slowdown_timer.cc,v 1.9 2002/03/06 01:19:50 instinc Exp $
/////////////////////////////////////////////////////////////////////////
//
#include "bochs.h"
#include <errno.h>
#if BX_USE_SLOWDOWN_TIMER
//These need to stay printfs because they are useless in the log file.
#define BX_SLOWDOWN_PRINTF_FEEDBACK 0
#define SECINUSEC 1000000
#define usectosec(a) ((a)/SECINUSEC)
#define sectousec(a) ((a)*SECINUSEC)
#define nsectousec(a) ((a)/1000)
#if BX_HAVE_USLEEP
# define Qval 1000
#else
# define Qval SECINUSEC
#endif
#define MAXMULT 1.5
#define REALTIME_Q SECINUSEC
bx_slowdown_timer_c bx_slowdown_timer;
bx_slowdown_timer_c::bx_slowdown_timer_c() {
s.start_time=0;
s.start_emulated_time=0;
s.timer_handle=BX_NULL_TIMER_HANDLE;
}
int
bx_slowdown_timer_c::init() {
s.MAXmultiplier=MAXMULT;
s.Q=Qval;
if(s.MAXmultiplier<1)
s.MAXmultiplier=1;
s.start_time=sectousec(time(NULL));
s.start_emulated_time = bx_pc_system.time_usec();
s.lasttime=0;
s.timer_handle=bx_pc_system.register_timer(this, timer_handler, 100 , 1, 1);
bx_pc_system.deactivate_timer(s.timer_handle);
bx_pc_system.activate_timer(s.timer_handle,(Bit32u)s.Q,0);
return 0;
}
void
bx_slowdown_timer_c::timer_handler(void * this_ptr) {
bx_slowdown_timer_c * class_ptr = (bx_slowdown_timer_c *) this_ptr;
class_ptr->handle_timer();
}
void
bx_slowdown_timer_c::handle_timer() {
Bit64u total_emu_time = (bx_pc_system.time_usec()) - s.start_emulated_time;
Bit64u wanttime = s.lasttime+s.Q;
Bit64u totaltime = sectousec(time(NULL)) - s.start_time;
Bit64u thistime=(wanttime>totaltime)?wanttime:totaltime;
#if BX_SLOWDOWN_PRINTF_FEEDBACK
printf("Entering slowdown timer handler.\n");
#endif
/* Decide if we're behind.
* Set interrupt interval accordingly. */
if(totaltime > total_emu_time) {
bx_pc_system.deactivate_timer(s.timer_handle);
bx_pc_system.activate_timer(s.timer_handle,
(Bit32u)((Bit64u)
(s.MAXmultiplier * (float)s.Q)),
0);
#if BX_SLOWDOWN_PRINTF_FEEDBACK
printf("running at MAX speed\n");
#endif
} else {
bx_pc_system.deactivate_timer(s.timer_handle);
bx_pc_system.activate_timer(s.timer_handle,s.Q,0);
#if BX_SLOWDOWN_PRINTF_FEEDBACK
printf("running at NORMAL speed\n");
#endif
}
/* Make sure we took at least one time quantum. */
/* This is a little strange. I'll try to explain.
* We're running bochs one second ahead of real time.
* this gives us a very precise division on whether
* we're ahead or behind the second line.
* Basically, here's how it works:
* *****|******************|***********...
* Time Time+1sec
* <^Bochs doesn't delay.
* ^>Bochs delays.
* <^Bochs runs at MAX speed.
* ^>Bochs runs at normal
*/
if(wanttime > (totaltime+REALTIME_Q)) {
#if BX_HAVE_USLEEP
usleep(s.Q);
#else
sleep(usectosec(s.Q));
#endif
//delay(wanttime-totaltime);
/*alternatively: delay(Q);
* This works okay because we share the delay between
* two time quantums.
*/
#if BX_SLOWDOWN_PRINTF_FEEDBACK
printf("DELAYING for a quantum\n");
#endif
}
s.lasttime=thistime;
//Diagnostic info:
#if 0
if(wanttime > (totaltime+REALTIME_Q)) {
if(totaltime > total_emu_time) {
printf("Solving OpenBSD problem.\n");
} else {
printf("too fast.\n");
}
} else {
if(totaltime > total_emu_time) {
printf("too slow.\n");
} else {
printf("sometimes invalid state, normally okay.\n");
}
}
#endif // Diagnostic info
}
#endif
|