Stack is a sticky situation. The way it's implemented an application more or less has a fixed stack size (typically 1 MB?) which is not free to be used by anything else, even when most of it is not in use, and neither can it expand its stack size when it runs out.
I understand why it was implemented this way -- to make pushing to and popping from the stack efficient. But I think it could be improved with no loss to performance. Just implement in the CPU architecture a check for each push and pop. If the push would go beyond the stack segment, raise an interrupt that calls an OS function that can then allocate more pages to the stack segment, then continue operation of that thread. And if a pop recedes by a certain amount, you can also raise an interrupt that calls an OS function that may free a page of memory if it's at least x bytes behind the stack pointer. This would obviously require a stack pointer that pushes up and pops down, as opposed the other way around which is only the case anachronistically anyway due to the old programs that put the stack and the other segments in the same memory space.
Realistically, you'd need backward compatibility with software, so you'd have to emulate the backwards stack pointer by starting it off at 0xFFFFFFF on 32-bit systems or 0xFFFFFFFFFFFF on 64-bit even though the memory addressed can't necessarily actually go down to zero without allocating more or raising an exception.
The OS could even start swapping out the uppermost stack data to disk upon interrupt if the pointer goes down too far to allocate more memory, thus giving us, say.. 300 GB of stack space, if'n we ever really need it. And it woudln't have to impinge on speed, because it only does this stuff when there would have been a stack overflow otherwise anyway.