Shop OBEX P1 Docs P2 Docs Learn Events
Stoping Running SPIN to allow 8 PASM COGs — Parallax Forums

Stoping Running SPIN to allow 8 PASM COGs

Brian FairchildBrian Fairchild Posts: 549
edited 2012-06-28 16:57 in Propeller 1
I'm not going to be near any real hardware for a few days to try but will this code snippet allow me to end up with 8 COGs all running PASM...

coginit(1,@cog1_pasm,0)
coginit(2,@cog2_pasm,0)
coginit(3,@cog3_pasm,0)
coginit(4,@cog4_pasm,0)
coginit(5,@cog5_pasm,0)
coginit(6,@cog6_pasm,0)
coginit(7,@cog7_pasm,0)
coginit(0,@cog0_pasm,0)

...where "cogx_pasm" points to my pasm code?

I'm just not sure about that last line. I know it's going to overwrite the running SPIN interpreter but is it a 'clean' switch over to the running PASM?

Comments

  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 08:38
    Yep. I have done stuff like that. Works just fine.

    Assuming you start from reset or otherwise know that you are running on cog 0.

    Otherwise I would get the ID of the cog running this code with "cogid". Then start the 7 cogs that are not this one with the PASM routines. Finally restart the current cog with:

    cogint (cogid, @whatever_pasm, 0)

    That's assuming you are not fussy about which cog runs which PASM routine. I believe there are cases where you might want to be fussy, and you would have to orchestrate things a bit more carefully there.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-06-27 08:39
    Yes, it is a clean switch. Cog 0 will stop running the Spin interpreter as soon as it executes the coginit instruction. It will begin executing the cog0_pasm code as soon as it is fully loaded. All of cog 0's registers will be cleared, as if you had done a cogstop.
  • ericballericball Posts: 774
    edited 2012-06-27 09:13
    Heater's solution (doesn't assume which cog is currently running SPIN).
    cognew(@cog1_pasm,@cog1_parms)
    cognew(@cog2_pasm,@cog2_parms)
    cognew(@cog3_pasm,@cog3_parms)
    cognew(@cog4_pasm,@cog4_parms)
    cognew(@cog5_pasm,@cog5_parms)
    cognew(@cog6_pasm,@cog6_parms)
    cognew(@cog7_pasm,@cog7_parms)
    coginit(cogid,@cog0_pasm,@cog0_parms)
    
  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 09:22
    Not quite Eric.
    What you have there might fail on any of those cognew statements if there are already cogs running.
    I was hinting at the general case where you don't know which cog you are or what is running on other cogs and you just want to trash them all for your new code.
    That is probably not required though.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-06-27 09:49
    You could ensure that the cognew's all work by running this code first.
      repeat i from 0 to 7
        if i <> cogid
          cogstop(i)
    
    I use this when starting a stand-alone program from Spinix. I also return all the locks so the Prop is essentially in the same state that it would be on boot up. Of course, most programs would be aware of which cogs and locks are in use, and would handle them as needed.
  • Mark_TMark_T Posts: 1,981
    edited 2012-06-27 09:59
    You might want to reset the locks too, if random other cogs have been running and you overwrite them they could leave some of the locks in use
      repeat i from 0 to 7
        if i <> cogid
          cogstop(i)
      repeat i from 0 to 7  
        lockclr (i)
        lockret (i)
      repeat i from 0 to 7
        if i <> cogid
          coginit (i, @cog_asm, @params)
      coginit (cogid, @cog_asm, @params)
    
      
    
  • ericballericball Posts: 774
    edited 2012-06-27 11:29
    @Heater - you're correct.

    @Mark_T - I was thinking "why stop the cogs first?", then I realized that if you don't stop them first then there's a risk releasing the locks will cause something bad to happen.
      pasm_ptr[0] := @cog0_pasm
      pasm_ptr[1] := @cog1_pasm
      pasm_ptr[2] := @cog2_pasm
      pasm_ptr[3] := @cog3_pasm
      pasm_ptr[4] := @cog4_pasm
      pasm_ptr[5] := @cog5_pasm
      pasm_ptr[6] := @cog6_pasm
      pasm_ptr[7] := @cog7_pasm
      parm_ptr[0] := @cog0_params
      parm_ptr[1] := @cog1_params
      parm_ptr[2] := @cog2_params
      parm_ptr[3] := @cog3_params
      parm_ptr[4] := @cog4_params
      parm_ptr[5] := @cog5_params
      parm_ptr[6] := @cog6_params
      parm_ptr[7] := @cog7_params
    
      repeat i from 0 to 7
        if i <> cogid
          cogstop(i)
      repeat i from 0 to 7  
        lockclr (i)
        lockret (i)
      repeat i from 0 to 7
        if i <> cogid
          coginit (i, pasm_ptr[i], parm_ptr[i])
      coginit (cogid, pasm_ptr[cogid], parm_ptr[cogid])
    
  • Brian FairchildBrian Fairchild Posts: 549
    edited 2012-06-27 11:57
    Thanks guys.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-27 12:00
    In an app where cogs have to be started and stopped, the code for those cogs should be written to release their locks and end gracefully upon request, rather than being forced with cogstop. Who's to say that, if you force a cog to stop, another cog that's still running won't be starting a new cog or acquiring a new lock? You could easily end up in a "whack-a-mole" situation that way.

    -Phil
  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 12:22
    Dam'it Phil you are right. This problem is not as simple as it first seems.
    So the challenge comes down to:

    How can you reliably stop all COG except your self and be sure all locks are released. So that you can safely start with a clean slate?
    This is a generalized problem that may be relevant if you are part of some OS and you have no knowledge of what the current application is doing with the COGs.

    Of course it could that the COGs you are trying to kill off are also wanting to take the entire machine including you!

    What we have here is a modern day "core wars" but this time with real cores.
  • pedwardpedward Posts: 1,642
    edited 2012-06-27 13:12
    The graceful way is to have a "check for exit condition" in your code.

    Another way is to launch all the cogs you can, to take up the free COG slots, then alternately kill the other running COGs and launch a replacement in it's place. Eventually you will force out the running COGs even if they aren't playing nice. Then you can reinit the locks and set a "start/continue" flag for the COGs.

    Since there is no way to send "signals" to the COGs, you have to rely on them checking flags periodically.
  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 13:33
    Might not work.

    In the face of malicious code running in the cogs there is no way to do this reliably unless there is a special "master cog" with extra hardware protection. Which there is not.
  • pedwardpedward Posts: 1,642
    edited 2012-06-27 13:48
    There is a master COG, it's called REBOOT. ;)
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-06-27 13:58
    In an app where cogs have to be started and stopped, the code for those cogs should be written to release their locks and end gracefully upon request, rather than being forced with cogstop. Who's to say that, if you force a cog to stop, another cog that's still running won't be starting a new cog or acquiring a new lock? You could easily end up in a "whack-a-mole" situation that way.
    You could run the cogstop loop twice. It takes a while for a cog to start up, so the second loop would stop any cogs that were started while the first loop ran. Of course, a Spin program might not be fast enough to do this, but a PASM program would work. The lock cleanup loop would run after the second cogstop loop.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-27 14:01
    'Brings up an interesting question. A cog has three states: stopped, loading, and running. What does a cogstop do to a cog that's loading?

    -Phil
  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 20:19
    Reboot does not help. How do yo know a malicious cog is not also doing a reboot and how do you know what code it has written to the boot ROM first?

    Being fast in PASM does not help. How do you know the malicious code is not also fast?

    Doing cogstop many times does not help. How do you know the malicious code is not doing that as well.

    In fact as you are running trying to be the master cog and shut everyone else down you have to consider that whatever you do the maliciois code might also be doing. Indeed it may be a clone of your own code.

    So in the end you cannot be sure who wins unless one of you has some extra hardware privilages.
  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 20:21
    Phil,
    "what does cog stop do to a cog that is loading?"
    Sounds like time for an experiment.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-06-27 20:31
    heater wrote:
    Sounds like time for an experiment.
    Yeah, I know. I'll add it to my list. :)

    -Phil
  • mindrobotsmindrobots Posts: 6,506
    edited 2012-06-27 20:50
    Use two propellers. One runs as the supervisory prop and remains protected from user code (malicious or otherwise) it can provide all control signals and forcibly load user code into the user prop after it resets it. The supervisor prop could also expose secure system services to the user prop through spi or i2c or high speed serial links.

    The additional cost is the $8 for the second prop.
  • Heater.Heater. Posts: 21,230
    edited 2012-06-27 21:03
    That would do it.
  • Mark_TMark_T Posts: 1,981
    edited 2012-06-28 16:57
    Heater. wrote: »
    Phil,
    "what does cog stop do to a cog that is loading?"
    Sounds like time for an experiment.

    Forces stop mode I should think. I suspect that's just a single cog-reset line that overrides everything in that cog.

    Similarly coginit during loading would restart the loading with the new parameters. That's how I'd design it (i.e. idempotent) for simplicity and avoidance of race conditions. I am guessing that loading is a done with a special circuit with two counters to copy hub ram to cog ram and then enable execution. coginit would simply have to set that circuit running. In fact I'd arrange that one counter is actually the program counter itself temperarily re-purposed. Wonder if it's done that way...
Sign In or Register to comment.