开发者

pthread_create fails with ENOMEM on low free memory scenario

开发者 https://www.devze.com 2023-03-30 10:17 出处:网络
I have a SH4 board, here are the specs... uname -a Linux LINUX7109 2.6.23.17_stm23_A18B-HMP_7109-STSDK #1 PREEMPT Fri Aug 6 16:08:19 ART 2010

I have a SH4 board, here are the specs...

uname -a
Linux LINUX7109 2.6.23.17_stm23_A18B-HMP_7109-STSDK #1 PREEMPT Fri Aug 6 16:08:19 ART 2010
sh4 unknown

and suppose I have eaten pretty much all the memory, and have only 9 MB left.

free
 total       used       free     shared    buffers     cached
Mem:         48072      42276       5796          0        172       3264
-/+ buffers/cache:      38840       9232
Swap:            0          0          0

Now, when I try to launch a single thread with default stack size (8 MB) the pthread_create fails with ENOMEM. If I strace my test code, I can see that the function that is failing is mmap:

old_mmap(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC,                       
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

However, when I set the stack size to a lower value using ulimit -s:

ulimit -s 7500

I can now l开发者_StackOverflow中文版aunch 10 threads. Each thread does not allocate anything, so it is only consuming the minimum overhead (aprox. 8 kb per thread, right?).

So, my question is:

Knowing that mmap doesnt actually consume the memory, Why is pthread_create() (or mmap) failing when memory available is below the thread stack size ?


The VM setting /proc/sys/vm/overcommit_memory (aka. sysctl vm.overcommit_memory) controls whether Linux is willing to hand out more address space than the combined RAM+swap of the machine. (Of course, if you actually try to access that much memory, something will crash. Try a search on "linux oom-killer"...)

The default for this setting is 0. I am going to speculate that someone set it to something else on your system.


Under glibc, the default stack size for threads is 2-10 megabytes (often 8). You should use pthread_attr_setstacksize and call pthread_create with the resulting attributes object to request a thread with a smaller stack.


mmap consume address space.

Pointers have to uniquely identify a piece of "memory" (including mmap file) in memory.

32-bit pointer can only address 2/3GB memory (32bit = 2^32 = 4GB. But some address space is reserved by kernel). This address space is limited.

All threads in the process share the same address space, but different process have separate address spaces.


This is the operating system's only chance to fail the operation gracefully. If the implementation allows this operation to succeed, it could run out of memory during an operation that it cannot return a failure code for, such as the stack growing. The operating system prefers to let an operation fail gracefully than risk having to kill a completely innocent process.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号