From 62f2ab5b3791bc3ec9c12aa4ebb5f529cd1e9a45 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 16:19:33 -0700 Subject: [PATCH] Allow the priority comparison function to return 0 if received priorites are same --- core/reactor_common.c | 4 +-- core/utils/pqueue.c | 2 +- core/utils/pqueue_base.c | 18 ++++++------ core/utils/pqueue_tag.c | 2 +- include/core/utils/pqueue_base.h | 2 +- lib/schedule.c | 47 +++++++++++--------------------- 6 files changed, 30 insertions(+), 45 deletions(-) diff --git a/core/reactor_common.c b/core/reactor_common.c index 495a440b5..afe37ef53 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -1181,8 +1181,8 @@ void termination(void) { lf_print_warning("---- There are %zu unprocessed future events on the event queue.", pqueue_tag_size(env[i].event_q)); event_t* event = (event_t*)pqueue_tag_peek(env[i].event_q); - interval_t event_time = event->base.tag.time - start_time; - lf_print_warning("---- The first future event has timestamp " PRINTF_TIME " after start time.", event_time); + lf_print_warning("---- The first future event has timestamp " PRINTF_TAG " after start tag.", + event->base.tag.time - start_time, event->base.tag.microstep); } // Print elapsed times. // If these are negative, then the program failed to start up. diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index 0187a37ca..cdee19e7d 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -13,7 +13,7 @@ #include "util.h" #include "lf_types.h" -int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return (thiz > that); } +int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 1 ? (thiz > that) : 0 ? (thiz == that) : -1; } int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 0; } diff --git a/core/utils/pqueue_base.c b/core/utils/pqueue_base.c index 30d84286e..144cbd68d 100644 --- a/core/utils/pqueue_base.c +++ b/core/utils/pqueue_base.c @@ -60,7 +60,7 @@ void* find_equal(pqueue_t* q, void* e, int pos, pqueue_pri_t max) { void* curr = q->d[pos]; // Stop the recursion when we've surpassed the maximum priority. - if (!curr || q->cmppri(q->getpri(curr), max)) { + if (!curr || q->cmppri(q->getpri(curr), max) == 1) { return NULL; } @@ -93,11 +93,11 @@ void* find_equal_same_priority(pqueue_t* q, void* e, int pos) { // Stop the recursion once we've surpassed the priority of the element // we're looking for. - if (!curr || q->cmppri(q->getpri(curr), q->getpri(e))) { + if (!curr || q->cmppri(q->getpri(curr), q->getpri(e)) == 1) { return NULL; } - if (q->getpri(curr) == q->getpri(e) && q->eqelem(curr, e)) { + if (q->cmppri(q->getpri(curr), q->getpri(e)) == 0 && q->eqelem(curr, e)) { return curr; } else { rval = find_equal_same_priority(q, e, LF_LEFT(pos)); @@ -157,7 +157,7 @@ static size_t maxchild(pqueue_t* q, size_t i) { if (child_node >= q->size) return 0; - if ((child_node + 1) < q->size && (q->cmppri(q->getpri(q->d[child_node]), q->getpri(q->d[child_node + 1])))) + if ((child_node + 1) < q->size && (q->cmppri(q->getpri(q->d[child_node]), q->getpri(q->d[child_node + 1])) == 1)) child_node++; /* use right child instead of left */ return child_node; @@ -168,7 +168,7 @@ static size_t bubble_up(pqueue_t* q, size_t i) { void* moving_node = q->d[i]; pqueue_pri_t moving_pri = q->getpri(moving_node); - for (parent_node = LF_PARENT(i); ((i > 1) && q->cmppri(q->getpri(q->d[parent_node]), moving_pri)); + for (parent_node = LF_PARENT(i); ((i > 1) && q->cmppri(q->getpri(q->d[parent_node]), moving_pri) == 1); i = parent_node, parent_node = LF_PARENT(i)) { q->d[i] = q->d[parent_node]; q->setpos(q->d[i], i); @@ -184,7 +184,7 @@ static void percolate_down(pqueue_t* q, size_t i) { void* moving_node = q->d[i]; pqueue_pri_t moving_pri = q->getpri(moving_node); - while ((child_node = maxchild(q, i)) && q->cmppri(moving_pri, q->getpri(q->d[child_node]))) { + while ((child_node = maxchild(q, i)) && (q->cmppri(moving_pri, q->getpri(q->d[child_node])) == 1)) { q->d[i] = q->d[child_node]; q->setpos(q->d[i], i); i = child_node; @@ -227,7 +227,7 @@ int pqueue_remove(pqueue_t* q, void* d) { return 0; // Nothing to remove size_t posn = q->getpos(d); q->d[posn] = q->d[--q->size]; - if (q->cmppri(q->getpri(d), q->getpri(q->d[posn]))) + if (q->cmppri(q->getpri(d), q->getpri(q->d[posn])) == 1) bubble_up(q, posn); else percolate_down(q, posn); @@ -320,7 +320,7 @@ static int subtree_is_valid(pqueue_t* q, int pos) { if ((size_t)left_pos < q->size) { /* has a left child */ - if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_LEFT(pos)]))) + if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_LEFT(pos)])) == 1) return 0; if (!subtree_is_valid(q, LF_LEFT(pos))) return 0; @@ -332,7 +332,7 @@ static int subtree_is_valid(pqueue_t* q, int pos) { } if ((size_t)right_pos < q->size) { /* has a right child */ - if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_RIGHT(pos)]))) + if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_RIGHT(pos)])) == 1) return 0; if (!subtree_is_valid(q, LF_RIGHT(pos))) return 0; diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 1c2efefe4..53d2375fd 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -33,7 +33,7 @@ static pqueue_pri_t pqueue_tag_get_priority(void* element) { return (pqueue_pri_ * @param priority2 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. */ static int pqueue_tag_compare(pqueue_pri_t priority1, pqueue_pri_t priority2) { - return (lf_tag_compare(((pqueue_tag_element_t*)priority1)->tag, ((pqueue_tag_element_t*)priority2)->tag) > 0); + return (lf_tag_compare(((pqueue_tag_element_t*)priority1)->tag, ((pqueue_tag_element_t*)priority2)->tag)); } /** diff --git a/include/core/utils/pqueue_base.h b/include/core/utils/pqueue_base.h index 8c9fc8f2c..0656abad8 100644 --- a/include/core/utils/pqueue_base.h +++ b/include/core/utils/pqueue_base.h @@ -81,7 +81,7 @@ typedef struct pqueue_t { * @param n the initial estimate of the number of queue items for which memory * should be preallocated * @param cmppri The callback function to run to compare two elements - * This callback should return 0 for 'lower' and non-zero + * This callback should return -1 for 'lower', 0 for 'same', and 1 * for 'higher', or vice versa if reverse priority is desired * @param getpri the callback function to run to set a score to an element * @param getpos the callback function to get the current element's position diff --git a/lib/schedule.c b/lib/schedule.c index 3781ef285..0998c0143 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -207,15 +207,11 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Check for conflicts (a queued event with the same trigger and tag). if (min_spacing <= 0) { // No minimum spacing defined. + e->base.tag = intended_tag; event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)e); // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { intended_tag.microstep++; - // // Skip to the last node in the linked list. - // while (found->next != NULL) { - // found = found->next; - // intended_tag.microstep++; - // } if (lf_is_tag_after_stop_tag(env, intended_tag)) { LF_PRINT_DEBUG("Attempt to schedule an event after stop_tag was rejected."); // Scheduling an event will incur a microstep @@ -223,8 +219,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int lf_recycle_event(env, e); return 0; } - // // Hook the event into the list. - // found->next = e; e->base.tag = intended_tag; trigger->last_tag = intended_tag; pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); @@ -255,26 +249,24 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int return (0); case replace: LF_PRINT_DEBUG("Policy is replace. Replacing the previous event."); - // // If the event with the previous tag is still on the event - // // queue, then replace the token. To find this event, we have - // // to construct a dummy event_t struct. - // event_t* dummy = lf_get_new_event(env); - // // dummy->next = NULL; - // dummy->trigger = trigger; - // dummy->base.tag = trigger->last_tag; - // event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, dummy); - event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, trigger->last_tag); + // If the event with the previous tag is still on the event + // queue, then replace the token. To find this event, we have + // to construct a dummy event_t struct. + event_t* dummy = lf_get_new_event(env); + dummy->trigger = trigger; + dummy->base.tag = trigger->last_tag; + event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)dummy); if (found != NULL) { // Recycle the existing token and the new event // and update the token of the existing event. lf_replace_token(found, token); lf_recycle_event(env, e); - // lf_recycle_event(env, dummy); + lf_recycle_event(env, dummy); // Leave the last_tag the same. return (0); } - // lf_recycle_event(env, dummy); + lf_recycle_event(env, dummy); // If the preceding event _has_ been handled, then adjust // the tag to defer the event. @@ -308,12 +300,12 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Set the tag of the event. e->base.tag = intended_tag; - // Do not schedule events if if the event time is past the stop time - // (current microsteps are checked earlier). - LF_PRINT_DEBUG("Comparing event with elapsed time " PRINTF_TIME " against stop time " PRINTF_TIME ".", - e->base.tag.time - lf_time_start(), env->stop_tag.time - lf_time_start()); - if (e->base.tag.time > env->stop_tag.time) { - LF_PRINT_DEBUG("lf_schedule_trigger: event time is past the timeout. Discarding event."); + // Do not schedule events if if the event time is past the stop tag. + LF_PRINT_DEBUG("Comparing event with elapsed tag " PRINTF_TAG " against stop tag " PRINTF_TAG ".", + e->base.tag.time - lf_time_start(), e->base.tag.microstep, + env->stop_tag.time - lf_time_start(), env->stop_tag.microstep); + if (lf_is_tag_after_stop_tag(env, intended_tag)) { + LF_PRINT_DEBUG("lf_schedule_trigger: event tag is past the timeout. Discarding event."); _lf_done_using(token); lf_recycle_event(env, e); return (0); @@ -324,13 +316,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int trigger->last_tag = intended_tag; // Queue the event. - // FIXME: Modify the comment below. - // NOTE: There is no need for an explicit microstep because - // when this is called, all events at the current tag - // (time and microstep) have been pulled from the queue, - // and any new events added at this tag will go into the reaction_q - // rather than the event_q, so anything put in the event_q with this - // same time will automatically be executed at the next microstep. LF_PRINT_LOG("Inserting event in the event queue with elapsed tag " PRINTF_TAG ".", e->base.tag.time - lf_time_start(), e->base.tag.microstep); pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e);