File: slowdown_timer.cc

package info (click to toggle)
bochs 1.4pre2-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 7,656 kB
  • ctags: 10,322
  • sloc: cpp: 66,880; ansic: 19,674; sh: 2,951; makefile: 2,183; asm: 2,110; yacc: 723; lex: 171; csh: 147; perl: 35
file content (138 lines) | stat: -rw-r--r-- 3,669 bytes parent folder | download
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