Fix pthread_getattr_np, pthread_attr_setguardsize, and pthread_attr_setstacksize.

pthread_getattr_np was reporting the values supplied to us, not the values we
actually used, which is kinda the whole point of pthread_getattr_np.

pthread_attr_setguardsize and pthread_attr_setstacksize were reporting EINVAL
for any size that wasn't a multiple of the system page size. This is
unnecessary. We can just round like POSIX suggests and glibc already does.

Also improve the error reporting for pthread_create failures.

Change-Id: I7ebc518628a8a1161ec72e111def911d500bba71
This commit is contained in:
Elliott Hughes
2013-07-15 14:51:07 -07:00
parent 59ed029b28
commit b95cf0d23a
3 changed files with 113 additions and 16 deletions

View File

@@ -17,6 +17,7 @@
#include <gtest/gtest.h>
#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <unistd.h>
@@ -339,3 +340,95 @@ TEST(pthread, pthread_join__multijoin) {
ASSERT_EQ(0, pthread_join(t2, &join_result));
ASSERT_EQ(0, reinterpret_cast<int>(join_result));
}
static void* GetActualGuardSizeFn(void* arg) {
pthread_attr_t attributes;
pthread_getattr_np(pthread_self(), &attributes);
pthread_attr_getguardsize(&attributes, reinterpret_cast<size_t*>(arg));
return NULL;
}
static size_t GetActualGuardSize(const pthread_attr_t& attributes) {
size_t result;
pthread_t t;
pthread_create(&t, &attributes, GetActualGuardSizeFn, &result);
void* join_result;
pthread_join(t, &join_result);
return result;
}
static void* GetActualStackSizeFn(void* arg) {
pthread_attr_t attributes;
pthread_getattr_np(pthread_self(), &attributes);
pthread_attr_getstacksize(&attributes, reinterpret_cast<size_t*>(arg));
return NULL;
}
static size_t GetActualStackSize(const pthread_attr_t& attributes) {
size_t result;
pthread_t t;
pthread_create(&t, &attributes, GetActualStackSizeFn, &result);
void* join_result;
pthread_join(t, &join_result);
return result;
}
TEST(pthread, pthread_attr_setguardsize) {
pthread_attr_t attributes;
ASSERT_EQ(0, pthread_attr_init(&attributes));
// Get the default guard size.
size_t default_guard_size;
ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &default_guard_size));
// No such thing as too small: will be rounded up to one page by pthread_create.
ASSERT_EQ(0, pthread_attr_setguardsize(&attributes, 128));
size_t guard_size;
ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
ASSERT_EQ(128U, guard_size);
ASSERT_EQ(4096U, GetActualGuardSize(attributes));
// Large enough and a multiple of the page size.
ASSERT_EQ(0, pthread_attr_setguardsize(&attributes, 32*1024));
ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
ASSERT_EQ(32*1024U, guard_size);
// Large enough but not a multiple of the page size; will be rounded up by pthread_create.
ASSERT_EQ(0, pthread_attr_setguardsize(&attributes, 32*1024 + 1));
ASSERT_EQ(0, pthread_attr_getguardsize(&attributes, &guard_size));
ASSERT_EQ(32*1024U + 1, guard_size);
}
TEST(pthread, pthread_attr_setstacksize) {
pthread_attr_t attributes;
ASSERT_EQ(0, pthread_attr_init(&attributes));
// Get the default stack size.
size_t default_stack_size;
ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &default_stack_size));
// Too small.
ASSERT_EQ(EINVAL, pthread_attr_setstacksize(&attributes, 128));
size_t stack_size;
ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size));
ASSERT_EQ(default_stack_size, stack_size);
ASSERT_GE(GetActualStackSize(attributes), default_stack_size);
// Large enough and a multiple of the page size.
ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, 32*1024));
ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size));
ASSERT_EQ(32*1024U, stack_size);
ASSERT_EQ(GetActualStackSize(attributes), 32*1024U);
// Large enough but not a multiple of the page size; will be rounded up by pthread_create.
ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, 32*1024 + 1));
ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size));
ASSERT_EQ(32*1024U + 1, stack_size);
#if __BIONIC__
// Bionic rounds up, which is what POSIX allows.
ASSERT_EQ(GetActualStackSize(attributes), (32 + 4)*1024U);
#else
// glibc rounds down, in violation of POSIX. They document this in their BUGS section.
ASSERT_EQ(GetActualStackSize(attributes), 32*1024U);
#endif
}