diff --git a/sim_timer.c b/sim_timer.c index f857d63d..f0a40053 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -153,6 +153,7 @@ volatile t_bool sim_idle_wait = FALSE; /* global flag */ static int32 sim_calb_tmr = -1; /* the system calibrated timer */ static int32 sim_calb_tmr_last = -1; /* shadow value when at sim> prompt */ static double sim_inst_per_sec_last = 0; /* shadow value when at sim> prompt */ +static double sim_stop_time = 0; /* time when sim_stop_timer_services was called */ static uint32 sim_idle_rate_ms = 0; static uint32 sim_os_sleep_min_ms = 0; @@ -187,6 +188,7 @@ static t_bool sim_catchup_ticks = TRUE; #endif t_bool sim_asynch_timer = FALSE; + #if defined (SIM_ASYNCH_CLOCKS) UNIT * volatile sim_wallclock_queue = QUEUE_LIST_END; UNIT * volatile sim_wallclock_entry = NULL; @@ -419,10 +421,7 @@ const t_bool rtc_avail = TRUE; uint32 sim_os_msec (void) { -__int64 nowTime; - -GetSystemTimeAsFileTime ((FILETIME *)&nowTime); -return (uint32)(((nowTime + 5000) / 10000) & 0xFFFFFFFF); +return timeGetTime (); /* use Multi-Media time source */ } void sim_os_sleep (unsigned int sec) @@ -796,6 +795,7 @@ t_stat sim_timer_stop_svc (UNIT *uptr); #define DBG_ACK 0x080 /* interrupt acknowledgement activities */ #define DBG_CHK 0x100 /* check scheduled activation time*/ #define DBG_INT 0x200 /* internal timer activities */ +#define DBG_GET 0x400 /* get_time activities */ DEBTAB sim_timer_debug[] = { {"TRACE", DBG_TRC, "Trace routine calls"}, {"IDLE", DBG_IDL, "Idling activities"}, @@ -803,6 +803,7 @@ DEBTAB sim_timer_debug[] = { {"IACK", DBG_ACK, "interrupt acknowledgement activities"}, {"CALIB", DBG_CAL, "Calibration activities"}, {"TIME", DBG_TIM, "Activation and scheduling activities"}, + {"GETTIME", DBG_GET, "get_time activities"}, {"INTER", DBG_INT, "Internal timer activities"}, {"THROT", DBG_THR, "Throttling activities"}, {"MUX", DBG_MUX, "Tmxr scheduling activities"}, @@ -899,13 +900,19 @@ else { if (rtc_hz[tmr] != ticksper) { /* changing tick rate? */ if (rtc_hz[tmr] == 0) rtc_clock_tick_start_time[tmr] = sim_timenow_double (); + if ((rtc_last_hz[tmr] != 0) && + (rtc_last_hz[tmr] != ticksper) && + (ticksper != 0)) + rtc_currd[tmr] = (int32)(sim_timer_inst_per_sec () / ticksper); rtc_last_hz[tmr] = rtc_hz[tmr]; rtc_hz[tmr] = ticksper; _rtcn_configure_calibrated_clock (tmr); if (ticksper != 0) { rtc_clock_tick_size[tmr] = 1.0 / ticksper; - rtc_currd[tmr] = (int32)(sim_timer_inst_per_sec () / ticksper); + sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) currd=%d\n", ticksper, tmr, rtc_currd[tmr]); } + else + sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) timer stopped currd was %d\n", ticksper, tmr, rtc_currd[tmr]); } if (ticksper == 0) /* running? */ return 10000; @@ -2038,7 +2045,7 @@ return SCPE_STOP; void sim_rtcn_get_time (struct timespec *now, int tmr) { -sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_get_time(tmr=%d)\n", tmr); +sim_debug (DBG_GET, &sim_timer_dev, "sim_rtcn_get_time(tmr=%d)\n", tmr); clock_gettime (CLOCK_REALTIME, now); } @@ -2097,7 +2104,8 @@ if ((rtc_hz[tmr] > sim_os_tick_hz) && /* faster than host tick */ sim_debug (DBG_QUE, &sim_timer_dev, "_rtcn_tick_catchup_check() - Enabling catchup ticks for %s\n", sim_uname (sim_clock_unit[tmr])); return TRUE; } -if (rtc_clock_catchup_eligible[tmr]) +if ((rtc_hz[tmr] > 0) && + rtc_clock_catchup_eligible[tmr]) { double tnow = sim_timenow_double(); @@ -2278,13 +2286,14 @@ return SCPE_OK; faster than the host system's clock. This is optimal so that accurate time measurements are taken. If the simulated system doesn't have a clock with an appropriate tick rate, an internal clock is run that meets - this requirement, + this requirement, OR when asynch clocks are enabled, the internal clock + is always run. */ static void _rtcn_configure_calibrated_clock (int32 newtmr) { int32 tmr; -/* Look for a timer running slower than the host system clock */ +/* Look for a timer running slower or the same as the host system clock */ sim_int_clk_tps = MIN(CLK_TPS, sim_os_tick_hz); for (tmr=0; tmr sim_gtime()) sim_activate_abs (&sim_stop_unit, (int32)(sim_timer_stop_time - sim_gtime())); #if defined(SIM_ASYNCH_CLOCKS) @@ -2431,23 +2457,27 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { accum = sim_cosched_interval[tmr]; while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) { UNIT *cptr = sim_clock_cosched_queue[tmr]; + double usecs_remaining = cptr->usecs_remaining; sim_clock_cosched_queue[tmr] = cptr->next; cptr->next = NULL; cptr->cancel = NULL; accum += cptr->time; + cptr->usecs_remaining = 0.0; _sim_activate (cptr, clock_time); - cptr->usecs_remaining = cptr->usecs_remaining + floor(1000000.0 * (accum - ((accum > 0) ? 1 : 0)) * rtc_clock_tick_size[tmr]); + cptr->usecs_remaining = usecs_remaining + floor(1000000.0 * (accum - ((accum > 0) ? 1 : 0)) * rtc_clock_tick_size[tmr]); sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d and %.0f usecs\n", tmr, sim_uname (cptr), clock_time, cptr->usecs_remaining); } sim_cosched_interval[tmr] = 0; } } + sim_cancel (&SIM_INTERNAL_UNIT); /* Make sure Internal Timer is stopped */ sim_cancel (&sim_timer_units[SIM_NTIMERS]); sim_calb_tmr_last = sim_calb_tmr; /* Save calibrated timer value for display */ sim_inst_per_sec_last = sim_timer_inst_per_sec (); /* Save execution rate for display */ sim_calb_tmr = -1; +sim_stop_time = sim_timenow_double (); /* record when execution stopped */ #if defined(SIM_ASYNCH_CLOCKS) pthread_mutex_lock (&sim_timer_lock); if (sim_timer_thread_running) { @@ -2867,12 +2897,13 @@ if (uptr->a_next) { if (uptr == sim_wallclock_entry) { /* Pending on the queue? */ sim_wallclock_entry = NULL; uptr->a_next = NULL; + sim_debug (DBG_QUE, &sim_timer_dev, "Canceled Queue Pending Timer Event for %s\n", sim_uname(uptr)); } else { if (uptr == sim_wallclock_queue) { sim_wallclock_queue = uptr->a_next; uptr->a_next = NULL; - sim_debug (DBG_QUE, &sim_timer_dev, "Canceling Timer Event for %s\n", sim_uname(uptr)); + sim_debug (DBG_QUE, &sim_timer_dev, "Canceled Top Timer Event for %s\n", sim_uname(uptr)); pthread_cond_signal (&sim_timer_wake); } else { @@ -2888,7 +2919,7 @@ if (uptr->a_next) { } } } - if (uptr->a_next == NULL) { + if (uptr->a_next == NULL) { /* Was canceled? */ uptr->a_due_time = uptr->a_due_gtime = uptr->a_usec_delay = 0; uptr->cancel = NULL; uptr->a_is_active = NULL;