diff options
author | Yabin Cui <yabinc@google.com> | 2015-03-16 22:46:42 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2015-03-20 17:42:09 -0700 |
commit | b58457221364eaad039c2c49a42626b725e980d5 (patch) | |
tree | a7a8d9b3de7c34bda99153ebae330b6d180b112e | |
parent | 4149dc944bbe3c5f1c14fc998106975e68bdd6bf (diff) | |
download | android_bionic-b58457221364eaad039c2c49a42626b725e980d5.tar.gz android_bionic-b58457221364eaad039c2c49a42626b725e980d5.tar.bz2 android_bionic-b58457221364eaad039c2c49a42626b725e980d5.zip |
Add test for pthread types alignment check.
Bug: 19249079
Change-Id: I83c4f0d11ec5d82a346ae0057d02a92bb1d519e8
-rw-r--r-- | libc/bionic/pthread_cond.cpp | 10 | ||||
-rw-r--r-- | libc/bionic/pthread_rwlock.cpp | 10 | ||||
-rw-r--r-- | libc/include/pthread.h | 4 | ||||
-rw-r--r-- | tests/pthread_test.cpp | 58 |
4 files changed, 76 insertions, 6 deletions
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp index 95a433c11..4a69da558 100644 --- a/libc/bionic/pthread_cond.cpp +++ b/libc/bionic/pthread_cond.cpp @@ -120,9 +120,15 @@ struct pthread_cond_internal_t { #endif }; +static_assert(sizeof(pthread_cond_t) == sizeof(pthread_cond_internal_t), + "pthread_cond_t should actually be pthread_cond_internal_t in implementation."); + +// For binary compatibility with old version of pthread_cond_t, we can't use more strict alignment +// than 4-byte alignment. +static_assert(alignof(pthread_cond_t) == 4, + "pthread_cond_t should fulfill the alignment requirement of pthread_cond_internal_t."); + static pthread_cond_internal_t* __get_internal_cond(pthread_cond_t* cond_interface) { - static_assert(sizeof(pthread_cond_t) == sizeof(pthread_cond_internal_t), - "pthread_cond_t should actually be pthread_cond_internal_t in implementation."); return reinterpret_cast<pthread_cond_internal_t*>(cond_interface); } diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp index f089940a8..8aa40ae0a 100644 --- a/libc/bionic/pthread_rwlock.cpp +++ b/libc/bionic/pthread_rwlock.cpp @@ -107,9 +107,15 @@ struct pthread_rwlock_internal_t { #endif }; +static_assert(sizeof(pthread_rwlock_t) == sizeof(pthread_rwlock_internal_t), + "pthread_rwlock_t should actually be pthread_rwlock_internal_t in implementation."); + +// For binary compatibility with old version of pthread_rwlock_t, we can't use more strict +// alignment than 4-byte alignment. +static_assert(alignof(pthread_rwlock_t) == 4, + "pthread_rwlock_t should fulfill the alignment requirement of pthread_rwlock_internal_t."); + static inline pthread_rwlock_internal_t* __get_internal_rwlock(pthread_rwlock_t* rwlock_interface) { - static_assert(sizeof(pthread_rwlock_t) == sizeof(pthread_rwlock_internal_t), - "pthread_rwlock_t should actually be pthread_rwlock_internal_t in implementation."); return reinterpret_cast<pthread_rwlock_internal_t*>(rwlock_interface); } diff --git a/libc/include/pthread.h b/libc/include/pthread.h index 09ea113aa..234a43d51 100644 --- a/libc/include/pthread.h +++ b/libc/include/pthread.h @@ -78,7 +78,7 @@ typedef struct { #else char __private[4]; #endif -} pthread_cond_t __attribute__((aligned(sizeof(long)))); +} pthread_cond_t __attribute__((aligned(4))); #define PTHREAD_COND_INITIALIZER { { 0 } } @@ -93,7 +93,7 @@ typedef struct { #else char __private[40]; #endif -} pthread_rwlock_t __attribute__((aligned(8))); +} pthread_rwlock_t __attribute__((aligned(4))); #define PTHREAD_RWLOCK_INITIALIZER { { 0 } } diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp index 251a230e9..4eb352d8e 100644 --- a/tests/pthread_test.cpp +++ b/tests/pthread_test.cpp @@ -33,6 +33,7 @@ #include <unistd.h> #include <atomic> +#include <vector> TEST(pthread, pthread_key_create) { pthread_key_t key; @@ -1303,3 +1304,60 @@ TEST(pthread, pthread_mutex_owner_tid_limit) { // Change the implementation if we need to support higher value than 65535. ASSERT_LE(pid_max, 65536); } + +class StrictAlignmentAllocator { + public: + void* allocate(size_t size, size_t alignment) { + char* p = new char[size + alignment * 2]; + allocated_array.push_back(p); + while (!is_strict_aligned(p, alignment)) { + ++p; + } + return p; + } + + ~StrictAlignmentAllocator() { + for (auto& p : allocated_array) { + delete [] p; + } + } + + private: + bool is_strict_aligned(char* p, size_t alignment) { + return (reinterpret_cast<uintptr_t>(p) % (alignment * 2)) == alignment; + } + + std::vector<char*> allocated_array; +}; + +TEST(pthread, pthread_types_allow_four_bytes_alignment) { +#if defined(__BIONIC__) + // For binary compatibility with old version, we need to allow 4-byte aligned data for pthread types. + StrictAlignmentAllocator allocator; + pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>( + allocator.allocate(sizeof(pthread_mutex_t), 4)); + ASSERT_EQ(0, pthread_mutex_init(mutex, NULL)); + ASSERT_EQ(0, pthread_mutex_lock(mutex)); + ASSERT_EQ(0, pthread_mutex_unlock(mutex)); + ASSERT_EQ(0, pthread_mutex_destroy(mutex)); + + pthread_cond_t* cond = reinterpret_cast<pthread_cond_t*>( + allocator.allocate(sizeof(pthread_cond_t), 4)); + ASSERT_EQ(0, pthread_cond_init(cond, NULL)); + ASSERT_EQ(0, pthread_cond_signal(cond)); + ASSERT_EQ(0, pthread_cond_broadcast(cond)); + ASSERT_EQ(0, pthread_cond_destroy(cond)); + + pthread_rwlock_t* rwlock = reinterpret_cast<pthread_rwlock_t*>( + allocator.allocate(sizeof(pthread_rwlock_t), 4)); + ASSERT_EQ(0, pthread_rwlock_init(rwlock, NULL)); + ASSERT_EQ(0, pthread_rwlock_rdlock(rwlock)); + ASSERT_EQ(0, pthread_rwlock_unlock(rwlock)); + ASSERT_EQ(0, pthread_rwlock_wrlock(rwlock)); + ASSERT_EQ(0, pthread_rwlock_unlock(rwlock)); + ASSERT_EQ(0, pthread_rwlock_destroy(rwlock)); + +#else + GTEST_LOG_(INFO) << "This test tests bionic implementation details."; +#endif +} |