← Back to context

Comment by simonask

16 hours ago

The amount of stack you pay for on a thread is proportional to the maximum depth that the stack ever reached on the thread. Operating systems can grow the amount of real memory allocated to a thread, but never shrink it.

It’s a programming model that has some really risky drawbacks.

> Operating systems can grow the amount of real memory allocated to a thread, but never shrink it.

Operating systems can shrink the memory usage of a stack.

  madvise(page, size, MADV_DONTNEED);

Leaves the memory mapping intact but the kernel frees underlying resources. Subsequent accesses get either new zero pages or the original file's pages.

Linux also supports mremap, which is essentially a kernel version of realloc. Supports growing and shrinking memory mappings.

  stack = mremap(stack, old_size, old_size / 2, MREMAP_MAYMOVE, 0);

Whether existing systems make use of this is another matter entirely. My language uses mremap for growth and shrinkage of stacks. C programs can't do it because pointers to stack allocated objects may exist.

  • > C programs can't do it because pointers to stack allocated objects may exist.

    They sure shouldn't exist to the unused region of the stack though; if they do, that's a bug (because anything could claim that memory now). You should be free and clear to release stack pages past your current stack pointer.

  • Stack memory is never unmapped until the thread terminates as far as I know. I don’t know of any kernel that does this, for precisely the reason you arrive at by the very last sentence.