c164-1bj@cordelia.berkeley.edu (Jonathan Dubman) (10/26/87)
I have a speedy maze program I wrote in C that I want to send to Fred and post here, but it needs a large stack. Maximum resolution requires about 150K of stack space. (Massive recursion.) I don't want everybody who runs it without reading the docs first to crash their machine. Is it possible in a C program to know how much stack space I have? I can write a short assembly language program if necessary. Is it possible, if the stack is too small, to dynamically allocate stack space? Can I just allocate a big chunk of memory, reset the stack pointer to there, and deallocate it at the end, resetting the stack pointer to the original stack that never went away? The least I can do is say, "Reset your stack size and run me again.". If I run it from workbench, WB will allocate the stack of the proper size, provided the .info file is correct. CLI is the problem. *&Jonathan Dubman
bryce@hoser.berkeley.edu (Bryce Nesbitt) (10/26/87)
In article <4585@zen.berkeley.edu> c164-1bj@cordelia.berkeley.edu (Jonathan Dubman) writes: >I have a speedy maze program I wrote in C that I want to send to Fred and post >here, but it needs a large stack. Maximum resolution requires about 150K of >stack space. (Massive recursion.) I don't want everybody who runs it without >reading the docs first to crash their machine. > >Is it possible in a C program to know how much stack space I have? I >can write a short assembly language program if necessary. From C, simply get a pointer to your task with "FindTask(0L);" This returns a pointer to struct Task from the exec/tasks.h include file. tc_SPLower is the lower bound of the stack tc_SPupper is the upper bound +2. It would be thoretically possible to allocate a new stack and start to use it. This sounds somewhat dangerous, however. There is no official function set up to swap stacks (and the requisite Task structure fields). In the future, particuarly the resource tracked future, you could be asking for problems. At least you know it is safe to: >say, "Reset your stack size and run me again.". Anyone starting it from Workbench will only get that message if they played with the icon. Anyone starting from the CLI when an icon exists can probably figure out how to type "stack 150000". Sounds like your program should also leave the automatic stack checking code in. This will pop a "Stack overflow" requester if a function call will overflow. You *must*, however, catch the exit and do a proper cleanup. |\ /| . Ack! (NAK, SOH, EOT) {o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (") U "Here. This'll shoot the lips off a cockroch" -Freedom Fighter
ali@rocky.STANFORD.EDU (Ali Ozer) (10/26/87)
In article <21440@ucbvax.BERKELEY.EDU> Bryce Nesbitt writes: >In article <4585@zen.berkeley.edu> Jonathan Dubman writes: >>I have a speedy maze program ... >>it needs a large stack. Maximum resolution requires about 150K of >>stack space. (Massive recursion.) ... >> "Reset your stack size and run me again.". > >Anyone starting it from Workbench will only get that message if they played >with the icon. Anyone starting from the CLI when an icon exists can probably >figure out how to type "stack 150000". You might also try launching a subprocess with the correct stack size. In fact, you might be able to determine the necessary stack size from the resolution and launch the main recursize code with the stack size set "just right." If you can prevent the recursive section of the code from doing any DOS stuff (like file I/O), then you can make it a task, and include it as a function in your program. Then, to launch it you would use CreateTask(), which takes a stack size and a starting address as an argument. If it somehow fails, it could send back a message or a signal to the parent task. This structure could also make it possible to abort the computations more gracefully, perhaps, if you had the parent waiting on both the child's and Intuition's signals. If the child did no memory allocations of its own, then the parent could kill it will a single RemTask(), >poof<. Ali Ozer, ali@rocky.stanford.edu
dillon@CORY.BERKELEY.EDU (Matt Dillon) (10/27/87)
>I have a speedy maze program I wrote in C that I want to send to Fred and post >here, but it needs a large stack. Maximum resolution requires about 150K of >stack space. (Massive recursion.) I don't want everybody who runs it without >reading the docs first to crash their machine. A program which uses that much stack should not assume it will be given it on startup. All you really have to do is allocate enough memory for your stack, then set your SP to the end of it. Be sure to set the SP back to the original stack and free the allocated memory before exiting. Remember that at any time an interrupt can come in and push+pop stuff on the stack. I'd say write a small assembly routine which 'switches' stacks... massiverecursion: (allocate new stack) move.l sp,A0 move.l EndofNewstack,sp move.l A0,-(sp) jsr routine that requires massive recursion move.l (sp)+,sp (deallocate new stack) rts -Matt
ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (10/27/87)
In article <21440@ucbvax.BERKELEY.EDU> bryce@hoser.berkeley.edu (Bryce Nesbitt) writes: >In article <4585@zen.berkeley.edu> c164-1bj@cordelia.berkeley.edu (Jonathan Dubman) writes: >>Is it possible in a C program to know how much stack space I have? I >>can write a short assembly language program if necessary. > >From C, simply get a pointer to your task with "FindTask(0L);" This returns >a pointer to struct Task from the exec/tasks.h include file. tc_SPLower is >the lower bound of the stack tc_SPupper is the upper bound +2. > Gee Byrce, I'm surprised you missed this. Yes, there are tc_SP{Upper,Lower} fields in the task control block, but these are not what DOS uses for the stack. That's stored in your process structure (an extension of Exec's task structure). To find out the size of the stack DOS allocated for you when your program was started, you say: stacksize = ((struct Process *) FindTask (0L)) -> pr_StackSize; I found this out a while ago when trying to debug a program. For some strange reason I decided to check to see if the stack had a sane value. Much to my consternation, I found the stack pointer pointing completely outside the range specified by tc_SP{Upper,Lower}. It suddenly dawned on me that DOS was probably screwing this up, too, and poked around in the process structure. Hope this helps. (Hope I'm right about it, too!) _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Leo L. Schwab -- The Guy in The Cape ihnp4!ptsfa -\ \_ -_ Recumbent Bikes: dual ---> !{well,unicom}!ewhac O----^o The Only Way To Fly. hplabs / (pronounced "AE-wack") "Although there are technical differences between the quality of images created on the Amiga and on our system, we feel that viewers could be misled to believe otherwise, even with your disclaimers to the contrary." -- Ralph J. Guggenheim, Pixar
bryce@hoser.berkeley.edu.UUCP (10/28/87)
ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes: >bryce@hoser.berkeley.edu (Bryce Nesbitt) writes: > >> From C, simply get a pointer to your task with "FindTask(0L);" This returns >> a pointer to struct Task from the exec/tasks.h include file. tc_SPLower is >> the lower bound of the stack tc_SPupper is the upper bound +2. > > Gee Byrce, I'm surprised you missed this. > Yes, there are tc_SP{Upper,Lower} fields in the task control block, > but these are not what DOS uses for the stack... > ...To find out the size of the stack DOS allocated for you when your > program was started, you say: > stacksize = ((struct Process *) FindTask (0L)) -> pr_StackSize; Guess what Leo? We are _both_ wrong! So much for Samaritanism. Actually we are both right. Got that one figured out yet? There is a not_so_subtle difference between the Workbench and the CLI. pr_StackSize GIVES THE WRONG ANSWER!! Better yet, pr_StackSize and cli_DefaultStack, both declared as longs, are stored in different units! I was so confused about the issue Leo brought up that only a sample program saved me. Try it from Workbench, "run" and direct CLI. Set a new stack number before each trial. Take note of just who's stack pr_StackSize represents (Hint: It's not always yours). Take note that my solution will not work either. (Also be on the lookout for a certain piece of commercial Amiga software that, when run from the CLI, seems to use 8,000 more bytes than it needs to... then complain to the programmer. :-) /* * stack_test.c 27-Oct-87. Bryce Nesbitt * * Created so I could have a clue. Just how is that stacksize stuff saved? * * This program points out that CLI started programs will have the stacksize * from cli_DefaultStack. This size is also saved at 4(a7) at startup... but * that is not available to a C program. THE NORMAL TASK STRUCTURE REFERS TO * THE CLI PROCESSES' STACK... NOT THE ONE YOU ARE RUNNING ON! * * From the Workbench there is no cli_DefaultStack. Here the normal task * structures take hold. * */ #include "exec/types.h" #include "exec/tasks.h" #include "libraries/dosextens.h" #include "stdio.h" struct Process *FindTask(); main() { register struct Process *Process; register FILE *Handle; struct CommandLineInterface *CLI; if (!(Handle=fopen("con:0/11/250/128/Stack Window","a"))) exit(20); /* "a" is used so the window won't flicker */ Process=FindTask(0L); if (CLI=(struct CommandLineInterface *)(Process->pr_CLI<<2)) { if (CLI->cli_Background) fprintf(Handle,"Background"); else fprintf(Handle,"Foreground"); fprintf(Handle," CLI #%ld\n\n",Process->pr_TaskNum); fprintf(Handle,"cli_DefaultStack is: %ld\n\n",\ CLI->cli_DefaultStack<<2); } else { fprintf(Handle,"This is not a CLI process\n"); fprintf(Handle,"Stack is %ld\n\n",Process->pr_StackSize); } /* Other useless information (we already know the stack size) */ fprintf(Handle,"pr_StackSize %ld\n",Process->pr_StackSize); fprintf(Handle,"pr_StackBase $%lx\n\n",Process->pr_StackBase<<2); fprintf(Handle,"tc_SPLower $%lx\n",Process->pr_Task.tc_SPLower); fprintf(Handle,"tc_SPUpper $%lx\n",Process->pr_Task.tc_SPUpper); fprintf(Handle,"Upper-Lower %ld\n\n", (long)Process->pr_Task.tc_SPUpper-\ (long)Process->pr_Task.tc_SPLower); fprintf(Handle,"tc_SPReg $%lx\n",Process->pr_Task.tc_SPReg); Delay(75L); /* Be quick :-) */ fprintf(Handle,"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); /* Dramatic exit :-) */ fclose(Handle); } |\ /| . Ack! (NAK, SOH, EOT) {o O} . bryce@hoser.berkeley.EDU -or- ucbvax!hoser!bryce (") U "I never said you _could_, I merely said you _should_." -Humpty Dumpty
karl@sugar.UUCP (11/01/87)
In article <4585@zen.berkeley.edu>, c164-1bj@cordelia.berkeley.edu (Jonathan Dubman) writes: > .... it needs a large stack. Maximum resolution requires about 150K of > stack space. (Massive recursion.) I don't want everybody who runs it without > reading the docs first to crash their machine. Most of the responses so far have been hacks for increasing the amount of stack space. Why not malloc the space and handle your recursive data yourself, managing your data frames explicitly by incrementing and decrementing an index on entry and exit of your recursive routine? (With this method, by the way, one can write recursive programs in BASIC.) Note that I'm assuming you're putting pretty much stuff on the stack each pass. If you needed 150K depth for a little frame but super deep recursion, this wouldn't gain much, if anything. --