Merge "Fix pthread_getattr_np for the main thread."
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 00be4ae..70cc8eb 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -53,7 +53,6 @@
arch-arm/bionic/atomics_arm.c \
arch-arm/bionic/__bionic_clone.S \
arch-arm/bionic/_exit_with_stack_teardown.S \
- arch-arm/bionic/__get_sp.S \
arch-arm/bionic/libgcc_compat.c \
arch-arm/bionic/memcmp.S \
arch-arm/bionic/_setjmp.S \
diff --git a/libc/arch-arm/bionic/__get_sp.S b/libc/arch-arm/bionic/__get_sp.S
deleted file mode 100644
index 9ae6f24..0000000
--- a/libc/arch-arm/bionic/__get_sp.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
- mov r0, sp
- bx lr
-END(__get_sp)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index ed991ce..6c4f6a6 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -29,7 +29,6 @@
libc_bionic_src_files_arm64 := \
arch-arm64/bionic/__bionic_clone.S \
arch-arm64/bionic/_exit_with_stack_teardown.S \
- arch-arm64/bionic/__get_sp.S \
arch-arm64/bionic/__rt_sigreturn.S \
arch-arm64/bionic/_setjmp.S \
arch-arm64/bionic/setjmp.S \
diff --git a/libc/arch-arm64/bionic/__get_sp.S b/libc/arch-arm64/bionic/__get_sp.S
deleted file mode 100644
index d5e88e9..0000000
--- a/libc/arch-arm64/bionic/__get_sp.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
- mov x0, sp
- ret
-END(__get_sp)
diff --git a/libc/arch-mips/bionic/__get_sp.S b/libc/arch-mips/bionic/__get_sp.S
deleted file mode 100644
index 5f5d32e..0000000
--- a/libc/arch-mips/bionic/__get_sp.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
- move v0, sp
- j ra
-END(__get_sp)
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index 8e415f9..31a1f32 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -54,7 +54,6 @@
arch-mips/bionic/bzero.S \
arch-mips/bionic/cacheflush.cpp \
arch-mips/bionic/_exit_with_stack_teardown.S \
- arch-mips/bionic/__get_sp.S \
arch-mips/bionic/_setjmp.S \
arch-mips/bionic/setjmp.S \
arch-mips/bionic/sigsetjmp.S \
diff --git a/libc/arch-mips64/bionic/__get_sp.S b/libc/arch-mips64/bionic/__get_sp.S
deleted file mode 100644
index 5f5d32e..0000000
--- a/libc/arch-mips64/bionic/__get_sp.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
- move v0, sp
- j ra
-END(__get_sp)
diff --git a/libc/arch-x86/bionic/__get_sp.S b/libc/arch-x86/bionic/__get_sp.S
deleted file mode 100644
index aea6ac6..0000000
--- a/libc/arch-x86/bionic/__get_sp.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
- mov %esp, %eax
- ret
-END(__get_sp)
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 019dc8e..a141548 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -25,7 +25,6 @@
libc_bionic_src_files_x86 += \
arch-x86/bionic/__bionic_clone.S \
arch-x86/bionic/_exit_with_stack_teardown.S \
- arch-x86/bionic/__get_sp.S \
arch-x86/bionic/_setjmp.S \
arch-x86/bionic/setjmp.S \
arch-x86/bionic/__set_tls.c \
diff --git a/libc/arch-x86_64/bionic/__get_sp.S b/libc/arch-x86_64/bionic/__get_sp.S
deleted file mode 100644
index 49a2406..0000000
--- a/libc/arch-x86_64/bionic/__get_sp.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-ENTRY_PRIVATE(__get_sp)
- mov %rsp, %rax
- ret
-END(__get_sp)
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 7887c51..b001b5e 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -30,7 +30,6 @@
libc_bionic_src_files_x86_64 := \
arch-x86_64/bionic/__bionic_clone.S \
arch-x86_64/bionic/_exit_with_stack_teardown.S \
- arch-x86_64/bionic/__get_sp.S \
arch-x86_64/bionic/__rt_sigreturn.S \
arch-x86_64/bionic/_setjmp.S \
arch-x86_64/bionic/setjmp.S \
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index ff9940e..2a6a03b 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -36,7 +36,6 @@
#include <stdlib.h>
#include <sys/auxv.h>
#include <sys/time.h>
-#include <sys/resource.h>
#include <unistd.h>
#include "private/bionic_auxv.h"
@@ -46,7 +45,6 @@
#include "pthread_internal.h"
extern "C" abort_msg_t** __abort_message_ptr;
-extern "C" uintptr_t __get_sp(void);
extern "C" int __system_properties_init(void);
extern "C" int __set_tls(void* ptr);
extern "C" int __set_tid_address(int* tid_address);
@@ -62,17 +60,6 @@
// Declared in "private/bionic_ssp.h".
uintptr_t __stack_chk_guard = 0;
-static size_t get_main_thread_stack_size() {
- rlimit stack_limit;
- int rlimit_result = getrlimit(RLIMIT_STACK, &stack_limit);
- if ((rlimit_result == 0) &&
- (stack_limit.rlim_cur != RLIM_INFINITY) &&
- (stack_limit.rlim_cur > PTHREAD_STACK_MIN)) {
- return (stack_limit.rlim_cur & ~(PAGE_SIZE - 1));
- }
- return PTHREAD_STACK_SIZE_DEFAULT;
-}
-
/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
* in memory. Beware: all writes to libc globals from this function will
* apply to linker-private copies and will not be visible from libc later on.
@@ -96,16 +83,15 @@
main_thread.tid = __set_tid_address(&main_thread.tid);
main_thread.set_cached_pid(main_thread.tid);
- // Work out the extent of the main thread's stack.
- uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
- size_t stack_size = get_main_thread_stack_size();
- void* stack_bottom = reinterpret_cast<void*>(stack_top - stack_size);
-
// We don't want to free the main thread's stack even when the main thread exits
// because things like environment variables with global scope live on it.
+ // We also can't free the pthread_internal_t itself, since that lives on the main
+ // thread's stack rather than on the heap.
pthread_attr_init(&main_thread.attr);
- pthread_attr_setstack(&main_thread.attr, stack_bottom, stack_size);
main_thread.attr.flags = PTHREAD_ATTR_FLAG_USER_ALLOCATED_STACK | PTHREAD_ATTR_FLAG_MAIN_THREAD;
+ main_thread.attr.guard_size = 0; // The main thread has no guard page.
+ main_thread.attr.stack_size = 0; // User code should never see this; we'll compute it when asked.
+ // TODO: the main thread's sched_policy and sched_priority need to be queried.
__init_thread(&main_thread, false);
__init_tls(&main_thread);
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index e1cd853..8df3bff 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -28,6 +28,13 @@
#include <pthread.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <sys/resource.h>
+
+#include "private/bionic_string_utils.h"
+#include "private/ErrnoRestorer.h"
+#include "private/libc_logging.h"
#include "pthread_internal.h"
int pthread_attr_init(pthread_attr_t* attr) {
@@ -90,8 +97,8 @@
}
int pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stack_size) {
- *stack_size = attr->stack_size;
- return 0;
+ void* unused;
+ return pthread_attr_getstack(attr, &unused, stack_size);
}
int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_size) {
@@ -106,7 +113,42 @@
return 0;
}
+static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
+ ErrnoRestorer errno_restorer;
+
+ // It doesn't matter which thread we are; we're just looking for "[stack]".
+ FILE* fp = fopen("/proc/self/maps", "re");
+ if (fp == NULL) {
+ return errno;
+ }
+ char line[BUFSIZ];
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if (ends_with(line, " [stack]\n")) {
+ uintptr_t lo, hi;
+ if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
+ *stack_base = reinterpret_cast<void*>(lo);
+ *stack_size = hi - lo;
+
+ // Does our current RLIMIT_STACK mean we won't actually get everything /proc/maps promises?
+ rlimit stack_limit;
+ if (getrlimit(RLIMIT_STACK, &stack_limit) != -1) {
+ if (*stack_size > stack_limit.rlim_cur) {
+ *stack_size = stack_limit.rlim_cur;
+ }
+ }
+
+ fclose(fp);
+ return 0;
+ }
+ }
+ }
+ __libc_fatal("No [stack] line found in /proc/self/maps!");
+}
+
int pthread_attr_getstack(const pthread_attr_t* attr, void** stack_base, size_t* stack_size) {
+ if ((attr->flags & PTHREAD_ATTR_FLAG_MAIN_THREAD) != 0) {
+ return __pthread_attr_getstack_main_thread(stack_base, stack_size);
+ }
*stack_base = attr->stack_base;
*stack_size = attr->stack_size;
return 0;
@@ -122,9 +164,8 @@
return 0;
}
-int pthread_getattr_np(pthread_t thid, pthread_attr_t* attr) {
- pthread_internal_t* thread = (pthread_internal_t*) thid;
- *attr = thread->attr;
+int pthread_getattr_np(pthread_t t, pthread_attr_t* attr) {
+ *attr = reinterpret_cast<pthread_internal_t*>(t)->attr;
return 0;
}
diff --git a/libc/private/bionic_string_utils.h b/libc/private/bionic_string_utils.h
new file mode 100644
index 0000000..ab0eccf
--- /dev/null
+++ b/libc/private/bionic_string_utils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BIONIC_STRING_UTILS_H_
+#define _BIONIC_STRING_UTILS_H_
+
+#include <string.h>
+
+static inline bool ends_with(const char* s1, const char* s2) {
+ size_t s1_length = strlen(s1);
+ size_t s2_length = strlen(s2);
+ if (s2_length > s1_length) {
+ return false;
+ }
+ return memcmp(s1 + (s1_length - s2_length), s2, s2_length) == 0;
+}
+
+#endif // _BIONIC_STRING_UTILS_H_
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index a731748..6de38c8 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -231,10 +231,8 @@
// Look in /proc/pid/maps to find out what address we were loaded at.
// TODO: factor /proc/pid/maps parsing out into a class and reuse all over bionic.
void* base_address = NULL;
- char path[PATH_MAX];
- snprintf(path, sizeof(path), "/proc/%d/maps", getpid());
char line[BUFSIZ];
- FILE* fp = fopen(path, "r");
+ FILE* fp = fopen("/proc/self/maps", "r");
ASSERT_TRUE(fp != NULL);
while (fgets(line, sizeof(line), fp) != NULL) {
uintptr_t start = strtoul(line, 0, 16);
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 5328e48..5f74e38 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -23,6 +23,7 @@
#include <pthread.h>
#include <signal.h>
#include <sys/mman.h>
+#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
@@ -816,3 +817,88 @@
ASSERT_EQ(0, pthread_mutex_unlock(&m));
ASSERT_EQ(0, pthread_mutex_destroy(&m));
}
+
+TEST(pthread, pthread_attr_getstack__main_thread) {
+ // This test is only meaningful for the main thread, so make sure we're running on it!
+ ASSERT_EQ(getpid(), syscall(__NR_gettid));
+
+ // Get the main thread's attributes.
+ pthread_attr_t attributes;
+ ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes));
+
+ // Check that we correctly report that the main thread has no guard page.
+ size_t guard_size;
+ ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
+ ASSERT_EQ(0U, guard_size); // The main thread has no guard page.
+
+ // Get the stack base and the stack size (both ways).
+ void* stack_base;
+ size_t stack_size;
+ ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size));
+ size_t stack_size2;
+ ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2));
+
+ // The two methods of asking for the stack size should agree.
+ EXPECT_EQ(stack_size, stack_size2);
+
+ // What does /proc/self/maps' [stack] line say?
+ void* maps_stack_base = NULL;
+ size_t maps_stack_size = 0;
+ FILE* fp = fopen("/proc/self/maps", "r");
+ ASSERT_TRUE(fp != NULL);
+ char line[BUFSIZ];
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ uintptr_t lo, hi;
+ char name[10];
+ sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d %10s", &lo, &hi, name);
+ if (strcmp(name, "[stack]") == 0) {
+ maps_stack_base = reinterpret_cast<void*>(lo);
+ maps_stack_size = hi - lo;
+ break;
+ }
+ }
+ fclose(fp);
+
+#if defined(__BIONIC__)
+ // bionic thinks that the stack base and size should correspond to the mapped region.
+ EXPECT_EQ(maps_stack_base, stack_base);
+ EXPECT_EQ(maps_stack_size, stack_size);
+#else
+ // glibc doesn't give the true extent for some reason.
+#endif
+
+ // Both bionic and glibc agree that the high address you can compute from the returned
+ // values should match what /proc/self/maps says.
+ void* stack_end = reinterpret_cast<uint8_t*>(stack_base) + stack_size;
+ void* maps_stack_end = reinterpret_cast<uint8_t*>(maps_stack_base) + maps_stack_size;
+ EXPECT_EQ(maps_stack_end, stack_end);
+
+ //
+ // What if the rlimit is smaller than the stack's current extent?
+ //
+ rlimit rl;
+ rl.rlim_cur = rl.rlim_max = 1024; // 1KiB. We know the stack must be at least a page already.
+ rl.rlim_max = RLIM_INFINITY;
+ ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+
+ ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes));
+ ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size));
+ ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2));
+
+ EXPECT_EQ(stack_size, stack_size2);
+ ASSERT_EQ(1024U, stack_size);
+
+ //
+ // What if the rlimit isn't a whole number of pages?
+ //
+ rl.rlim_cur = rl.rlim_max = 6666; // Not a whole number of pages.
+ rl.rlim_max = RLIM_INFINITY;
+ ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
+
+ ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attributes));
+ ASSERT_EQ(0, pthread_attr_getstack(&attributes, &stack_base, &stack_size));
+ ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size2));
+
+ EXPECT_EQ(stack_size, stack_size2);
+ ASSERT_EQ(6666U, stack_size);
+}