aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/dlfcn_test.cpp4
-rw-r--r--tests/pthread_test.cpp86
2 files changed, 87 insertions, 3 deletions
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index c2c9286f6..457fcd5c0 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -188,10 +188,8 @@ TEST(dlfcn, dladdr) {
// 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 5328e48cf..5f74e388d 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 @@ TEST(pthread, pthread_mutex_timedlock) {
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);
+}