From ddb10425e72281355d30b519353a52ceec11210b Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 8 May 2013 09:34:53 -0700 Subject: [PATCH] Reworked all asynch queues to always link using the unit a_next field instead of the next field. --- scp.c | 4 +-- sim_defs.h | 92 +++++++++++++++++++++++++---------------------------- sim_timer.c | 29 +++++++++-------- 3 files changed, 61 insertions(+), 64 deletions(-) diff --git a/scp.c b/scp.c index 7d8fc19c..cde6982c 100644 --- a/scp.c +++ b/scp.c @@ -2923,7 +2923,7 @@ if (sim_wallclock_queue == QUEUE_LIST_END) else { fprintf (st, "%s wall clock event queue status, time = %.0f\n", sim_name, sim_time); - for (uptr = sim_wallclock_queue; uptr != QUEUE_LIST_END; uptr = uptr->next) { + for (uptr = sim_wallclock_queue; uptr != QUEUE_LIST_END; uptr = uptr->a_next) { if ((dptr = find_dev_from_unit (uptr)) != NULL) { fprintf (st, " %s", sim_dname (dptr)); if (dptr->numunits > 1) @@ -2938,7 +2938,7 @@ else { if (sim_clock_cosched_queue != QUEUE_LIST_END) { fprintf (st, "%s clock (%s) co-schedule event queue status, time = %.0f\n", sim_name, sim_uname(sim_clock_unit), sim_time); - for (uptr = sim_clock_cosched_queue; uptr != QUEUE_LIST_END; uptr = uptr->next) { + for (uptr = sim_clock_cosched_queue; uptr != QUEUE_LIST_END; uptr = uptr->a_next) { if ((dptr = find_dev_from_unit (uptr)) != NULL) { fprintf (st, " %s", sim_dname (dptr)); if (dptr->numunits > 1) diff --git a/sim_defs.h b/sim_defs.h index 6e66bbb2..de97ad74 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -785,13 +785,13 @@ extern int32 sim_asynch_inst_latency; if ((uptr)->a_cancel) \ (uptr)->a_cancel (uptr); \ else { \ - if ((uptr)->next) { \ + AIO_UPDATE_QUEUE; \ + if ((uptr)->a_next) { \ UNIT *cptr; \ - AIO_UPDATE_QUEUE; \ pthread_mutex_lock (&sim_timer_lock); \ if ((uptr) == sim_wallclock_queue) { \ - sim_wallclock_queue = (uptr)->next; \ - (uptr)->next = NULL; \ + sim_wallclock_queue = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Timer Event for %s\n", sim_uname(uptr));\ sim_timer_event_canceled = TRUE; \ pthread_cond_signal (&sim_timer_wake); \ @@ -799,30 +799,30 @@ extern int32 sim_asynch_inst_latency; else \ for (cptr = sim_wallclock_queue; \ (cptr != QUEUE_LIST_END); \ - cptr = cptr->next) \ - if (cptr->next == (uptr)) { \ - cptr->next = (uptr)->next; \ - (uptr)->next = NULL; \ + cptr = cptr->a_next) \ + if (cptr->a_next == (uptr)) { \ + cptr->a_next = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Timer Event for %s\n", sim_uname(uptr));\ break; \ } \ - if ((uptr)->next == NULL) \ + if ((uptr)->a_next == NULL) \ (uptr)->a_due_time = (uptr)->a_usec_delay = 0; \ else { \ if ((uptr) == sim_clock_cosched_queue) { \ - sim_clock_cosched_queue = (uptr)->next; \ - (uptr)->next = NULL; \ + sim_clock_cosched_queue = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ } \ else \ for (cptr = sim_clock_cosched_queue; \ (cptr != QUEUE_LIST_END); \ - cptr = cptr->next) \ - if (cptr->next == (uptr)) { \ - cptr->next = (uptr)->next; \ - (uptr)->next = NULL; \ + cptr = cptr->a_next) \ + if (cptr->a_next == (uptr)) { \ + cptr->a_next = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ break; \ } \ - if ((uptr)->next == NULL) { \ + if ((uptr)->a_next == NULL) { \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Clock Coscheduling Event for %s\n", sim_uname(uptr));\ } \ } \ @@ -854,19 +854,19 @@ extern int32 sim_asynch_inst_latency; if ((uptr)->a_cancel) \ (uptr)->a_cancel (uptr); \ else { \ + AIO_UPDATE_QUEUE; \ if (((uptr)->dynflags & UNIT_TM_POLL) && \ !((uptr)->next) && !((uptr)->a_next)) { \ (uptr)->a_polling_now = FALSE; \ sim_tmxr_poll_count -= (uptr)->a_poll_waiter_count; \ (uptr)->a_poll_waiter_count = 0; \ } \ - if ((uptr)->next) { \ + if ((uptr)->a_next) { \ UNIT *cptr; \ - AIO_UPDATE_QUEUE; \ pthread_mutex_lock (&sim_timer_lock); \ if ((uptr) == sim_wallclock_queue) { \ - sim_wallclock_queue = (uptr)->next; \ - (uptr)->next = NULL; \ + sim_wallclock_queue = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Timer Event for %s\n", sim_uname(uptr));\ sim_timer_event_canceled = TRUE; \ pthread_cond_signal (&sim_timer_wake); \ @@ -874,30 +874,30 @@ extern int32 sim_asynch_inst_latency; else \ for (cptr = sim_wallclock_queue; \ (cptr != QUEUE_LIST_END); \ - cptr = cptr->next) \ - if (cptr->next == (uptr)) { \ - cptr->next = (uptr)->next; \ - (uptr)->next = NULL; \ + cptr = cptr->a_next) \ + if (cptr->a_next == (uptr)) { \ + cptr->a_next = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Timer Event for %s\n", sim_uname(uptr));\ break; \ } \ - if ((uptr)->next == NULL) \ + if ((uptr)->a_next == NULL) \ (uptr)->a_due_time = (uptr)->a_usec_delay = 0; \ else { \ if ((uptr) == sim_clock_cosched_queue) { \ - sim_clock_cosched_queue = (uptr)->next; \ - (uptr)->next = NULL; \ + sim_clock_cosched_queue = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ } \ else \ for (cptr = sim_clock_cosched_queue; \ (cptr != QUEUE_LIST_END); \ - cptr = cptr->next) \ - if (cptr->next == (uptr)) { \ - cptr->next = (uptr)->next; \ - (uptr)->next = NULL; \ + cptr = cptr->a_next) \ + if (cptr->a_next == (uptr)) { \ + cptr->a_next = (uptr)->a_next; \ + (uptr)->a_next = NULL; \ break; \ } \ - if ((uptr)->next == NULL) { \ + if ((uptr)->a_next == NULL) { \ sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Canceling Clock Coscheduling Event for %s\n", sim_uname(uptr));\ } \ } \ @@ -917,7 +917,7 @@ extern int32 sim_asynch_inst_latency; pthread_mutex_lock (&sim_timer_lock); \ for (cptr = sim_wallclock_queue; \ cptr != QUEUE_LIST_END; \ - cptr = cptr->next) \ + cptr = cptr->a_next) \ if ((uptr) == cptr) { \ double inst_per_sec = sim_timer_inst_per_sec (); \ int32 result; \ @@ -1028,8 +1028,10 @@ extern int32 sim_asynch_inst_latency; else \ a_event_time = uptr->a_event_time; \ uptr->a_activate_call (uptr, a_event_time); \ - if (uptr->a_check_completion) \ + if (uptr->a_check_completion) { \ + sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Calling Completion Check for asynch event on %s\n", sim_uname(uptr));\ uptr->a_check_completion (uptr); \ + } \ } \ } else (void)0 #define AIO_ACTIVATE(caller, uptr, event_time) \ @@ -1063,20 +1065,16 @@ extern int32 sim_asynch_inst_latency; return SCPE_OK; \ } else (void)0 #define AIO_ACTIVATE_LIST(caller, list, event_time) \ - if (1) { \ + if (list) { \ UNIT *ouptr, *q, *qe; \ sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Queueing Asynch events for %s after %d instructions\n", sim_uname(list), event_time);\ - for (qe=(list); qe->next != QUEUE_LIST_END;) { \ + for (qe=(list); qe->a_next != QUEUE_LIST_END;) { \ qe->a_event_time = event_time; \ qe->a_activate_call = caller; \ - qe->a_next = qe->next; \ - qe->next = NULL; \ qe = qe->a_next; \ } \ qe->a_event_time = event_time; \ qe->a_activate_call = caller; \ - qe->a_next = QUEUE_LIST_END; \ - qe->next = NULL; \ ouptr = (list); \ do { \ do \ @@ -1137,7 +1135,7 @@ extern int32 sim_asynch_inst_latency; while (sim_asynch_queue != QUEUE_LIST_END) { /* List !Empty */ \ int32 a_event_time; \ uptr = sim_asynch_queue; \ - sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "found asynch event for %s after %d instructions\n", sim_uname(uptr), uptr->a_event_time);\ + sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Migrating Asynch event for %s after %d instructions\n", sim_uname(uptr), uptr->a_event_time);\ sim_asynch_queue = uptr->a_next; \ uptr->a_next = NULL; /* hygiene */ \ if (uptr->a_activate_call != &sim_activate_notbefore) { \ @@ -1148,10 +1146,11 @@ extern int32 sim_asynch_inst_latency; else \ a_event_time = uptr->a_event_time; \ AIO_UNLOCK; \ - sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "calling completion check for asynch event on %s\n", sim_uname(uptr));\ uptr->a_activate_call (uptr, a_event_time); \ - if (uptr->a_check_completion) \ + if (uptr->a_check_completion) { \ + sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Calling Completion Check for asynch event on %s\n", sim_uname(uptr));\ uptr->a_check_completion (uptr); \ + } \ AIO_LOCK; \ } \ AIO_UNLOCK; \ @@ -1177,19 +1176,16 @@ extern int32 sim_asynch_inst_latency; return SCPE_OK; \ } else (void)0 #define AIO_ACTIVATE_LIST(caller, list, event_time) \ - if (1) { \ + if (list) { \ UNIT *qe; \ sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Queueing Asynch events for %s after %d instructions\n", sim_uname(list), event_time);\ - for (qe=list; qe->next != QUEUE_LIST_END;) { \ + for (qe=list; qe->a_next != QUEUE_LIST_END;) { \ qe->a_event_time = event_time; \ qe->a_activate_call = caller; \ - qe->a_next = qe->next; \ - qe->next = NULL; \ qe = qe->a_next; \ } \ qe->a_event_time = event_time; \ qe->a_activate_call = caller; \ - qe->next = NULL; \ AIO_LOCK; \ qe->a_next = sim_asynch_queue; \ sim_asynch_queue = list; \ diff --git a/sim_timer.c b/sim_timer.c index 0cdef0c5..87d9799d 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -1185,18 +1185,18 @@ while (sim_asynch_enabled && sim_asynch_timer && sim_is_running) { sim_wallclock_entry = NULL; prvptr = NULL; - for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->next) { + for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->a_next) { if (uptr->a_due_time < cptr->a_due_time) break; prvptr = cptr; } if (prvptr == NULL) { /* insert at head */ - cptr = uptr->next = sim_wallclock_queue; + cptr = uptr->a_next = sim_wallclock_queue; sim_wallclock_queue = uptr; } else { - cptr = uptr->next = prvptr->next; /* insert at prvptr */ - prvptr->next = uptr; + cptr = uptr->a_next = prvptr->a_next; /* insert at prvptr */ + prvptr->a_next = uptr; } } @@ -1224,8 +1224,8 @@ while (sim_asynch_enabled && sim_asynch_timer && sim_is_running) { inst_per_sec = sim_timer_inst_per_sec (); uptr = sim_wallclock_queue; - sim_wallclock_queue = uptr->next; - uptr->next = NULL; /* hygiene */ + sim_wallclock_queue = uptr->a_next; + uptr->a_next = NULL; /* hygiene */ clock_gettime(CLOCK_REALTIME, &stop_time); if (1 != sim_timespec_compare (&due_time, &stop_time)) { @@ -1240,11 +1240,12 @@ while (sim_asynch_enabled && sim_asynch_timer && sim_is_running) { 1000.0*(_timespec_to_double (&stop_time)-_timespec_to_double (&start_time)), sim_uname(uptr), inst_delay); if (sim_clock_unit == uptr) { /* - * Some devices may depend on executing during the same instruction as the - * clock tick event. We link the clock coschedule queue to the clock tick - * and then insert that list in the asynch event queue in a single operation + * Some devices may depend on executing during the same instruction or immediately + * after the clock tick event. To satisfy this, we link the clock unit to the head + * of the clock coschedule queue and then insert that list in the asynch event + * queue in a single operation */ - uptr->next = sim_clock_cosched_queue; + uptr->a_next = sim_clock_cosched_queue; sim_clock_cosched_queue = QUEUE_LIST_END; AIO_ACTIVATE_LIST(sim_activate, uptr, inst_delay); } @@ -1277,7 +1278,7 @@ if (sim_asynch_enabled && sim_asynch_timer) { /* when restarting after being manually stopped the due times for all */ /* timer events needs to slide so they fire in the future. (clock ticks */ /* don't accumulate when the simulator is stopped) */ - for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->next) { + for (cptr = sim_wallclock_queue; cptr != QUEUE_LIST_END; cptr = cptr->a_next) { if (cptr == sim_wallclock_queue) { /* Handle first entry */ struct timespec now; double due_time; @@ -1332,9 +1333,9 @@ else { uptr = sim_wallclock_queue; if (uptr == QUEUE_LIST_END) break; - sim_wallclock_queue = uptr->next; + sim_wallclock_queue = uptr->a_next; accum += uptr->time; - uptr->next = NULL; + uptr->a_next = NULL; uptr->a_due_time = 0; uptr->a_usec_delay = 0; sim_activate_after (uptr, accum); @@ -1464,7 +1465,7 @@ else (rtc_elapsed[sim_calb_tmr ] >= sim_idle_stable)) { sim_debug (DBG_TIM, &sim_timer_dev, "sim_clock_coschedule() - queueing %s for clock co-schedule\n", sim_uname (uptr)); pthread_mutex_lock (&sim_timer_lock); - uptr->next = sim_clock_cosched_queue; + uptr->a_next = sim_clock_cosched_queue; sim_clock_cosched_queue = uptr; pthread_mutex_unlock (&sim_timer_lock); return SCPE_OK;