TIMER: Fix problem activation time for clock units
This commit is contained in:
parent
08665e4989
commit
f046171269
2 changed files with 35 additions and 70 deletions
|
@ -555,8 +555,7 @@ struct UNIT {
|
|||
/* waiting for this unit */
|
||||
/* Asynchronous Timer control */
|
||||
double a_due_time; /* due time for timer event */
|
||||
double a_skew; /* accumulated skew being corrected */
|
||||
double a_last_fired_time; /* time last event fired */
|
||||
double a_due_gtime; /* due time (in instructions) for timer event */
|
||||
int32 a_usec_delay; /* time delay for timer event */
|
||||
#endif
|
||||
};
|
||||
|
|
70
sim_timer.c
70
sim_timer.c
|
@ -748,7 +748,6 @@ return sim_rtcn_init_unit (NULL, time, tmr);
|
|||
|
||||
int32 sim_rtcn_init_unit (UNIT *uptr, int32 time, int32 tmr)
|
||||
{
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "_sim_rtcn_init_unit(unit=%s, time=%d, tmr=%d)\n", sim_uname(uptr), time, tmr);
|
||||
if (time == 0)
|
||||
time = 1;
|
||||
if (tmr == SIM_INTERNAL_CLK)
|
||||
|
@ -766,6 +765,7 @@ if (rtc_currd[tmr])
|
|||
time = rtc_currd[tmr];
|
||||
if (!uptr)
|
||||
uptr = sim_clock_unit[tmr];
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "_sim_rtcn_init_unit(unit=%s, time=%d, tmr=%d)\n", sim_uname(uptr), time, tmr);
|
||||
if (uptr) {
|
||||
if (!sim_clock_unit[tmr]) {
|
||||
sim_clock_unit[tmr] = uptr;
|
||||
|
@ -1837,14 +1837,10 @@ while (sim_asynch_timer && sim_is_running) {
|
|||
uptr->a_next = NULL; /* hygiene */
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &stop_time);
|
||||
if (1 != sim_timespec_compare (&due_time, &stop_time)) {
|
||||
if (1 != sim_timespec_compare (&due_time, &stop_time))
|
||||
inst_delay = 0;
|
||||
uptr->a_last_fired_time = _timespec_to_double(&stop_time);
|
||||
}
|
||||
else {
|
||||
else
|
||||
inst_delay = (int32)(inst_per_sec*(_timespec_to_double(&due_time)-_timespec_to_double(&stop_time)));
|
||||
uptr->a_last_fired_time = uptr->a_due_time;
|
||||
}
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - slept %.0fms - activating(%s,%d)\n",
|
||||
1000.0*(_timespec_to_double (&stop_time)-_timespec_to_double (&start_time)), sim_uname(uptr), inst_delay);
|
||||
sim_activate (uptr, inst_delay);
|
||||
|
@ -1989,18 +1985,16 @@ if (sim_timer_thread_running) {
|
|||
/* Any wallclock queued events are now migrated to the normal event queue */
|
||||
while (sim_wallclock_queue != QUEUE_LIST_END) {
|
||||
UNIT *uptr = sim_wallclock_queue;
|
||||
double d_due_delta = uptr->a_due_time - sim_timenow_double ();
|
||||
double inst_delay_d = uptr->a_due_gtime - sim_gtime ();
|
||||
int32 inst_delay;
|
||||
double inst_delay_d;
|
||||
|
||||
uptr->cancel (uptr);
|
||||
if (d_due_delta < 0.0)
|
||||
d_due_delta = 0.0;
|
||||
inst_delay_d = sim_timer_inst_per_sec () * d_due_delta;
|
||||
if (inst_delay_d < 0.0)
|
||||
inst_delay_d = 0.0;
|
||||
/* Bound delay to avoid overflow. */
|
||||
/* Long delays are usually canceled before they expire */
|
||||
if (inst_delay_d > (double)0x7fffffff)
|
||||
inst_delay_d = (double)0x7fffffff;
|
||||
if (inst_delay_d > (double)0x7FFFFFFF)
|
||||
inst_delay_d = (double)0x7FFFFFFF;
|
||||
inst_delay = (int32)inst_delay_d;
|
||||
if ((inst_delay == 0) && (inst_delay_d != 0.0))
|
||||
inst_delay = 1; /* Minimum non-zero delay is 1 instruction */
|
||||
|
@ -2074,42 +2068,9 @@ if ((sim_calb_tmr == -1) || /* if No timer initializ
|
|||
if (1) {
|
||||
double d_now = sim_timenow_double ();
|
||||
|
||||
/* Determine if this is a clock tick like invocation
|
||||
or an occasional measured device delay */
|
||||
if ((uptr->a_usec_delay == usec_delay) &&
|
||||
(uptr->a_due_time != 0.0)) {
|
||||
double d_delay = ((double)usec_delay)/1000000.0;
|
||||
|
||||
uptr->a_due_time += d_delay;
|
||||
if (uptr->a_due_time < (d_now + d_delay*0.1)) { /* Accumulate lost time */
|
||||
uptr->a_skew += (d_now + d_delay*0.1) - uptr->a_due_time;
|
||||
uptr->a_due_time = d_now + d_delay/10.0;
|
||||
if (uptr->a_skew > 30.0) { /* Gap too big? */
|
||||
uptr->a_usec_delay = usec_delay;
|
||||
uptr->a_skew = uptr->a_last_fired_time = 0.0;
|
||||
uptr->a_due_time = d_now + (double)(usec_delay)/1000000.0;
|
||||
}
|
||||
if (fabs (uptr->a_skew) > fabs (rtc_clock_skew_max[sim_calb_tmr]))
|
||||
rtc_clock_skew_max[sim_calb_tmr] = uptr->a_skew;
|
||||
}
|
||||
else {
|
||||
if (uptr->a_skew > 0.0) { /* Lost time to make up? */
|
||||
if (uptr->a_skew > d_delay*0.9) {
|
||||
uptr->a_skew -= d_delay*0.9;
|
||||
uptr->a_due_time -= d_delay*0.9;
|
||||
}
|
||||
else {
|
||||
uptr->a_due_time -= uptr->a_skew;
|
||||
uptr->a_skew = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uptr->a_usec_delay = usec_delay;
|
||||
uptr->a_skew = uptr->a_last_fired_time = 0.0;
|
||||
uptr->a_due_time = d_now + (double)(usec_delay)/1000000.0;
|
||||
}
|
||||
uptr->a_due_gtime = sim_gtime () + (sim_timer_inst_per_sec () * (double)(usec_delay)/1000000.0);
|
||||
uptr->time = usec_delay;
|
||||
uptr->cancel = &_sim_wallclock_cancel; /* bind cleanup method */
|
||||
uptr->a_is_active = &_sim_wallclock_is_active;
|
||||
|
@ -2311,7 +2272,7 @@ if (uptr->a_next) {
|
|||
}
|
||||
}
|
||||
if (uptr->a_next == NULL) {
|
||||
uptr->a_due_time = uptr->a_skew = uptr->a_last_fired_time = uptr->a_usec_delay = 0;
|
||||
uptr->a_due_time = uptr->a_due_gtime = uptr->a_usec_delay = 0;
|
||||
uptr->cancel = NULL;
|
||||
uptr->a_is_active = NULL;
|
||||
if (tmr < SIM_NTIMERS) { /* Timer Unit? */
|
||||
|
@ -2326,12 +2287,13 @@ pthread_mutex_unlock (&sim_timer_lock);
|
|||
int32 sim_timer_activate_time (UNIT *uptr)
|
||||
{
|
||||
UNIT *cptr;
|
||||
double inst_per_sec = sim_timer_inst_per_sec ();
|
||||
double d_result;
|
||||
int32 tmr;
|
||||
|
||||
if (uptr->a_is_active == &_sim_wallclock_is_active) {
|
||||
pthread_mutex_lock (&sim_timer_lock);
|
||||
if (uptr == sim_wallclock_entry) {
|
||||
d_result = ((uptr)->a_due_time - sim_timenow_double())*inst_per_sec;
|
||||
d_result = uptr->a_due_gtime - sim_gtime ();
|
||||
if (d_result < 0.0)
|
||||
d_result = 0.0;
|
||||
if (d_result > (double)0x7FFFFFFE)
|
||||
|
@ -2343,7 +2305,7 @@ for (cptr = sim_wallclock_queue;
|
|||
cptr != QUEUE_LIST_END;
|
||||
cptr = cptr->a_next)
|
||||
if (uptr == cptr) {
|
||||
d_result = ((uptr)->a_due_time - sim_timenow_double())*inst_per_sec;
|
||||
d_result = uptr->a_due_gtime - sim_gtime ();
|
||||
if (d_result < 0.0)
|
||||
d_result = 0.0;
|
||||
if (d_result > (double)0x7FFFFFFE)
|
||||
|
@ -2352,8 +2314,12 @@ for (cptr = sim_wallclock_queue;
|
|||
return ((int32)d_result) + 1;
|
||||
}
|
||||
pthread_mutex_unlock (&sim_timer_lock);
|
||||
}
|
||||
if (uptr->a_next)
|
||||
return uptr->a_event_time + 1;
|
||||
for (tmr=0; tmr<SIM_NTIMERS; tmr++)
|
||||
if (sim_clock_unit[tmr] == uptr)
|
||||
return sim_activate_time (&sim_timer_units[tmr]);
|
||||
return -1; /* Not found. */
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue