Revision f3fc6e2e
b/qemu-timer.c | ||
---|---|---|
153 | 153 |
char const *name; |
154 | 154 |
int (*start)(struct qemu_alarm_timer *t); |
155 | 155 |
void (*stop)(struct qemu_alarm_timer *t); |
156 |
void (*rearm)(struct qemu_alarm_timer *t); |
|
156 |
void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
|
|
157 | 157 |
#if defined(__linux__) |
158 | 158 |
int fd; |
159 | 159 |
timer_t timer; |
... | ... | |
181 | 181 |
return !!t->rearm; |
182 | 182 |
} |
183 | 183 |
|
184 |
static int64_t qemu_next_alarm_deadline(void) |
|
185 |
{ |
|
186 |
int64_t delta; |
|
187 |
int64_t rtdelta; |
|
188 |
|
|
189 |
if (!use_icount && vm_clock->active_timers) { |
|
190 |
delta = vm_clock->active_timers->expire_time - |
|
191 |
qemu_get_clock_ns(vm_clock); |
|
192 |
} else { |
|
193 |
delta = INT32_MAX; |
|
194 |
} |
|
195 |
if (host_clock->active_timers) { |
|
196 |
int64_t hdelta = host_clock->active_timers->expire_time - |
|
197 |
qemu_get_clock_ns(host_clock); |
|
198 |
if (hdelta < delta) { |
|
199 |
delta = hdelta; |
|
200 |
} |
|
201 |
} |
|
202 |
if (rt_clock->active_timers) { |
|
203 |
rtdelta = (rt_clock->active_timers->expire_time - |
|
204 |
qemu_get_clock_ns(rt_clock)); |
|
205 |
if (rtdelta < delta) { |
|
206 |
delta = rtdelta; |
|
207 |
} |
|
208 |
} |
|
209 |
|
|
210 |
return delta; |
|
211 |
} |
|
212 |
|
|
184 | 213 |
static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) |
185 | 214 |
{ |
186 |
if (!alarm_has_dynticks(t)) |
|
215 |
int64_t nearest_delta_ns; |
|
216 |
assert(alarm_has_dynticks(t)); |
|
217 |
if (!rt_clock->active_timers && |
|
218 |
!vm_clock->active_timers && |
|
219 |
!host_clock->active_timers) { |
|
187 | 220 |
return; |
188 |
|
|
189 |
t->rearm(t); |
|
221 |
} |
|
222 |
nearest_delta_ns = qemu_next_alarm_deadline(); |
|
223 |
t->rearm(t, nearest_delta_ns); |
|
190 | 224 |
} |
191 | 225 |
|
192 | 226 |
/* TODO: MIN_TIMER_REARM_NS should be optimized */ |
... | ... | |
196 | 230 |
|
197 | 231 |
static int mm_start_timer(struct qemu_alarm_timer *t); |
198 | 232 |
static void mm_stop_timer(struct qemu_alarm_timer *t); |
199 |
static void mm_rearm_timer(struct qemu_alarm_timer *t); |
|
233 |
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
|
|
200 | 234 |
|
201 | 235 |
static int win32_start_timer(struct qemu_alarm_timer *t); |
202 | 236 |
static void win32_stop_timer(struct qemu_alarm_timer *t); |
203 |
static void win32_rearm_timer(struct qemu_alarm_timer *t); |
|
237 |
static void win32_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
|
|
204 | 238 |
|
205 | 239 |
#else |
206 | 240 |
|
207 | 241 |
static int unix_start_timer(struct qemu_alarm_timer *t); |
208 | 242 |
static void unix_stop_timer(struct qemu_alarm_timer *t); |
209 |
static void unix_rearm_timer(struct qemu_alarm_timer *t); |
|
243 |
static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
|
|
210 | 244 |
|
211 | 245 |
#ifdef __linux__ |
212 | 246 |
|
213 | 247 |
static int dynticks_start_timer(struct qemu_alarm_timer *t); |
214 | 248 |
static void dynticks_stop_timer(struct qemu_alarm_timer *t); |
215 |
static void dynticks_rearm_timer(struct qemu_alarm_timer *t); |
|
249 |
static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
|
|
216 | 250 |
|
217 | 251 |
#endif /* __linux__ */ |
218 | 252 |
|
... | ... | |
715 | 749 |
qemu_run_timers(host_clock); |
716 | 750 |
} |
717 | 751 |
|
718 |
static int64_t qemu_next_alarm_deadline(void); |
|
719 |
|
|
720 | 752 |
#ifdef _WIN32 |
721 | 753 |
static void CALLBACK host_alarm_handler(PVOID lpParam, BOOLEAN unused) |
722 | 754 |
#else |
... | ... | |
781 | 813 |
return delta; |
782 | 814 |
} |
783 | 815 |
|
784 |
static int64_t qemu_next_alarm_deadline(void) |
|
785 |
{ |
|
786 |
int64_t delta; |
|
787 |
int64_t rtdelta; |
|
788 |
|
|
789 |
if (!use_icount && vm_clock->active_timers) { |
|
790 |
delta = vm_clock->active_timers->expire_time - |
|
791 |
qemu_get_clock_ns(vm_clock); |
|
792 |
} else { |
|
793 |
delta = INT32_MAX; |
|
794 |
} |
|
795 |
if (host_clock->active_timers) { |
|
796 |
int64_t hdelta = host_clock->active_timers->expire_time - |
|
797 |
qemu_get_clock_ns(host_clock); |
|
798 |
if (hdelta < delta) |
|
799 |
delta = hdelta; |
|
800 |
} |
|
801 |
if (rt_clock->active_timers) { |
|
802 |
rtdelta = (rt_clock->active_timers->expire_time - |
|
803 |
qemu_get_clock_ns(rt_clock)); |
|
804 |
if (rtdelta < delta) |
|
805 |
delta = rtdelta; |
|
806 |
} |
|
807 |
|
|
808 |
return delta; |
|
809 |
} |
|
810 |
|
|
811 | 816 |
#if defined(__linux__) |
812 | 817 |
|
813 | 818 |
#include "compatfd.h" |
... | ... | |
860 | 865 |
timer_delete(host_timer); |
861 | 866 |
} |
862 | 867 |
|
863 |
static void dynticks_rearm_timer(struct qemu_alarm_timer *t) |
|
868 |
static void dynticks_rearm_timer(struct qemu_alarm_timer *t, |
|
869 |
int64_t nearest_delta_ns) |
|
864 | 870 |
{ |
865 | 871 |
timer_t host_timer = t->timer; |
866 | 872 |
struct itimerspec timeout; |
867 |
int64_t nearest_delta_ns = INT64_MAX; |
|
868 | 873 |
int64_t current_ns; |
869 | 874 |
|
870 |
assert(alarm_has_dynticks(t)); |
|
871 |
if (!rt_clock->active_timers && |
|
872 |
!vm_clock->active_timers && |
|
873 |
!host_clock->active_timers) |
|
874 |
return; |
|
875 |
|
|
876 |
nearest_delta_ns = qemu_next_alarm_deadline(); |
|
877 | 875 |
if (nearest_delta_ns < MIN_TIMER_REARM_NS) |
878 | 876 |
nearest_delta_ns = MIN_TIMER_REARM_NS; |
879 | 877 |
|
... | ... | |
915 | 913 |
return 0; |
916 | 914 |
} |
917 | 915 |
|
918 |
static void unix_rearm_timer(struct qemu_alarm_timer *t) |
|
916 |
static void unix_rearm_timer(struct qemu_alarm_timer *t, |
|
917 |
int64_t nearest_delta_ns) |
|
919 | 918 |
{ |
920 | 919 |
struct itimerval itv; |
921 |
int64_t nearest_delta_ns = INT64_MAX; |
|
922 | 920 |
int err; |
923 | 921 |
|
924 |
assert(alarm_has_dynticks(t)); |
|
925 |
if (!rt_clock->active_timers && |
|
926 |
!vm_clock->active_timers && |
|
927 |
!host_clock->active_timers) |
|
928 |
return; |
|
929 |
|
|
930 |
nearest_delta_ns = qemu_next_alarm_deadline(); |
|
931 | 922 |
if (nearest_delta_ns < MIN_TIMER_REARM_NS) |
932 | 923 |
nearest_delta_ns = MIN_TIMER_REARM_NS; |
933 | 924 |
|
... | ... | |
1014 | 1005 |
timeEndPeriod(mm_period); |
1015 | 1006 |
} |
1016 | 1007 |
|
1017 |
static void mm_rearm_timer(struct qemu_alarm_timer *t) |
|
1008 |
static void mm_rearm_timer(struct qemu_alarm_timer *t, int64_t delta)
|
|
1018 | 1009 |
{ |
1019 |
int nearest_delta_ms; |
|
1020 |
|
|
1021 |
assert(alarm_has_dynticks(t)); |
|
1022 |
if (!rt_clock->active_timers && |
|
1023 |
!vm_clock->active_timers && |
|
1024 |
!host_clock->active_timers) { |
|
1025 |
return; |
|
1026 |
} |
|
1027 |
|
|
1028 |
timeKillEvent(mm_timer); |
|
1029 |
|
|
1030 |
nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; |
|
1010 |
int nearest_delta_ms = (delta + 999999) / 1000000; |
|
1031 | 1011 |
if (nearest_delta_ms < 1) { |
1032 | 1012 |
nearest_delta_ms = 1; |
1033 | 1013 |
} |
1014 |
|
|
1015 |
timeKillEvent(mm_timer); |
|
1034 | 1016 |
mm_timer = timeSetEvent(nearest_delta_ms, |
1035 | 1017 |
mm_period, |
1036 | 1018 |
mm_alarm_handler, |
... | ... | |
1082 | 1064 |
} |
1083 | 1065 |
} |
1084 | 1066 |
|
1085 |
static void win32_rearm_timer(struct qemu_alarm_timer *t) |
|
1067 |
static void win32_rearm_timer(struct qemu_alarm_timer *t, |
|
1068 |
int64_t nearest_delta_ns) |
|
1086 | 1069 |
{ |
1087 | 1070 |
HANDLE hTimer = t->timer; |
1088 | 1071 |
int nearest_delta_ms; |
1089 | 1072 |
BOOLEAN success; |
1090 | 1073 |
|
1091 |
assert(alarm_has_dynticks(t)); |
|
1092 |
if (!rt_clock->active_timers && |
|
1093 |
!vm_clock->active_timers && |
|
1094 |
!host_clock->active_timers) |
|
1095 |
return; |
|
1096 |
|
|
1097 |
nearest_delta_ms = (qemu_next_alarm_deadline() + 999999) / 1000000; |
|
1074 |
nearest_delta_ms = (nearest_delta_ns + 999999) / 1000000; |
|
1098 | 1075 |
if (nearest_delta_ms < 1) { |
1099 | 1076 |
nearest_delta_ms = 1; |
1100 | 1077 |
} |
Also available in: Unified diff