Default stack size for pthreads
As I understand, the default stack size for a pthread on Linux is 16K. I am getting strange results on my 64-bit Ubuntu install.
pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &stacksize); printf("Thread stack size = %d bytes \n", stacksize); Prints Thread stack size = 8388608 bytes
You’re thinking of 16k per thread kernel stacks. Totally separate issue from user-space stack memory. kernel stacks are tiny because they can’t be paged, or be lazy-allocated, and have to be contiguous pages in physical memory. elinux.org/Kernel_Small_Stacks. Having an extremely high number of total threads can be a problem for i386, where address-space is limited, especially with 8k stacks by default for 32-bit.
2 Answers 2
Actually, your virtual stack size is 8388608 bytes (8 MB). Of course, it’s natural to conclude that this can’t be right, because that’s a ridiculously large amount of memory for every thread to consume for its stack when 99% of the time a couple of KB is probably all they need.
The good news is that your thread only uses the amount of physical memory that it actually needs. This is one of the magical powers that your OS gets from using the hardware Memory Management Unit (MMU) in your processor. Here’s what happens:
- The OS allocates 8 MB of virtual memory for your stack by setting up the MMU’s page tables for your thread. This requires very little RAM to hold the page table entries only.
- When your thread runs and tries to access a virtual address on the stack that doesn’t have a physical page assigned to it yet, a hardware exception called a «page fault» is triggered by the MMU.
- The CPU core responds to the page fault exception by switching to a privileged execution mode (which has its own stack) and calling the page fault exception handler function inside the kernel.
- The kernel allocates a page of physical RAM to that virtual memory page and returns back to the user space thread.
The user space thread sees none of that work. From its point of view, it just uses the stack as if the memory was there all along. Meanwhile, the stack automatically grows (or doesn’t) to meet the thread’s needs.
The MMU is a key part of the hardware of today’s computer systems. In particular, it’s responsible for a lot of the «magic» in the system, so I highly recommend learning more about what the MMU does, and about virtual memory in general. Also, if your application is performance sensitive and deals with a significant amount of data, you should understand how the TLB (the MMU’s page table cache) works and how you can restructure your data or your algorithms to maximize your TLB hit rate.
Is there a limit of stack size of a process in linux
Is there a limit on the stack size of a process in Linux? Is it simply dependent on the RAM of the machine? I want to know this in order to limit the depth of recursive calls to a function.
that’s true, but it’s a good estimate. if you really wanted you could count the number of bits in use in temporary variables and method parameters and work it out exactly for a given function
4 Answers 4
The stack is normally limited by a resource limit. You can see what the default settings are on your installation using ulimit -a :
(this shows that mine is 8MB, which is huge).
If you remove or increase that limit, you still won’t be able to use all the RAM in the machine for the stack — the stack grows downward from a point near the top of your process’s address space, and at some point it will run into your code, heap or loaded libraries.
«at some point it will run into your code, heap or loaded libraries» I doubt whether that would be a problem on 64-bit systems such as Linux x86_64?
@SamWatkins: Right — this answer was written 5 years ago, and was in the context of 32 bit environments.
This is incorrect for i386 if its ABI is to be believed. In it, stack is located under everything else and can theoretically grow to a bit over 128MiB . In AMD64 ABI, it grows from under the 128GiB mark, just under shared libraries. So it can theoretically overwrite code/data, but only of the main program or its heap.
@ivan_pozdeev: Stack is last on Linux — check /proc/
The limit can be set by the admin.
There is probably a default which you cannot cross. If you have to worry about stack limits, I would say you need to rethink your design, perhaps write an iterative version?
Or just write a recursive version that uses a manually managed stack instead of the function call stack.
It largely depends what architecture you’re on (32 or 64-bit) and whether you’re multithreaded or not.
By default in a single threaded process, i.e. the main thread created by the OS at exec() time, your stack usually will grow until it hits something else in the address space. This means that it is generally possible, on a 32-bit machine, to have, say 1G of stack.
However, this is definitely NOT the case in a multithreaded 32-bit process. In multithreaded procesess, the stacks share address space and hence need to be allocated, so they typically get given a small amount of address space (e.g. 1M) so that many threads can be created without exhausting address space.
So in a multithreaded process, it’s small and finite, in a single threaded one, it’s basically until you hit something else in the address-space (which the default allocation mechanism tries to ensure doesn’t happen too soon).
In a 64-bit machine, of course there is a lot more address space to play with.
In any case you can always run out of virtual memory, in which case you’ll get a SIGBUS or SIGSEGV or something.
How to increase stack limit permanently without restarting
The ulimit method only works as long as I am logged in.
limits.conf will work after a restart.
Is there a possible way to increase the limit without restarting?
There must be a way to do this. The ulimit shell command doesn’t work for a user. And the current logged in user doesn’t have permission to alter their limit unless they are root.
4 Answers 4
What’s wrong with editing your .bashrc file to do a ulimit -s size every time you start a terminal session?
unfortunately that is not for me as a user, it is for the couchdb process, which crashes because a document in the DB is to big to fit in the stack.
@Simon: that means you’re currently restarting that process every time? How is that done? Can’t you splice the ulimit -s size in the scripts that control the restarts?
well, it is a subprocess of couchdb that crashes (couchjs). So all processes started by the user couchdb should have a bigger stack
If you want to do this programatically, you can use the setrlimit() function.
unfortunately I need to set the limit for couchdb, not for a program of my own. So setting it programatically is out of question
Linux (and POSIX compatible systems in general) inherit current process limits from existing processes when a new process is started (using fork() or exec() ). As a result, you would just need to change the limits for all existing processes that are already running on your system. The config files just define the values for the initial processes after the system has been booted and everything else inherits the current values of parent processes.
Why would you want to increase stack limit of everything? Do all your existing processes immediately require increased stack space for some reason?
If you actually need to change the limits of any given process after that process has already been started, you can do it with command prlimit which uses kernel interface int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlimit *old_limit) behind the scenes. It requires CAP_SYS_RESOURCE for many use cases so you often need to run that as root in practice.
Setting the default stack size on Linux globally for the program
So I’ve noticed that the default stack size for threads on linux is 8MB (if I’m wrong, PLEASE correct me), and, incidentally, 1MB on Windows. This is quite bad for my application, as on a 4-core processor that means 64 MB is space is used JUST for threads! The worst part is, I’m never using more than 100kb of stack per thread (I abuse the heap a LOT ;)). My solution right now is to limit the stack size of threads. However, I have no idea how to do this portably. Just for context, I’m using Boost.Thread for my threading needs. I’m okay with a little bit of #ifdef hell, but I’d like to know how to do it easily first. Basically, I want something like this (where windows_* is linked on windows builds, and posix_* is linked under linux builds)
// windows_stack_limiter.c int limit_stack_size() < // Windows impl. return 0; >// posix_stack_limiter.c int limit_stack_size() < // Linux impl. return 0; >// stack_limiter.cpp int limit_stack_size(); static volatile int placeholder = limit_stack_size();
How do I flesh out those functions? Or, alternatively, am I just doing this entirely wrong? Remember I have no control over the actual thread creation (no new params to CreateThread on Windows), as I’m using Boost.Thread.
It’s not as bad as you think. only address space is reserved, not actual RAM. So e.g. if you spawn 8 threads, and each thread actually uses 100kb of stack space, then you’ve only used up 800kb of RAM, not 8MB.