TIMER: Fix coscheduling functionality to produce consistent results
Added debug CHECK option to the sim_timer_activate_after() to verify that coscheduled events actually have sim_activate_time_usecs() results which are consistent with each other. Additionally, coschedule tick processing now properly counts down pending coschedule queued activities.
This commit is contained in:
parent
af1603f000
commit
e36873f466
4 changed files with 91 additions and 48 deletions
17
scp.c
17
scp.c
|
@ -9204,15 +9204,11 @@ return (((uptr->next) || AIO_IS_ACTIVE(uptr) || ((uptr->dynflags & UNIT_TMR_UNIT
|
||||||
result = absolute activation time + 1, 0 if inactive
|
result = absolute activation time + 1, 0 if inactive
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 sim_activate_time (UNIT *uptr)
|
int32 _sim_activate_time (UNIT *uptr)
|
||||||
{
|
{
|
||||||
UNIT *cptr;
|
UNIT *cptr;
|
||||||
int32 accum;
|
int32 accum;
|
||||||
|
|
||||||
AIO_VALIDATE;
|
|
||||||
accum = sim_timer_activate_time (uptr);
|
|
||||||
if (accum >= 0)
|
|
||||||
return accum;
|
|
||||||
accum = 0;
|
accum = 0;
|
||||||
for (cptr = sim_clock_queue; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
for (cptr = sim_clock_queue; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
||||||
if (cptr == sim_clock_queue) {
|
if (cptr == sim_clock_queue) {
|
||||||
|
@ -9227,6 +9223,17 @@ for (cptr = sim_clock_queue; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 sim_activate_time (UNIT *uptr)
|
||||||
|
{
|
||||||
|
int32 accum;
|
||||||
|
|
||||||
|
AIO_VALIDATE;
|
||||||
|
accum = _sim_timer_activate_time (uptr);
|
||||||
|
if (accum >= 0)
|
||||||
|
return accum;
|
||||||
|
return _sim_activate_time (uptr);
|
||||||
|
}
|
||||||
|
|
||||||
double sim_activate_time_usecs (UNIT *uptr)
|
double sim_activate_time_usecs (UNIT *uptr)
|
||||||
{
|
{
|
||||||
UNIT *cptr;
|
UNIT *cptr;
|
||||||
|
|
1
scp.h
1
scp.h
|
@ -130,6 +130,7 @@ t_stat _sim_activate_after_abs (UNIT *uptr, double usecs_walltime);
|
||||||
t_stat sim_cancel (UNIT *uptr);
|
t_stat sim_cancel (UNIT *uptr);
|
||||||
t_bool sim_is_active (UNIT *uptr);
|
t_bool sim_is_active (UNIT *uptr);
|
||||||
int32 sim_activate_time (UNIT *uptr);
|
int32 sim_activate_time (UNIT *uptr);
|
||||||
|
int32 _sim_activate_time (UNIT *uptr);
|
||||||
double sim_activate_time_usecs (UNIT *uptr);
|
double sim_activate_time_usecs (UNIT *uptr);
|
||||||
t_stat sim_run_boot_prep (int32 flag);
|
t_stat sim_run_boot_prep (int32 flag);
|
||||||
double sim_gtime (void);
|
double sim_gtime (void);
|
||||||
|
|
119
sim_timer.c
119
sim_timer.c
|
@ -774,6 +774,7 @@ t_stat sim_timer_tick_svc (UNIT *uptr);
|
||||||
#define DBG_TIM 0x020 /* timer thread activities */
|
#define DBG_TIM 0x020 /* timer thread activities */
|
||||||
#define DBG_THR 0x040 /* throttle activities */
|
#define DBG_THR 0x040 /* throttle activities */
|
||||||
#define DBG_ACK 0x080 /* interrupt acknowledgement activities */
|
#define DBG_ACK 0x080 /* interrupt acknowledgement activities */
|
||||||
|
#define DBG_CHK 0x100 /* check scheduled activation time*/
|
||||||
DEBTAB sim_timer_debug[] = {
|
DEBTAB sim_timer_debug[] = {
|
||||||
{"TRACE", DBG_TRC, "Trace routine calls"},
|
{"TRACE", DBG_TRC, "Trace routine calls"},
|
||||||
{"IDLE", DBG_IDL, "Idling activities"},
|
{"IDLE", DBG_IDL, "Idling activities"},
|
||||||
|
@ -783,6 +784,7 @@ DEBTAB sim_timer_debug[] = {
|
||||||
{"TIME", DBG_TIM, "Activation and scheduling activities"},
|
{"TIME", DBG_TIM, "Activation and scheduling activities"},
|
||||||
{"THROT", DBG_THR, "Throttling activities"},
|
{"THROT", DBG_THR, "Throttling activities"},
|
||||||
{"MUX", DBG_MUX, "Tmxr scheduling activities"},
|
{"MUX", DBG_MUX, "Tmxr scheduling activities"},
|
||||||
|
{"CHECK", DBG_CHK, "Check scheduled activation time"},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1796,7 +1798,9 @@ if (sim_clock_unit[tmr]->action == NULL)
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
stat = sim_clock_unit[tmr]->action (sim_clock_unit[tmr]);
|
stat = sim_clock_unit[tmr]->action (sim_clock_unit[tmr]);
|
||||||
--sim_cosched_interval[tmr]; /* Countdown ticks */
|
--sim_cosched_interval[tmr]; /* Countdown ticks */
|
||||||
if (stat == SCPE_OK) {
|
if ((stat == SCPE_OK) &&
|
||||||
|
(sim_cosched_interval[tmr] <= 0) &&
|
||||||
|
(sim_clock_cosched_queue[tmr] != QUEUE_LIST_END)) {
|
||||||
if (rtc_clock_catchup_eligible[tmr]) { /* calibration started? */
|
if (rtc_clock_catchup_eligible[tmr]) { /* calibration started? */
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
double skew;
|
double skew;
|
||||||
|
@ -1807,8 +1811,7 @@ if (stat == SCPE_OK) {
|
||||||
if (fabs(skew) > fabs(rtc_clock_skew_max[tmr]))
|
if (fabs(skew) > fabs(rtc_clock_skew_max[tmr]))
|
||||||
rtc_clock_skew_max[tmr] = skew;
|
rtc_clock_skew_max[tmr] = skew;
|
||||||
}
|
}
|
||||||
while ((sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) &&
|
do {
|
||||||
(sim_cosched_interval[tmr] <= 0)) {
|
|
||||||
UNIT *cptr = sim_clock_cosched_queue[tmr];
|
UNIT *cptr = sim_clock_cosched_queue[tmr];
|
||||||
sim_clock_cosched_queue[tmr] = cptr->next;
|
sim_clock_cosched_queue[tmr] = cptr->next;
|
||||||
cptr->next = NULL;
|
cptr->next = NULL;
|
||||||
|
@ -1820,19 +1823,15 @@ if (stat == SCPE_OK) {
|
||||||
sim_cosched_interval[tmr] = 0;
|
sim_cosched_interval[tmr] = 0;
|
||||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_tick_svc(tmr=%d) - coactivating %s", tmr, sim_uname (cptr));
|
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_tick_svc(tmr=%d) - coactivating %s", tmr, sim_uname (cptr));
|
||||||
if (cptr->usecs_remaining) {
|
if (cptr->usecs_remaining) {
|
||||||
double usec_delay = cptr->usecs_remaining;
|
sim_debug (DBG_QUE, &sim_timer_dev, " remnant: %.0f - next %s after cosched interval: %d ticks\n", cptr->usecs_remaining, (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) ? sim_uname (sim_clock_cosched_queue[tmr]) : "", sim_cosched_interval[tmr]);
|
||||||
|
sim_timer_activate_after (cptr, cptr->usecs_remaining);
|
||||||
cptr->usecs_remaining = 0;
|
|
||||||
sim_debug (DBG_QUE, &sim_timer_dev, " remnant: %.0f - next %s after cosched interval: %d ticks\n", usec_delay, (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) ? sim_uname (sim_clock_cosched_queue[tmr]) : "", sim_cosched_interval[tmr]);
|
|
||||||
sim_timer_activate_after (cptr, usec_delay);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sim_debug (DBG_QUE, &sim_timer_dev, " - next %s after cosched interval: %d ticks\n", (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) ? sim_uname (sim_clock_cosched_queue[tmr]) : "", sim_cosched_interval[tmr]);
|
sim_debug (DBG_QUE, &sim_timer_dev, " - next %s after cosched interval: %d ticks\n", (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) ? sim_uname (sim_clock_cosched_queue[tmr]) : "", sim_cosched_interval[tmr]);
|
||||||
_sim_activate (cptr, 0);
|
_sim_activate (cptr, 0);
|
||||||
}
|
}
|
||||||
}
|
} while ((sim_cosched_interval[tmr] <= 0) &&
|
||||||
if (sim_clock_cosched_queue[tmr] == QUEUE_LIST_END)
|
(sim_clock_cosched_queue[tmr] != QUEUE_LIST_END));
|
||||||
sim_cosched_interval[tmr] = 0;
|
|
||||||
}
|
}
|
||||||
return stat;
|
return stat;
|
||||||
}
|
}
|
||||||
|
@ -2210,8 +2209,10 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||||
int32 accum;
|
int32 accum;
|
||||||
|
|
||||||
if (sim_clock_unit[tmr]) {
|
if (sim_clock_unit[tmr]) {
|
||||||
int32 clock_time = sim_timer_activate_time (sim_clock_unit[tmr]);
|
int32 clock_time = _sim_activate_time (&sim_timer_units[tmr]);
|
||||||
|
|
||||||
|
if (clock_time < 0)
|
||||||
|
clock_time = 0;
|
||||||
/* Stop clock assist unit and make sure the clock unit has a tick queued */
|
/* Stop clock assist unit and make sure the clock unit has a tick queued */
|
||||||
sim_cancel (&sim_timer_units[tmr]);
|
sim_cancel (&sim_timer_units[tmr]);
|
||||||
if (rtc_hz[tmr]) {
|
if (rtc_hz[tmr]) {
|
||||||
|
@ -2308,8 +2309,10 @@ return sim_timer_activate_after (uptr, (double)((interval * 1000000.0) / sim_tim
|
||||||
|
|
||||||
t_stat sim_timer_activate_after (UNIT *uptr, double usec_delay)
|
t_stat sim_timer_activate_after (UNIT *uptr, double usec_delay)
|
||||||
{
|
{
|
||||||
|
UNIT *ouptr = uptr;
|
||||||
int inst_delay, tmr;
|
int inst_delay, tmr;
|
||||||
double inst_delay_d, inst_per_usec;
|
double inst_delay_d, inst_per_usec;
|
||||||
|
t_stat stat;
|
||||||
|
|
||||||
AIO_VALIDATE;
|
AIO_VALIDATE;
|
||||||
/* If this is a clock unit, we need to schedule the related timer unit instead */
|
/* If this is a clock unit, we need to schedule the related timer unit instead */
|
||||||
|
@ -2320,6 +2323,12 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++)
|
||||||
}
|
}
|
||||||
if (sim_is_active (uptr)) /* already active? */
|
if (sim_is_active (uptr)) /* already active? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
uptr->usecs_remaining = 0;
|
||||||
|
if (usec_delay <= 0.0) {
|
||||||
|
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - invalid usec value\n",
|
||||||
|
sim_uname(uptr), usec_delay);
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Handle long delays by aligning with the calibrated timer's calibration
|
* Handle long delays by aligning with the calibrated timer's calibration
|
||||||
* activities. Delays which would expire prior to the next calibration
|
* activities. Delays which would expire prior to the next calibration
|
||||||
|
@ -2330,23 +2339,25 @@ if (sim_is_active (uptr)) /* already active? */
|
||||||
* desired time has elapsed.
|
* desired time has elapsed.
|
||||||
*/
|
*/
|
||||||
inst_per_usec = sim_timer_inst_per_sec () / 1000000.0;
|
inst_per_usec = sim_timer_inst_per_sec () / 1000000.0;
|
||||||
inst_delay_d = inst_per_usec * usec_delay;
|
inst_delay_d = floor(inst_per_usec * usec_delay);
|
||||||
inst_delay = (int32)inst_delay_d;
|
inst_delay = (int32)inst_delay_d;
|
||||||
if ((inst_delay == 0) && (usec_delay != 0))
|
if ((inst_delay == 0) && (usec_delay != 0))
|
||||||
inst_delay_d = inst_delay = 1; /* Minimum non-zero delay is 1 instruction */
|
inst_delay_d = inst_delay = 1; /* Minimum non-zero delay is 1 instruction */
|
||||||
if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr])) { /* Calibrated Timer available? */
|
if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr])) { /* Calibrated Timer available? */
|
||||||
int32 inst_til_tick = sim_activate_time (&sim_timer_units[sim_calb_tmr]);
|
int32 inst_til_tick = sim_activate_time (&sim_timer_units[sim_calb_tmr]) - 1;
|
||||||
int32 ticks_til_calib = rtc_hz[sim_calb_tmr] - rtc_ticks[sim_calb_tmr];
|
int32 ticks_til_calib = rtc_hz[sim_calb_tmr] - rtc_ticks[sim_calb_tmr];
|
||||||
int32 inst_til_calib = inst_til_tick +
|
int32 inst_til_calib = inst_til_tick + ((ticks_til_calib - 1) * rtc_currd[sim_calb_tmr]);
|
||||||
((ticks_til_calib - 1) * rtc_currd[sim_calb_tmr]);
|
uint32 usecs_til_calib = (uint32)ceil(inst_til_calib / inst_per_usec);
|
||||||
uint32 usecs_til_calib = (uint32)(inst_til_calib / inst_per_usec);
|
|
||||||
|
|
||||||
if (uptr != &sim_timer_units[sim_calb_tmr]) { /* Not scheduling calibrated timer? */
|
if (uptr != &sim_timer_units[sim_calb_tmr]) { /* Not scheduling calibrated timer? */
|
||||||
if (inst_delay_d >= (double)inst_til_calib) { /* long wait? */
|
if (inst_delay_d >= (double)inst_til_calib) { /* long wait? */
|
||||||
uptr->usecs_remaining = usec_delay - usecs_til_calib;
|
stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib - 1);
|
||||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs\n",
|
uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_calib : 0.0;
|
||||||
sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining);
|
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d\n",
|
||||||
return sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib);
|
sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick);
|
||||||
|
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||||
|
sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr));
|
||||||
|
return stat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2365,7 +2376,6 @@ if ((sim_calb_tmr != -1) && (rtc_hz[sim_calb_tmr])) { /* Calibrated Timer
|
||||||
if (inst_delay_d > (double)0x7fffffff)
|
if (inst_delay_d > (double)0x7fffffff)
|
||||||
inst_delay_d = (double)0x7fffffff; /* Bound delay to avoid overflow. */
|
inst_delay_d = (double)0x7fffffff; /* Bound delay to avoid overflow. */
|
||||||
inst_delay = (int32)inst_delay_d;
|
inst_delay = (int32)inst_delay_d;
|
||||||
uptr->usecs_remaining = 0.0; /* make sure there is no remnant here */
|
|
||||||
#if defined(SIM_ASYNCH_CLOCKS)
|
#if defined(SIM_ASYNCH_CLOCKS)
|
||||||
if ((sim_asynch_timer) &&
|
if ((sim_asynch_timer) &&
|
||||||
(usec_delay > sim_idle_rate_ms*1000.0)) {
|
(usec_delay > sim_idle_rate_ms*1000.0)) {
|
||||||
|
@ -2413,9 +2423,15 @@ if ((sim_asynch_timer) &&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d\n",
|
stat = _sim_activate (uptr, inst_delay); /* queue it now */
|
||||||
sim_uname(uptr), usec_delay, inst_delay);
|
uptr->usecs_remaining = ((stat == SCPE_OK) && (0.0 < (usec_delay - ceil(inst_delay / inst_per_usec) ))) ?
|
||||||
return _sim_activate (uptr, inst_delay); /* queue it now */
|
usec_delay - floor(inst_delay / inst_per_usec) :
|
||||||
|
0.0;
|
||||||
|
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d - remnant: %.0f\n",
|
||||||
|
sim_uname(uptr), usec_delay, inst_delay, uptr->usecs_remaining);
|
||||||
|
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||||
|
sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr));
|
||||||
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clock coscheduling routines */
|
/* Clock coscheduling routines */
|
||||||
|
@ -2433,7 +2449,7 @@ if (NULL == uptr) { /* deregistering? */
|
||||||
/* they will fire and subsequently requeue themselves */
|
/* they will fire and subsequently requeue themselves */
|
||||||
while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) {
|
while (sim_clock_cosched_queue[tmr] != QUEUE_LIST_END) {
|
||||||
UNIT *uptr = sim_clock_cosched_queue[tmr];
|
UNIT *uptr = sim_clock_cosched_queue[tmr];
|
||||||
double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1;
|
double usecs_remaining = sim_timer_activate_time_usecs (uptr);
|
||||||
|
|
||||||
_sim_coschedule_cancel (uptr);
|
_sim_coschedule_cancel (uptr);
|
||||||
_sim_activate (uptr, 1);
|
_sim_activate (uptr, 1);
|
||||||
|
@ -2488,6 +2504,8 @@ sim_cancel (uptr);
|
||||||
return sim_clock_coschedule (uptr, interval);
|
return sim_clock_coschedule (uptr, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ticks - 0 means on the next tick, 1 means the second tick, etc. */
|
||||||
|
|
||||||
t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks)
|
t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks)
|
||||||
{
|
{
|
||||||
if (ticks < 0)
|
if (ticks < 0)
|
||||||
|
@ -2679,7 +2697,7 @@ return FALSE;
|
||||||
}
|
}
|
||||||
#endif /* defined(SIM_ASYNCH_CLOCKS) */
|
#endif /* defined(SIM_ASYNCH_CLOCKS) */
|
||||||
|
|
||||||
int32 sim_timer_activate_time (UNIT *uptr)
|
int32 _sim_timer_activate_time (UNIT *uptr)
|
||||||
{
|
{
|
||||||
UNIT *cptr;
|
UNIT *cptr;
|
||||||
int32 tmr;
|
int32 tmr;
|
||||||
|
@ -2718,20 +2736,25 @@ if (uptr->a_next)
|
||||||
|
|
||||||
if (uptr->cancel == &_sim_coschedule_cancel) {
|
if (uptr->cancel == &_sim_coschedule_cancel) {
|
||||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||||
int32 accum;
|
int32 accum = 0;
|
||||||
|
|
||||||
accum = sim_cosched_interval[tmr];
|
|
||||||
for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
||||||
if (cptr != sim_clock_cosched_queue[tmr])
|
if (cptr == sim_clock_cosched_queue[tmr]) {
|
||||||
|
if (sim_cosched_interval[tmr] > 0)
|
||||||
|
accum += sim_cosched_interval[tmr];
|
||||||
|
}
|
||||||
|
else
|
||||||
accum += cptr->time;
|
accum += cptr->time;
|
||||||
if (cptr == uptr)
|
if (cptr == uptr)
|
||||||
return (rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]);
|
return (rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++)
|
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||||
if (sim_clock_unit[tmr] == uptr)
|
if ((uptr == &sim_timer_units[tmr]) && (uptr->next)){
|
||||||
return sim_activate_time (&sim_timer_units[tmr]);
|
return _sim_activate_time (&sim_timer_units[tmr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
return -1; /* Not found. */
|
return -1; /* Not found. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2749,6 +2772,10 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sim_is_active (uptr)) {
|
||||||
|
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) - not active\n", sim_uname (uptr), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#if defined(SIM_ASYNCH_CLOCKS)
|
#if defined(SIM_ASYNCH_CLOCKS)
|
||||||
if (uptr->a_is_active == &_sim_wallclock_is_active) {
|
if (uptr->a_is_active == &_sim_wallclock_is_active) {
|
||||||
pthread_mutex_lock (&sim_timer_lock);
|
pthread_mutex_lock (&sim_timer_lock);
|
||||||
|
@ -2784,29 +2811,37 @@ if (uptr->a_next) {
|
||||||
|
|
||||||
if (uptr->cancel == &_sim_coschedule_cancel) {
|
if (uptr->cancel == &_sim_coschedule_cancel) {
|
||||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||||
int32 accum;
|
int32 accum = 0;
|
||||||
|
|
||||||
accum = sim_cosched_interval[tmr];
|
|
||||||
for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
for (cptr = sim_clock_cosched_queue[tmr]; cptr != QUEUE_LIST_END; cptr = cptr->next) {
|
||||||
if (cptr != sim_clock_cosched_queue[tmr])
|
if (cptr == sim_clock_cosched_queue[tmr]) {
|
||||||
|
if (sim_cosched_interval[tmr] > 0)
|
||||||
|
accum += sim_cosched_interval[tmr];
|
||||||
|
}
|
||||||
|
else
|
||||||
accum += cptr->time;
|
accum += cptr->time;
|
||||||
if (cptr == uptr) {
|
if (cptr == uptr) {
|
||||||
if (accum > 0)
|
result = uptr->usecs_remaining + ceil(1000000.0 * ((rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr]) - 1) / sim_timer_inst_per_sec ());
|
||||||
--accum;
|
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, ticksize=%d, ticks=%d, inst_til_tick=%d\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), tmr, rtc_currd[tmr], accum, sim_activate_time (&sim_timer_units[tmr]) - 1);
|
||||||
result = uptr->usecs_remaining + (1000000.0 * ((rtc_currd[tmr] * accum) + sim_activate_time (&sim_timer_units[tmr])) / sim_timer_inst_per_sec ());
|
|
||||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) coscheduled - %.0f usecs, inst_per_sec=%.0f, tmr=%d, hz=%d\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), sim_calb_tmr, rtc_hz[sim_calb_tmr]);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||||
if (sim_clock_unit[tmr] == uptr) {
|
if ((uptr == sim_clock_unit[tmr]) && (uptr->next)) {
|
||||||
result = sim_clock_unit[tmr]->usecs_remaining + (1000000.0 * sim_activate_time (&sim_timer_units[tmr])) / sim_timer_inst_per_sec ();
|
result = sim_clock_unit[tmr]->usecs_remaining + (1000000.0 * (sim_activate_time (&sim_timer_units[tmr]) - 1)) / sim_timer_inst_per_sec ();
|
||||||
|
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if ((uptr == &sim_timer_units[tmr]) && (uptr->next)){
|
||||||
|
result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec ();
|
||||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
|
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec ();
|
||||||
|
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec ());
|
||||||
return result; /* Not found. */
|
return result; /* Not found. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ void sim_stop_timer_services (void);
|
||||||
t_stat sim_timer_change_asynch (void);
|
t_stat sim_timer_change_asynch (void);
|
||||||
t_stat sim_timer_activate (UNIT *uptr, int32 interval);
|
t_stat sim_timer_activate (UNIT *uptr, int32 interval);
|
||||||
t_stat sim_timer_activate_after (UNIT *uptr, double usec_delay);
|
t_stat sim_timer_activate_after (UNIT *uptr, double usec_delay);
|
||||||
int32 sim_timer_activate_time (UNIT *uptr);
|
int32 _sim_timer_activate_time (UNIT *uptr);
|
||||||
double sim_timer_activate_time_usecs (UNIT *uptr);
|
double sim_timer_activate_time_usecs (UNIT *uptr);
|
||||||
t_bool sim_timer_is_active (UNIT *uptr);
|
t_bool sim_timer_is_active (UNIT *uptr);
|
||||||
t_bool sim_timer_cancel (UNIT *uptr);
|
t_bool sim_timer_cancel (UNIT *uptr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue