Skip to content

Commit

Permalink
Allow the priority comparison function to return 0 if received priori…
Browse files Browse the repository at this point in the history
…tes are same
  • Loading branch information
byeonggiljun committed Mar 12, 2024
1 parent 31a5b1b commit 62f2ab5
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 45 deletions.
4 changes: 2 additions & 2 deletions core/reactor_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion core/utils/pqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down
18 changes: 9 additions & 9 deletions core/utils/pqueue_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion core/utils/pqueue_tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/**
Expand Down
2 changes: 1 addition & 1 deletion include/core/utils/pqueue_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 16 additions & 31 deletions lib/schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,24 +207,18 @@ 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
// after the stop tag.
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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 62f2ab5

Please sign in to comment.