Shop OBEX P1 Docs P2 Docs Learn Events
Stack space — Parallax Forums

Stack space

RsadeikaRsadeika Posts: 3,837
edited 2009-08-15 17:37 in Propeller 1
After looking through the manual I did not get a good handle on how you should calculate for stack space. In the snippet below, I had a heck of a time of getting the program to run properly when the value was 'long BTstack[noparse][[/noparse]10]'. When I changed the value to 'long BTstack[noparse][[/noparse]20]', then it ran as expected. So, is there a way of calculating as to what that value should be? I can not imagine going through a repetition of, is it [noparse][[/noparse]10], is it [noparse][[/noparse]11], .... is it [noparse][[/noparse]20], until the program runs correctly. The snippet will be expanded to start up all the cogs available with cognew, so it would helpful if I had some easy way of figuring the stack space values.

CON
  _clkmode  = xtal1 + pll16x
  _xinfreq = 5_000_000

  
OBJ
fds  : "FullDuplexSerial"  '' => fds[noparse][[/noparse]0], fds, fds

VAR
  long BTstack[noparse][[/noparse]20]

PUB Main
  cognew(BTprog, @BTstack)

PRI BTprog
'  waitcnt(clkfreq+cnt)
  fds[noparse][[/noparse]0].start(0,1,0,57600)             '' Start the serial port
  fds[noparse][[/noparse]0].str(string("This is a test",10,13))  '' Print out the header
  fds[noparse][[/noparse]0].str(string("End of test"))





Thanks

Ray

Post Edited (Rsadeika) : 8/15/2009 5:22:58 PM GMT

Comments

  • localrogerlocalroger Posts: 3,452
    edited 2009-08-14 20:37
    Look for the Stack Length object in the obex, that's what it's designed for.
  • Mike GreenMike Green Posts: 23,101
    edited 2009-08-14 20:46
    There's no easy way to calculate the amount of stack needed. You can only estimate it, then add a "fudge factor" to allow for mistakes and oversights. It gets fairly complicated if your routines call other routines like those in FullDuplexSerial. Each level of method call uses about 3 longs plus the space for any parameters and declared local variables. If a method call is used like a function, there may be temporary variables needed in the expression prior to the method call.

    In your case, you've got 3 longs for BTprog plus 3 longs for the call on fds[noparse][[/noparse] 0 ].start plus 4 longs for the 4 parameters plus any storage that the start method requires (you'd have to look at the FDS source for that). The calls to fds[noparse][[/noparse] 0 ].str method need space for only 1 parameter, but there's a chain of calls internal to FDS (str -> tx -> rx -> rxcheck) that each need 3 longs, maybe more.

    I'd use a stack space with at least 30 longs, more to be safe. It's either that or a painstaking analysis of your program and the objects it uses. The other option is to use a stack monitor object (like the one in the Object Exchange) that uses a cog to watch another cog's stack usage and see what's actually used.

    Post Edited (Mike Green) : 8/14/2009 9:55:49 PM GMT
  • jazzedjazzed Posts: 11,803
    edited 2009-08-14 21:42
    Each stack frame (method call) is 2 longs + a long for result + a long per local variable + N longs per local array of size N + a long per parameter. Then you have to add longs for intermediate processing such as complicated math expressions. Avoid recursion if possible [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    --Steve


    Propalyzer: Propeller PC Logic Analyzer
    http://forums.parallax.com/showthread.php?p=788230
  • RsadeikaRsadeika Posts: 3,837
    edited 2009-08-14 22:24
    I guess I will probably end up just taking a wild guess, then add some value, and then add 20 just to be safe. Probably the more important aspect is that you do not get any warning that you may be a little short on your stack space number. I can see a large complicated program becoming a debugging nightmare if you get your values wrong. I guess the lesson learned here is, be very careful with the values that you select.

    Ray
  • CounterRotatingPropsCounterRotatingProps Posts: 1,132
    edited 2009-08-14 22:46
    Right Ray, just brute force it - just pick a bigger number than the worst case. When code gets tight, use that OBEX tool LocalRoger mentions.
    Indeed, if the stack is *just* slightly too small, you might not get errors at all - until your code runs through an infrequent chain - then *BANG*.

    ANd you know, its often in the error trapping routines that stacks prove to be too small - how ironic is having your error routine trap something and then crash themselves?

    - H

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
  • RsadeikaRsadeika Posts: 3,837
    edited 2009-08-15 17:27
    Since I am thinking about stack space, coginit also uses it. What would be the advantage in using coginit as opposed to cognew? Would the tracking of stack space be made easier with coginit, or is it the same problem. All the examples that I have seen use cognew, so there must be something to it.

    Ray
  • Mike GreenMike Green Posts: 23,101
    edited 2009-08-15 17:37
    There are very few circumstances where you should use COGINIT vs. COGNEW. The main one is when you want the new program to use the same cog that's issuing the COGINIT. There you want to explicitly supply a cog # (from COGID).

    Almost all the time you would want to use COGNEW because you will make mistakes and start up the new cog using a cog that you still need and the bug will be very hard to track down. Better to use COGSTOP to stop cogs that you no longer need and use COGNEW and let the hardware keep track of which ones are in use and which are available.

    Whether there's a stack or not and what size it needs to be has nothing to do with COGNEW or COGINIT.
Sign In or Register to comment.