4

A few weeks back I had an issue with a Python script resetting my Amiga on execution. Someone suggested to change stack size in startup-sequence to 4096. I just read that it can be set up to 2500000.

http://www.mattowen.co.uk/amiga/amiga-os-command-reference-help/stack.html

It also says it may cause unintended system or application behaviour. What is its significance and how it is effected in layman's terms, please?

Shouldn't apps and system have functionality to adjust it for the best performance at any given time?

3
  • 1
    Make it too small and the app may crash with insufficient stack space. Make it too large and the app may crash with insufficient code+data space. "Adjusting" at run time may not be possible by simple expansion; adjusting by copying may be expensive. No free lunches in programming. May 16, 2021 at 15:09
  • 2
    It is generally impossible to relocate a stack while a program is running. Variables on the stack may contain the addresses of other variables on the stack, but there's no way for the OS to know that, or where they are. May 19, 2021 at 13:51
  • You couldn't really relocate the whole stack, no. But you could allocate a new stack at the start of a function call, if there's no space left. When you return from the function, free the stack and switch back to the original. Jun 21, 2021 at 15:36

1 Answer 1

8

What is its significance and how it is effected in layman's terms, please?

(not sure about the "layman's term" part)

On the Amiga (and on a lot of other systems including modern ones), stack size is the number of bytes that the operating system reserves for "automatic" memory at program startup and places the stack pointer (A7/SP register) at the top of that reserved zone. There can be only one stack by process/task.

Now, if you have an assembly program, the stack is mostly going to be used for:

  • storing return address when the program calls a subroutine
  • storing registers at start of subroutines to preserve them so the caller of the subroutine doesn't get them trashed (unless specified)

When using compiled programs (C mainly), the stack has a more extensive usage.

  • same as above but also:
  • allocating memory for local variables, so the routines can be recursive/reentrant (call themselves/be called from several processes concurrently)
  • parameter passing (assembly programs usually use registers, compilers use stack unless specially directives are given)

The compiler doesn't know the caller context so it "plays safe" and saves a lot of stuff. In assembly programs (generally hand written) the coder uses a lot of global variables because they know that it cannot be called recursively.

That stack management explains why compiled programs generally use more stack than assembly programs.

Native, old C/BCPL/assembly applications try not to "abuse" the stack so they can usually run with 4000 bytes (the default stack for the shell), and sometimes 8000, but not much more. The compilers are also Amiga-specific and use registers a lot more.

Ported applications (or complex applications) like Python use a lot more stack, first because they're big, and second because most of the time gcc was used to build them because Manx/Aztec-C or SAS wasn't compatible enough. Python is probably one of them, being very demanding in the compiler area.

And the old versions of Amiga GCC weren't very good at optimizing (which isn't the case of the new GCC 10)

Shouldn't apps and system have functionality to adjust it for the best performance at any given time?

Old Kickstart versions didn't have a dedicated routine to "swap the stack" (of course it can be done manually in assembly). Post kick 1.3 OS have the StackSwap function that does exactly this: it allocates some stack and replaces the shell stack by a bigger one. But it has to be done at startup. So a C program could crash if this was called mid-program or even at the start of the main program, because you can't control the startup (some linkers may have an option to increase the stack size in their crt0.o startup though.

That is a specific Amiga routine, so a ported program may not do that, and require that the stack is expanded before starting the program by using the stack command.

But the "at any given time" is a little more problematic. Stack cannot be easily moved when the program is running, as all the callers and the stack itself may have references to stack addresses (LINK instruction for instance).

And the OS doesn't use virtual memory/translation tables for programs, so we can't fool a program by using address translation. Not yet :)

Size can be reallocated at runtime (using the same base location) but it can also fail if the system cannot find a contiguous bigger block (even if there is plenty of memory somewhere else)

As a conclusion, Python must have been ported with a compiler that doesn't support stack reallocation or stack reallocation options weren't used in link options: you have to use

stack 100000

in the shell you're using to run the program or it will crash almost instantly by writing to memory it doesn't own. Increase if problems still persist.

(note that Windows executables headers carry the stack size information, and there's no stack command, but Linux/Unix still have a stack equivalent (ulimit) so Amiga looks more like Unix than Windows on that aspect)

2
  • 1
    There's still a big difference between linux/unix/whatsoever stacks and amiga stack. When former programs run out of their current stack, new virtual memory page is allocated by OS (or the program is artificially killed once it past stack limit). For amiga, nobody checks that (AmigaOS is not using benefits of virtual memory) and the programs just ends up using non-allocated memory, corrupting other programs memory, OS, etc.
    – lvd
    May 16, 2021 at 18:23
  • 1
    You're right. I have explained the lack of virtual memory usage on AmigaOS in my post May 16, 2021 at 18:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .