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 */
|
/* waiting for this unit */
|
||||||
/* Asynchronous Timer control */
|
/* Asynchronous Timer control */
|
||||||
double a_due_time; /* due time for timer event */
|
double a_due_time; /* due time for timer event */
|
||||||
double a_skew; /* accumulated skew being corrected */
|
double a_due_gtime; /* due time (in instructions) for timer event */
|
||||||
double a_last_fired_time; /* time last event fired */
|
|
||||||
int32 a_usec_delay; /* time delay for timer event */
|
int32 a_usec_delay; /* time delay for timer event */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
102
sim_timer.c
102
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)
|
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)
|
if (time == 0)
|
||||||
time = 1;
|
time = 1;
|
||||||
if (tmr == SIM_INTERNAL_CLK)
|
if (tmr == SIM_INTERNAL_CLK)
|
||||||
|
@ -766,6 +765,7 @@ if (rtc_currd[tmr])
|
||||||
time = rtc_currd[tmr];
|
time = rtc_currd[tmr];
|
||||||
if (!uptr)
|
if (!uptr)
|
||||||
uptr = sim_clock_unit[tmr];
|
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 (uptr) {
|
||||||
if (!sim_clock_unit[tmr]) {
|
if (!sim_clock_unit[tmr]) {
|
||||||
sim_clock_unit[tmr] = uptr;
|
sim_clock_unit[tmr] = uptr;
|
||||||
|
@ -1837,14 +1837,10 @@ while (sim_asynch_timer && sim_is_running) {
|
||||||
uptr->a_next = NULL; /* hygiene */
|
uptr->a_next = NULL; /* hygiene */
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &stop_time);
|
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;
|
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)));
|
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",
|
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);
|
1000.0*(_timespec_to_double (&stop_time)-_timespec_to_double (&start_time)), sim_uname(uptr), inst_delay);
|
||||||
sim_activate (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 */
|
/* Any wallclock queued events are now migrated to the normal event queue */
|
||||||
while (sim_wallclock_queue != QUEUE_LIST_END) {
|
while (sim_wallclock_queue != QUEUE_LIST_END) {
|
||||||
UNIT *uptr = sim_wallclock_queue;
|
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;
|
int32 inst_delay;
|
||||||
double inst_delay_d;
|
|
||||||
|
|
||||||
uptr->cancel (uptr);
|
uptr->cancel (uptr);
|
||||||
if (d_due_delta < 0.0)
|
if (inst_delay_d < 0.0)
|
||||||
d_due_delta = 0.0;
|
inst_delay_d = 0.0;
|
||||||
inst_delay_d = sim_timer_inst_per_sec () * d_due_delta;
|
|
||||||
/* Bound delay to avoid overflow. */
|
/* Bound delay to avoid overflow. */
|
||||||
/* Long delays are usually canceled before they expire */
|
/* Long delays are usually canceled before they expire */
|
||||||
if (inst_delay_d > (double)0x7fffffff)
|
if (inst_delay_d > (double)0x7FFFFFFF)
|
||||||
inst_delay_d = (double)0x7fffffff;
|
inst_delay_d = (double)0x7FFFFFFF;
|
||||||
inst_delay = (int32)inst_delay_d;
|
inst_delay = (int32)inst_delay_d;
|
||||||
if ((inst_delay == 0) && (inst_delay_d != 0.0))
|
if ((inst_delay == 0) && (inst_delay_d != 0.0))
|
||||||
inst_delay = 1; /* Minimum non-zero delay is 1 instruction */
|
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) {
|
if (1) {
|
||||||
double d_now = sim_timenow_double ();
|
double d_now = sim_timenow_double ();
|
||||||
|
|
||||||
/* Determine if this is a clock tick like invocation
|
uptr->a_usec_delay = usec_delay;
|
||||||
or an occasional measured device delay */
|
uptr->a_due_time = d_now + (double)(usec_delay)/1000000.0;
|
||||||
if ((uptr->a_usec_delay == usec_delay) &&
|
uptr->a_due_gtime = sim_gtime () + (sim_timer_inst_per_sec () * (double)(usec_delay)/1000000.0);
|
||||||
(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->time = usec_delay;
|
uptr->time = usec_delay;
|
||||||
uptr->cancel = &_sim_wallclock_cancel; /* bind cleanup method */
|
uptr->cancel = &_sim_wallclock_cancel; /* bind cleanup method */
|
||||||
uptr->a_is_active = &_sim_wallclock_is_active;
|
uptr->a_is_active = &_sim_wallclock_is_active;
|
||||||
|
@ -2311,7 +2272,7 @@ if (uptr->a_next) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uptr->a_next == NULL) {
|
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->cancel = NULL;
|
||||||
uptr->a_is_active = NULL;
|
uptr->a_is_active = NULL;
|
||||||
if (tmr < SIM_NTIMERS) { /* Timer Unit? */
|
if (tmr < SIM_NTIMERS) { /* Timer Unit? */
|
||||||
|
@ -2326,24 +2287,13 @@ pthread_mutex_unlock (&sim_timer_lock);
|
||||||
int32 sim_timer_activate_time (UNIT *uptr)
|
int32 sim_timer_activate_time (UNIT *uptr)
|
||||||
{
|
{
|
||||||
UNIT *cptr;
|
UNIT *cptr;
|
||||||
double inst_per_sec = sim_timer_inst_per_sec ();
|
|
||||||
double d_result;
|
double d_result;
|
||||||
|
int32 tmr;
|
||||||
|
|
||||||
pthread_mutex_lock (&sim_timer_lock);
|
if (uptr->a_is_active == &_sim_wallclock_is_active) {
|
||||||
if (uptr == sim_wallclock_entry) {
|
pthread_mutex_lock (&sim_timer_lock);
|
||||||
d_result = ((uptr)->a_due_time - sim_timenow_double())*inst_per_sec;
|
if (uptr == sim_wallclock_entry) {
|
||||||
if (d_result < 0.0)
|
d_result = uptr->a_due_gtime - sim_gtime ();
|
||||||
d_result = 0.0;
|
|
||||||
if (d_result > (double)0x7FFFFFFE)
|
|
||||||
d_result = (double)0x7FFFFFFE;
|
|
||||||
pthread_mutex_unlock (&sim_timer_lock);
|
|
||||||
return ((int32)d_result) + 1;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
if (d_result < 0.0)
|
if (d_result < 0.0)
|
||||||
d_result = 0.0;
|
d_result = 0.0;
|
||||||
if (d_result > (double)0x7FFFFFFE)
|
if (d_result > (double)0x7FFFFFFE)
|
||||||
|
@ -2351,9 +2301,25 @@ for (cptr = sim_wallclock_queue;
|
||||||
pthread_mutex_unlock (&sim_timer_lock);
|
pthread_mutex_unlock (&sim_timer_lock);
|
||||||
return ((int32)d_result) + 1;
|
return ((int32)d_result) + 1;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock (&sim_timer_lock);
|
for (cptr = sim_wallclock_queue;
|
||||||
|
cptr != QUEUE_LIST_END;
|
||||||
|
cptr = cptr->a_next)
|
||||||
|
if (uptr == cptr) {
|
||||||
|
d_result = uptr->a_due_gtime - sim_gtime ();
|
||||||
|
if (d_result < 0.0)
|
||||||
|
d_result = 0.0;
|
||||||
|
if (d_result > (double)0x7FFFFFFE)
|
||||||
|
d_result = (double)0x7FFFFFFE;
|
||||||
|
pthread_mutex_unlock (&sim_timer_lock);
|
||||||
|
return ((int32)d_result) + 1;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock (&sim_timer_lock);
|
||||||
|
}
|
||||||
if (uptr->a_next)
|
if (uptr->a_next)
|
||||||
return uptr->a_event_time + 1;
|
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. */
|
return -1; /* Not found. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue