Shop OBEX P1 Docs P2 Docs Learn Events
How long does it take for a cog to start - and when does SPIN cognew return? — Parallax Forums

How long does it take for a cog to start - and when does SPIN cognew return?

agsags Posts: 386
edited 2013-05-02 05:44 in Propeller 1
I just finished debugging a problem that was solved (or the problem masked, as I can't yet explain the behavior I've observed) by adding a pause after starting another cog. In my top object, I call another object's Init method to start a new cog (the "child" cog) which launches PASM code, then call methods that run in the original cog (the "parent" cog - the one from which Init was called to start the "child" cog) and which interact with the "child" cog. If this description is not clear I can post some code.

My hypothesis is that (SPIN) cognew returns before the cog which it starts has loaded and launched the PASM code and stabilized. So if the next method I call requires the other ("child") cog to be running for correct function, it fails. If cognew waits for the new cog to be up and running before returning, this theory doesn't make sense.

I note that just a single 1 second pause immediately after cognew returns solves the problem; no other pauses are necessary.

So when does cognew return, and how long does it take for a newly started cog (executing PASM code) to be ready to process requests?

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-05-01 21:36
    ags wrote: »
    So when does cognew return, and how long does it take for a newly started cog (executing PASM code) to be ready to process requests?
    Immediately. Startup time is the same (even the SPIN interpreter is just PASM), it goes through the motion of 512 hubops (despite only loading/using 496 longs) so 8K cycles are good enough in most cases ([post=864343]details[/post]).
  • agsags Posts: 386
    edited 2013-05-01 22:06
    That explains it. Given that insight I played with my delay, reducing it from a constant 1 second to incrementally smaller numbers of clock cycles. It failed between 3k and 4k clocks, which I can explain because the Init call actually passes through 3 methods, so when the Init returns it has to pop three callstacks before the method that interacts with the child cog happens.

    It is considered a best practice to always add a delay in the initializing method after starting a cog to avoid this type of problem? This type of problem is hard to diagnose, particularly if the same object worked in other applications (because the caller didn't hit the new cog with an immediate method call).

    Thanks for another helpful answer. I'm surprised that I haven't hit this before, or seen it discussed here.
  • kuronekokuroneko Posts: 3,623
    edited 2013-05-01 22:14
    ags wrote: »
    It is considered a best practice to always add a delay in the initializing method after starting a cog to avoid this type of problem?
    Depends, if the user of said cog can't deal with the startup delay then you have to wait. Usually a delay is added (for worst case) or you block until the cog tells you that it's up e.g. by clearing/setting a specific parameter field which is monitored by the caller.
  • Heater.Heater. Posts: 21,230
    edited 2013-05-02 04:14
    A delay will ensure things run correctly and is probably OK as we know that the cog start up time is always constant.

    Personally I don't like the style. I would rather the parent cog waits for some flag to be set (or cleared) by the child when it is up and running and ready to do business. There are many approaches to this.
  • agsags Posts: 386
    edited 2013-05-02 05:44
    I agree fully. Like I said, I find it astonishing that I didn't realize this, or run into problems before. That's just because I must have had enough delay inherent in the program flow but of which I was unaware. Having the caller wait for the cog to launch could waste time if other things can be done in the "parent" cog during that time. Passing back a "ready" flag is the way to go. I won't even wait for the flag to be set/cleared before returning to the caller. As it turns out, I already have all the machinery available to support this. I use a "mailbox" to communicate with the child cog. When the child has completed an operation, it clears the mailbox. Whenever I initiate a command, I first wait for the mailbox to be cleared, indicating it is ready for the next one. At cog startup, this mailbox starts out cleared (PASM entry point takes care of all initialization) but I have always been sure to clear the mailbox as the last step in initialization anyway. All I have to do is force the mailbox to not be clear when I initialize the cog. Now, if a child cog method is called before the initialization is complete, it will wait, but the parent isn't forced to wait a fixed time (which would have to be the worst-case time assuming the very next method called was a child cog method) if it's not needed.

    One line of code to change. Brilliant. Thanks.
Sign In or Register to comment.