Shop OBEX P1 Docs P2 Docs Learn Events
Stack up or stack down? — Parallax Forums

Stack up or stack down?

CannibalRoboticsCannibalRobotics Posts: 535
edited 2011-06-17 12:58 in Propeller 1
So if I'm trying to test stack depth and I use:
  bytefill(@MCPStack, %1010_0101, 500 * 4)              ' Fill stack space.
to fill the stack. Where MCPStack is set to 500 longs.

Then I use:
pub TestStack | i,j
  repeat i from @MCPStack to (@MCPStack + (500 * 4)-1)
    bytemove(@j,i,1)   
    if j <> %1010_0101
      return (i - @MCPStack)/4
to read it.
So, unless I'm really lucky with the value of the test byte, it should tell me the depth?
I'm getting 7 every time even after changing the value of the test byte.
So, is this only using 7 longs in the stack?
Thanks in advance,
Jim-

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-06-16 10:46
    7 longs sounds approximately right. TestStack uses 3 or 4 longs, the local variables use another 2. The bytemove uses 3 temporarily
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2011-06-16 10:56
    It's testing a much larger program though, not just TestStack.
    TestStack is called about once a minute.
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-06-16 16:26
    Jim,

    I'm not sure why you get a value of 7. The test should fail immediately on the first byte, and you should get a value of 0. The beginning of the stack contains a stack frame, so the first byte shouldn't match your test value. You should check the stack starting from the end instead of the beginning. Also, it is better to use a 32-bit test value rather than 8 bits because there is less chance of a false match. Your code should look something like the code shown below.

    Dave
      longfill(@MCPStack, $12345678, 500)              ' Fill stack space.
    ...
    pub TestStack | i
      repeat i from 499 to 0
        if long[@MCPStack][i] <> $12345678
          quit
      return i
    

    EDIT: When do you fill the stack? You should be doing it before you do the cognew. I suspect that you might be doing it at the beginning of the new cog's method. This might explain why the first 7 longs contain the test value.
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2011-06-17 08:34
    OK,
    I'll try it prior to COGNEW, it's sitting in the top of the main program loaded into the cog.
    J-
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2011-06-17 10:24
    OK,
    got it worked out and relearned a few things along the way. This one counts down from the top, not up from the bottom, seems to make more sense and the values are more reasonable for the code; in the 30 to 50 longs range.
    Note the placement ahead of COGNEW - Thanks Dave.
    In the start pub we have...
      seed := seed?
      bytefill(@Stack,seed, 100 * 4)              ' Fill stack space.
      cognew(Main, @Stack)
    
    To sample the stack use:
    pub TestStack | i,j
      j := seed
      i := @Stack + (100 * 4) - 1
      repeat while j == seed and i > @Stack - 1
        bytemove(@j,i,1)   
        i --
        
      i := (i - @Stack) / 4
      return i
    

    The other thing I was reminded of is that variables used locally, like the i and j of TestStack must be initialized on every call.
    This begs a discussion of the question: Is stack depth the sum of all stack calls in an object or is it the maximum depth of the most simultaneously active pub/pri stack calls?
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-06-17 12:58
    The stack depth is the maximum depth of the most simultaneously active pub/pri calls plus additional space needed for intermediate storage. An expression like a := b + c * (d / e) loads b, c, d and e on the stack, and then performs the /, * and + operations. It needs four longs on the stack to do this.

    Here's a simple program to measure the amount of stack used by each call
    con
      _clkmode = xtal1+pll16x
      _clkfreq = 80_000_000
      
    obj
      ser : "FullDuplexSerial"
    
    pub main
      ser.start(31, 30, 0, 115200)
      recurse(@Result, 1)
    
    pub recurse(pResult, callnum)
      ser.dec(callnum)
      ser.tx(" ")
      ser.dec(pResult)
      ser.tx(13)
      if callnum < 4
       recurse(@Result, callnum + 1)
    
    It produces the following output.
    1 856
    2 868
    3 888
    4 908
    
    main uses 12 bytes, and recurse uses 20 bytes for each call. The difference between main and recurse is the 8 bytes used for the two parameters in recurse. The other 12 bytes are for the Result variable, and the 8-byte stack frame used for each call.
Sign In or Register to comment.