Shop OBEX P1 Docs P2 Docs Learn Events
Order of Spin parameters in memory — Parallax Forums

Order of Spin parameters in memory

David BetzDavid Betz Posts: 14,516
edited 2013-08-15 18:52 in Propeller 1
Can I count on the fact that adjacent parameters in a Spin argument list are actually contiguous in memory? I have the following code that I'd like to simplify:
CON
  INIT_MBOXES           = 0     ' base of an array of mailboxes
  INIT_CONFIG_1         = 1     ' driver specific configuration
  INIT_CONFIG_2         = 2
  INIT_CONFIG_3         = 3
  INIT_CONFIG_4         = 4
  _INIT_SIZE            = 5

PUB start(code, mbox_count, mboxes, config1, config2, config3, config4) | params[_INIT_SIZE]
    xm_mbox := mboxes   ' use the first mailbox
    longfill(mboxes, 0, _MBOX_SIZE * mbox_count)
    long[mboxes + _MBOX_SIZE * mbox_count] := $00000008
    params[INIT_MBOXES] := mboxes
    params[INIT_CONFIG_1] := config1
    params[INIT_CONFIG_2] := config2
    params[INIT_CONFIG_3] := config3
    params[INIT_CONFIG_4] := config4
    cognew(code, @params)

Can I change it to this and have it still work?
PUB start(code, mbox_count, mboxes, config1, config2, config3, config4)
    xm_mbox := mboxes   ' use the first mailbox
    longfill(mboxes, 0, _MBOX_SIZE * mbox_count)
    long[mboxes + _MBOX_SIZE * mbox_count] := $00000008
    cognew(code, @mboxes)

I would normally not do something like this in C since it depends on the underlying compiler implementation. Should I stay away from it in Spin as well?

Comments

  • ersmithersmith Posts: 6,054
    edited 2013-08-15 06:09
    A lot of Spin programs do seem to assume that contiguous parameters are contiguous in memory, and use exactly the trick you're asking about (passing the address of the first parameter to a COG) so it's unlikely to change. However, even then one does have to be careful -- the parameters are on the stack, so they're going to be overwritten by the Spin interpreter "soon". Most Spin programs seem to ignore this problem because COG code pretty much always wins the race, but one does have to be aware of the race condition and make sure copying the parameters is the first thing done in the COG program.

    (spin2cpp has to implement some slightly painful memory shuffling to work around exactly this issue in order to maintain compatibility with Spin)

    Eric
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-15 06:21
    ersmith wrote: »
    A lot of Spin programs do seem to assume that contiguous parameters are contiguous in memory, and use exactly the trick you're asking about (passing the address of the first parameter to a COG) so it's unlikely to change. However, even then one does have to be careful -- the parameters are on the stack, so they're going to be overwritten by the Spin interpreter "soon". Most Spin programs seem to ignore this problem because COG code pretty much always wins the race, but one does have to be aware of the race condition and make sure copying the parameters is the first thing done in the COG program.

    (spin2cpp has to implement some slightly painful memory shuffling to work around exactly this issue in order to maintain compatibility with Spin)

    Eric
    That's a very good point! It's also something I'd like to change in the SDRAM driver startup protocol. Right now it seems not to have a way to determine that it's done with its initialization. I guess I could propose that the first element of the initialization structure (the base address of the mailbox array) be zeroed by the driver after it has completed parsing the parameters. Thanks for catching this!

    The code would be changed to this:
    PUB start(code, mbox_count, mboxes, config1, config2, config3, config4)
        xm_mbox := mboxes   ' use the first mailbox
        longfill(mboxes, 0, _MBOX_SIZE * mbox_count)
        long[mboxes + _MBOX_SIZE * mbox_count] := $00000008
        cognew(code, @mboxes)
        repeat while mboxes != 0
    
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-08-15 08:37
    so they're going to be overwritten by the Spin interpreter "soon"

    I have used this scheme more than once, assuming that the parameters were safe... I'm thinking now that I need to have the cog flag my Spin code that it has picked up all of the parameters before returning from the Spin method that instantiates the cog.

    Thanks for the tip.
  • David BetzDavid Betz Posts: 14,516
    edited 2013-08-15 08:42
    David Betz wrote: »
    That's a very good point! It's also something I'd like to change in the SDRAM driver startup protocol. Right now it seems not to have a way to determine that it's done with its initialization.
    In thinking about this a little more, I realize that Chip's original protocol is fine. No surprise there! I introduced the synchronization problem when I changed the startup protocol to pass the address of a parameter block instead of just the address of the mailbox array. So I guess I've just fixed a bug that I introduced myself by adding the handshaking to my modified driver.
  • agsags Posts: 386
    edited 2013-08-15 08:52
    Looks like you already have several confirmations, but if it helps, I use this "trick" all the time. It took a while for me not to break out in a rash when I first started (I've spent a lot of time doing large-scale C++ programming) but it's now comfortable. As you point out, the parameters are on the (SPIN) stack, and they are ordered as expected. I use the handshaking technique to make sure that the values have all been loaded into cog RAM before I continue in the SPIN code (before the method returns, freeing the stack).

    When I first started coding the Propeller, I would copy the parameters to a DAT or VAR, and then pass that way. Then I tried to compress parameters (they often are not long values, so I can shift and combine multiple bytes and/or words). Then I tried putting DAT blocks after the cog PASM code so the values at coginit were copied to the cog RAM automatically. I have come to the conclusion that the hub RAM used and/or number of cycles executing the SPIN code to compress the parameters is more than just passing a start address in a mailbox - as you are doing here. It's proven reliable for me.
  • localrogerlocalroger Posts: 3,451
    edited 2013-08-15 18:52
    It takes 8,000 clocks for the COG to start and then it presumably gets its args in a few microseconds. If there's any doubt a waitcnt(cnt+10000) should ensure that the stack hangs around for a new cog to get it s goodies.
Sign In or Register to comment.