-
Notifications
You must be signed in to change notification settings - Fork 51
Description
在测试LoongArch glibc的libcbench测例时发现爆内存,经检查是mmap映射了过多的虚拟地址空间所致,内核打印的调试信息中包含数条以下调试信息:
[sys_mmap] addr:0x0, length:0x801000, prot:MmapProt(0x0), flags:MmapFlags(MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK), fd:18446744073709551615, offset:0x0
阅读位于 libc-bench/pthread.c:35的源码可知,该测试项创建了2500个线程,并意图为每个线程分配16384字节大小的栈空间。pthread_create使用mmap系统调用分配线程栈,在用户为attr设置了栈大小stacksize的情况下,mmap系统调用的length参数理应为stacksize+guardsize,这与实际情况不符。
阅读glibc代码发现,在测例调用pthread_attr_setstacksize时,glibc设置attr中的stacksize字段前,会检查传入的stacksize是否大于等于PTHREAD_STACK_MIN(参见nptl/pthread_attr_setstacksize.c),这个值在LA架构下等于131072。不满足时不修改attr->stacksize字段并返回错误码。在线程创建时,attr->stacksize仍为缺省值,故glibc使用默认的__default_pthread_attr.internal.stacksize,这个值在__pthread_early_init中被初始化为rlimit_stack,这个值在我们内核的设计中是8MB。我们尝试修改了prlimit64系统调用的返回值,观察到mmap分配的内核栈大小也改变了,验证了这一猜想。
对libc-bench进行反汇编,也能验证这个猜想。以下是pthread_attr_setstacksize的汇编代码:
000000012001a954 <__pthread_attr_setstacksize>:
check_stacksize_attr():
/home/airxs/user/gnu/build-cross-tools-hf/glibc-2.38/nptl/../sysdeps/nptl/pthreadP.h:707
12001a954: 1400040c lu12i.w $t0, 32
12001a958: 6c000cac bgeu $a1, $t0, 12 # 12001a964 <__pthread_attr_setstacksize+0x10>
__pthread_attr_setstacksize():
/home/airxs/user/gnu/build-cross-tools-hf/glibc-2.38/nptl/pthread_attr_setstacksize.c:38
12001a95c: 02805804 li.w $a0, 22
/home/airxs/user/gnu/build-cross-tools-hf/glibc-2.38/nptl/pthread_attr_setstacksize.c:43
12001a960: 4c000020 ret
/home/airxs/user/gnu/build-cross-tools-hf/glibc-2.38/nptl/pthread_attr_setstacksize.c:40
12001a964: 29c08085 st.d $a1, $a0, 32
/home/airxs/user/gnu/build-cross-tools-hf/glibc-2.38/nptl/pthread_attr_setstacksize.c:42
12001a968: 00150004 move $a0, $zero
12001a96c: 4c000020 ret
第一行lu12i.w $t0, 32,便是glibc中LA架构的PTHREAD_STACK_MIN值131072。
这个问题可能导致大多数队伍使用正常手段无法通过LA架构glibc的libc-bench测例,希望老师能修复这个问题。