Remove duplication in pthread_mutex.cpp.
Also add unit tests about thread woken up by pthread_mutex_unlock.
Bug: 19216648
Change-Id: I8bde8105b00186c52a2f41d92458ae4a5eb90426
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index c507faa..b5c4a46 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -733,8 +733,10 @@
pthread_t thread;
ASSERT_EQ(0, pthread_create(&thread, NULL,
reinterpret_cast<void* (*)(void*)>(pthread_rwlock_reader_wakeup_writer_helper), &wakeup_arg));
- sleep(1);
- ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);
+ while (wakeup_arg.progress != RwlockWakeupHelperArg::LOCK_WAITING) {
+ usleep(5000);
+ }
+ usleep(5000);
wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_RELEASED;
ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock));
@@ -764,8 +766,10 @@
pthread_t thread;
ASSERT_EQ(0, pthread_create(&thread, NULL,
reinterpret_cast<void* (*)(void*)>(pthread_rwlock_writer_wakeup_reader_helper), &wakeup_arg));
- sleep(1);
- ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);
+ while (wakeup_arg.progress != RwlockWakeupHelperArg::LOCK_WAITING) {
+ usleep(5000);
+ }
+ usleep(5000);
wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_RELEASED;
ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock));
@@ -1118,15 +1122,21 @@
ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
ASSERT_EQ(0, pthread_mutexattr_gettype(&attr, &attr_type));
ASSERT_EQ(PTHREAD_MUTEX_RECURSIVE, attr_type);
+
+ ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
+}
+
+static void CreateMutex(pthread_mutex_t& mutex, int mutex_type) {
+ pthread_mutexattr_t attr;
+ ASSERT_EQ(0, pthread_mutexattr_init(&attr));
+ ASSERT_EQ(0, pthread_mutexattr_settype(&attr, mutex_type));
+ ASSERT_EQ(0, pthread_mutex_init(&mutex, &attr));
+ ASSERT_EQ(0, pthread_mutexattr_destroy(&attr));
}
TEST(pthread, pthread_mutex_lock_NORMAL) {
- pthread_mutexattr_t attr;
- ASSERT_EQ(0, pthread_mutexattr_init(&attr));
- ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL));
-
pthread_mutex_t lock;
- ASSERT_EQ(0, pthread_mutex_init(&lock, &attr));
+ CreateMutex(lock, PTHREAD_MUTEX_NORMAL);
ASSERT_EQ(0, pthread_mutex_lock(&lock));
ASSERT_EQ(0, pthread_mutex_unlock(&lock));
@@ -1134,12 +1144,8 @@
}
TEST(pthread, pthread_mutex_lock_ERRORCHECK) {
- pthread_mutexattr_t attr;
- ASSERT_EQ(0, pthread_mutexattr_init(&attr));
- ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
-
pthread_mutex_t lock;
- ASSERT_EQ(0, pthread_mutex_init(&lock, &attr));
+ CreateMutex(lock, PTHREAD_MUTEX_ERRORCHECK);
ASSERT_EQ(0, pthread_mutex_lock(&lock));
ASSERT_EQ(EDEADLK, pthread_mutex_lock(&lock));
@@ -1152,12 +1158,8 @@
}
TEST(pthread, pthread_mutex_lock_RECURSIVE) {
- pthread_mutexattr_t attr;
- ASSERT_EQ(0, pthread_mutexattr_init(&attr));
- ASSERT_EQ(0, pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE));
-
pthread_mutex_t lock;
- ASSERT_EQ(0, pthread_mutex_init(&lock, &attr));
+ CreateMutex(lock, PTHREAD_MUTEX_RECURSIVE);
ASSERT_EQ(0, pthread_mutex_lock(&lock));
ASSERT_EQ(0, pthread_mutex_lock(&lock));
@@ -1169,6 +1171,66 @@
ASSERT_EQ(0, pthread_mutex_destroy(&lock));
}
+class MutexWakeupHelper {
+ private:
+ pthread_mutex_t mutex;
+ enum Progress {
+ LOCK_INITIALIZED,
+ LOCK_WAITING,
+ LOCK_RELEASED,
+ LOCK_ACCESSED
+ };
+ std::atomic<Progress> progress;
+
+ static void thread_fn(MutexWakeupHelper* helper) {
+ ASSERT_EQ(LOCK_INITIALIZED, helper->progress);
+ helper->progress = LOCK_WAITING;
+
+ ASSERT_EQ(0, pthread_mutex_lock(&helper->mutex));
+ ASSERT_EQ(LOCK_RELEASED, helper->progress);
+ ASSERT_EQ(0, pthread_mutex_unlock(&helper->mutex));
+
+ helper->progress = LOCK_ACCESSED;
+ }
+
+ public:
+ void test(int mutex_type) {
+ CreateMutex(mutex, mutex_type);
+ ASSERT_EQ(0, pthread_mutex_lock(&mutex));
+ progress = LOCK_INITIALIZED;
+
+ pthread_t thread;
+ ASSERT_EQ(0, pthread_create(&thread, NULL,
+ reinterpret_cast<void* (*)(void*)>(MutexWakeupHelper::thread_fn), this));
+
+ while (progress != LOCK_WAITING) {
+ usleep(5000);
+ }
+ usleep(5000);
+ progress = LOCK_RELEASED;
+ ASSERT_EQ(0, pthread_mutex_unlock(&mutex));
+
+ ASSERT_EQ(0, pthread_join(thread, NULL));
+ ASSERT_EQ(LOCK_ACCESSED, progress);
+ ASSERT_EQ(0, pthread_mutex_destroy(&mutex));
+ }
+};
+
+TEST(pthread, pthread_mutex_NORMAL_wakeup) {
+ MutexWakeupHelper helper;
+ helper.test(PTHREAD_MUTEX_NORMAL);
+}
+
+TEST(pthread, pthread_mutex_ERRORCHECK_wakeup) {
+ MutexWakeupHelper helper;
+ helper.test(PTHREAD_MUTEX_ERRORCHECK);
+}
+
+TEST(pthread, pthread_mutex_RECURSIVE_wakeup) {
+ MutexWakeupHelper helper;
+ helper.test(PTHREAD_MUTEX_RECURSIVE);
+}
+
TEST(pthread, pthread_mutex_owner_tid_limit) {
FILE* fp = fopen("/proc/sys/kernel/pid_max", "r");
ASSERT_TRUE(fp != NULL);