-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for broken deadline propagation mechanism #1451
Conversation
I have added 3 test programs that fails on master which verifies that the deadline reactions are indeed prioritized |
@edwardalee Update:
|
Actually, ecplise-tests fails due to stack overflow in getInferredReactions. Can there be cycles when you follow the dependentReactions? |
@edwardalee I pushed a fix, but not sure if it is truly satisfactory. The stack-overflow happens because a reactionInstance can have itself in the set of |
Actually, that fix is not enough as the spiralling can be through other reactions and thus not be caught. There has to be some way of differentiating between reactions in different reactors in a bank? |
Oh, I think I know what the problem is. Each instance of ReactionInstance can stand for more than one "runtime instance." I.e., there is only one instance of ReactionInstance for the whole bank. The docs for ReactionInstance say this:
I think the deadline needs to be calculated and stored in It looks like there was a previous attempt to propagate deadlines. In
However, this won't do the job, I think. Deadlines, like levels, propagate more than one level. I think the implementation needs to be like |
It is a bit suspicious that only the macOS tests are failing. But I have now a design which I believe works. It followed Edwards proposal and mimics assignLevels, only doing it backwards. I have added a call to |
The MacOS CI runs seem to be very vulnerable to unexpected deadline violations. It seems that deadlines of hundreds of milliseconds are not enough. Maybe these tests are being run on a mechanical Turing machine and hence are very slow? |
Aha. I increased the deadlines now, their magnitude doesn't matter since I just wanna check that priorities are assigned correctly. I guess technically a Turing machine couldn't execute a LF program since we depend on constant "interaction" with an external clock and control flow is dictated by this interaction (deadlines)? |
Assign deadlines only if there are deadlines. Handle all 4 cases of hasLevels and hasDeadlines
org.lflang/src/org/lflang/generator/c/CTriggerObjectsGenerator.java
Outdated
Show resolved
Hide resolved
Sorry for the delay here, let's finish this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! Let's merge!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Only minor nitpicks about comments.
/** | ||
* Return a list of levels that runtime instances of this reaction have. | ||
* The size of this list is the total number of runtime instances. | ||
* A ReactionInstance may have more than one level if it lies within |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same out-of-context comment here.
org.lflang/src/org/lflang/generator/c/CTriggerObjectsGenerator.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Marten Lohstroh <[email protected]>
I still have some doubts whether the deadline propagation is implemented correctly. How it works now: When main reactor is created, if there is a deadline in the program, the deadlines are propagated on the ReactionInstanceGraph using Kahns Algorithm. The levels are also propagated. This is the only place where the deadline propagation algorithm is invoked. My doubt arises from this: assignLevels are called multiple other places also, which doesn't result in extra work because the results are cached. But we don't do this caching for the deadlines. So it suggests that there are scenarios where levels (and deadlines) are not propagated from the top-level main reactor. But I cannot think of such an example, but there must be a reason for calling assignLevels multiple places "just in case" |
I agee, @erlingrj, that it's sus. The only way to eliminate this doubt is to make sure |
@lhstrh @edwardalee. Can we merge this? My latest changes was to remove seemingly unnecessary calls to |
There is still an unaddressed |
Its done |
@@ -356,12 +351,27 @@ public Set<ReactionInstance> dependsOnReactions() { | |||
public Set<Integer> getLevels() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless assignLevels
is invoked in the constructor, there is no assurance that this method will always return a sensible result. Where is assignLevels
called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assignLevels is invoked once in createMainReactorInstance()
in CGenerator.c
. So it is called once on the top level reactor, which, if my understanding is correct should do the calculation for the whole reaction graph exactly once
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the problem that was addressed by calling assignLevels, "just in case" is that the level of a reaction is not known until you have constructed the whole reaction graph. So you cannot just do it in the constructor. A simple fix would be to add a simple function to reactorInstance which checks if levels has been assigned yet. (hasLevelsBeenAssigned()) this would walk up the containment hierarchy to the main reactor and check if it has created a reactionInstanceGraph yet (and thus assigned levels). If this for some reason is not true, then I propose to throw an error because the developer might be requesting the levels at a point in time where they are not available (e.g. before the reaction graph has been fully constructed).
How does this sound?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, that sounds like a good stop-gap measure to me. Still not fond of the original design, but the error will help prevent confusion.
I'm all for merging this! |
Does this fix #1448? |
This PR fixes two things:
reaction_t
always use FOREVER as the deadline. I.e. the EDF scheduling of reactions didn't work on single-threadedThis solves the problem of AfterDelay reactors blocking deadline reactions because they have low priority.
I am using this fix on an outdated branch it seems to work.
TODO: