help w choosing stack size
smthrll
Posts: 4
Hello, I've been working thru the tutorials on propeller C. I'm having a bit of difficulty understanding the choosing of a stack size. Please look at the following snippet from the tutorial:
/* Blink Light with Simple Multicore and Locks.c
Version 0.94 for use with SimpleIDE 9.40 and its Simple Libraries
Multicore example for use with CMM or LMM memory models.
http://learn.parallax.com/propeller-c-tutorials
*/
#include "simpletools.h" // Include simpletools header
// For LMM cog 160 bytes declared as int
// Add enough for stack & calcs (50 bytes declared as int
unsigned int stack[(160 + (50 * 4)) / 4];
// Declare volatile variables that will not be optimized
// to one variable for both cogs to share.
volatile unsigned int pin;
volatile unsigned int tdelay;
volatile unsigned int lockID;
// Function prototype
void blink(void *par);
// Cog 0 starts here
int main()
{
pin = 26;
tdelay = 200;
lockID = locknew();
print("lockID = %d\n", lockID);
// Pass function pointer, optional parameter value,
// stack array address, and the stack's size to cogstart.
int cog = cogstart(&blink, NULL, stack, sizeof(stack));
Could somebody shed some light on the bold part: why (160 +(50
/* Blink Light with Simple Multicore and Locks.c
Version 0.94 for use with SimpleIDE 9.40 and its Simple Libraries
Multicore example for use with CMM or LMM memory models.
http://learn.parallax.com/propeller-c-tutorials
*/
#include "simpletools.h" // Include simpletools header
// For LMM cog 160 bytes declared as int
// Add enough for stack & calcs (50 bytes declared as int
unsigned int stack[(160 + (50 * 4)) / 4];
// Declare volatile variables that will not be optimized
// to one variable for both cogs to share.
volatile unsigned int pin;
volatile unsigned int tdelay;
volatile unsigned int lockID;
// Function prototype
void blink(void *par);
// Cog 0 starts here
int main()
{
pin = 26;
tdelay = 200;
lockID = locknew();
print("lockID = %d\n", lockID);
// Pass function pointer, optional parameter value,
// stack array address, and the stack's size to cogstart.
int cog = cogstart(&blink, NULL, stack, sizeof(stack));
Could somebody shed some light on the bold part: why (160 +(50
Comments
That's a stacksize in bytes. And, it looks like from above that _thread_state_t is 176-12=164 bytes*, so if I were to rewrite the learn example I would do:
Where /4 is to convert to ints (4 bytes per int), and 50 is the estimated or measured stack required for this specific range of calling choices. If it's a single function that doesn't call anything you could make it smaller, if it's a complex web of functions it should be bigger.
As to why leave the math in there it's a matter of maintenance. It makes it easier to see how the number is derived, and since GCC will evaluate it at compile time there is no performance penalty. If you didn't have the math in there you'd just have to have a comment explaining how you got the number.
* That's when it was written. Since then improvements may have decreased the size to 160 bytes.
You've found a discrepancy in the documentation. I think the correct answer is ~176 bytes, not longs. At this point one of the PropGCC authors can answer best, but I'll hypothesize:
In the demo code we have the following two lines:
malloc takes bytes as a parameter (source), so it looks like the original author intended stacksize to be in bytes. I think it's a documentation error that it says long. It probably perpetuated from the cast to int* rather than keeping it as char*.
You might be able to experimentally try and see what the minimum stack size is. Perhaps start with a really small stack (10 bytes?), and see what the failure mode is. Then increase the stack until it starts working. If it starts working at a value not around 176 bytes or 176*4 bytes then it's probably a coincidental success. But the easier method would just be to wait for one of the Gurus.
I've updated the cogstart documentation.
Using malloc for stack as SRLM suggests is a good idea to get a more accurate size.
If you don't mind using vintage C99, it is also possible to declare an array dynamically.
The objective: cog 0 starts two cogs each blinks an LED, one at 1 Hz other at 2 Hz. No global variables. CMM model.
I don't understand why mine works with far less stack size than indicated in above posts. I'm using 40+25 which I copied from sample code (I'm embarrassed to forget where).
After reading above I would think it would take the minimum of 160 (no additional for global variables which are not used).
My only guess is CMM is different than LMM and LMM is discussed above.
Anyone know why this works?
Your example code is declaring 185 [edit] I should have said 260 here, see correction and explanation in next post [/edit] bytes of stack space, so you have a few extra for locals. How far did you reduce the stacks before strange symptoms appeared?
Andy
P.S. The 40 + 25 was based on a 160 byte stack and some room for local variables. We should update our learn site examples, probably to 176/4 + some number/4.
Andy,
I'm confused (a little more than usual). Isn't "unsigned int stack[40 + 25];" equal to the size of 65 longs = 40*4 + 25*4 = 160 + 100 bytes = 260 bytes?
But to summarize, I think that the minimum stack size declaration would be "unsigned int stack[44 + S];" which gives 176 bytes + 4*S, where S is based on "...space needed for local variables, parameters, and return address in the longest call chain that could ever be active."
The phrase in quotes is taken from ersmith's response to a question I had asked regarding how to calculate needed stack space in the thread at the link below.
http://forums.parallax.com/showthread.php/152866-In-C-how-do-you-calculate-stack_size-for-cogstart
Comments requested to help reduce confusion.
Thanks
Tom