1 ////////////////////////////////////////////////////////////////////////
2 // $Id: virt_timer.h 14109 2021-01-30 23:55:24Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2002-2021  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21 
22 #ifndef _BX_VIRT_TIMER_H
23 #define _BX_VIRT_TIMER_H
24 
25 #include "pc_system.h"
26 
27 // should be adjusted if want to support more SMP processors
28 #define BX_MAX_VIRTUAL_TIMERS (32)
29 
30 #define BX_MAX_VIRTUAL_TIME (0x7fffffff)
31 
32 class BOCHSAPI bx_virt_timer_c : public logfunctions {
33 private:
34 
35   struct {
36     bool inUse;         // Timer slot is in-use (currently registered).
37     Bit64u  period;     // Timer periodocity in virtual useconds.
38     Bit64u  timeToFire; // Time to fire next (in virtual useconds).
39     bool active;        // 0=inactive, 1=active.
40     bool continuous;    // 0=one-shot timer, 1=continuous periodicity.
41     bool realtime;      // 0=standard timer, 1=use realtime mode
42     bx_timer_handler_t funct;  // A callback function for when the
43                                //   timer fires.
44                                //   This function MUST return.
45     void *this_ptr;            // The this-> pointer for C++ callbacks
46                                //   has to be stored as well.
47     char id[BxMaxTimerIDLen]; // String ID of timer.
48   } timer[BX_MAX_VIRTUAL_TIMERS];
49 
50   unsigned   numTimers;  // Number of currently allocated timers.
51 
52   struct {
53     //Variables for the timer subsystem:
54     Bit64u current_timers_time;
55     Bit64u timers_next_event_time;
56     Bit64u last_sequential_time;
57 
58     //Variables for the time sync subsystem:
59     Bit64u virtual_next_event_time;
60     Bit64u current_virtual_time;
61 
62     int system_timer_id;
63   } s[2];
64 
65   bool in_timer_handler;
66 
67   // Local copy of IPS value
68   Bit64u ips;
69 
70   bool init_done;
71 
72   //Real time variables:
73   Bit64u last_real_time;
74   Bit64u total_real_usec;
75   Bit64u last_realtime_delta;
76   Bit64u real_time_delay;
77   //System time variables:
78   Bit64u last_usec;
79   Bit64u usec_per_second;
80   Bit64u stored_delta;
81   Bit64u last_system_usec;
82   Bit64u em_last_realtime;
83   //Virtual timer variables:
84   Bit64u total_ticks;
85   Bit64u last_realtime_ticks;
86   Bit64u ticks_per_second;
87 
88   // A special null timer is always inserted in the timer[0] slot.  This
89   // make sure that at least one timer is always active, and that the
90   // duration is always less than a maximum 32-bit integer, so a 32-bit
91   // counter can be used for the current countdown.
92   static const Bit64u NullTimerInterval;
93   static void nullTimer(void* this_ptr);
94 
95   //Step the given number of cycles, optionally calling any timer handlers.
96   void periodic(Bit64u time_passed, bool mode);
97 
98   //Called when next_event_time changes.
99   void next_event_time_update(bool mode);
100 
101   //Called to advance the virtual time.
102   // calls periodic as needed.
103   void advance_virtual_time(Bit64u time_passed, bool mode);
104 
105 public:
106 
107   bx_virt_timer_c();
~bx_virt_timer_c()108   virtual ~bx_virt_timer_c() {}
109 
110   //Get the current virtual time.
111   //  This may return the same value on subsequent calls.
112   Bit64u time_usec(bool mode);
113 
114   //Get the current virtual time.
115   //  This will return a monotonically increasing value.
116   // MUST NOT be called from within a timer handler.
117   Bit64u time_usec_sequential(bool mode);
118 
119   //Register a timer handler to go off after a given interval.
120   //Register a timer handler to go off with a periodic interval.
121   int  register_timer(void *this_ptr, bx_timer_handler_t handler,
122                          Bit32u useconds, bool continuous,
123                          bool active, bool realtime, const char *id);
124 
125   //unregister a previously registered timer.
126   bool unregisterTimer(unsigned timerID);
127 
128   void start_timers(void);
129 
130   //activate a deactivated but registered timer.
131   void activate_timer(unsigned timer_index, Bit32u useconds,
132                       bool continuous);
133 
134   //deactivate (but don't unregister) a currently registered timer.
135   void deactivate_timer(unsigned timer_index);
136 
137 
138   //Timer handlers passed to pc_system
139   static void pc_system_timer_handler_0(void* this_ptr);
140   static void pc_system_timer_handler_1(void* this_ptr);
141 
142   //The real timer handler.
143   void timer_handler(bool mode);
144 
145   //Initialization step #1 in constructor and for cleanup
146   void setup(void);
147 
148   //Initialization step #2
149   void init(void);
150 
151   void register_state(void);
152 
153   //Determine the real time elapsed during runtime config or between save and
154   //restore.
155   void set_realtime_delay(void);
156 };
157 
158 BOCHSAPI extern bx_virt_timer_c bx_virt_timer;
159 
160 #endif // _BX_VIRT_TIMER_H
161