]> git.saurik.com Git - apple/libpthread.git/blobdiff - tests/cond.c
libpthread-301.20.1.tar.gz
[apple/libpthread.git] / tests / cond.c
index 65c53ce176f19be81da45fb3f50cbd56243d218c..0fc91c2b5aa9082edc67c80f81e326caa44ec588 100644 (file)
@@ -8,77 +8,95 @@
 #include <errno.h>
 #include <libkern/OSAtomic.h>
 
+#include "darwintest_defaults.h"
+#include <darwintest_utils.h>
+
 struct context {
        pthread_cond_t cond;
        pthread_mutex_t mutex;
+       pthread_cond_t ready_cond;
        long waiters;
        long count;
+       bool ready;
+       char _padding[7];
 };
 
-void *wait_thread(void *ptr) {
-       int res;
+
+static void *wait_thread(void *ptr) {
        struct context *context = ptr;
 
-       int i = 0;
-       char *str;
+       // tell producer thread that we are ready
+       T_QUIET;
+       T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context->mutex), "pthread_mutex_lock");
+       context->ready = true;
+       T_QUIET;
+       T_ASSERT_POSIX_ZERO(pthread_cond_signal(&context->ready_cond), "pthread_cond_signal");
 
        bool loop = true;
        while (loop) {
-               res = pthread_mutex_lock(&context->mutex);
-               if (res) {
-                       fprintf(stderr, "[%ld] pthread_mutex_lock: %s\n", context->count, strerror(res));
-                       abort();
-               }
-               
+
                if (context->count > 0) {
                        ++context->waiters;
-                       res = pthread_cond_wait(&context->cond, &context->mutex);
-                       if (res) {
-                               fprintf(stderr, "[%ld] pthread_rwlock_unlock: %s\n", context->count, strerror(res));
-                               abort();
-                       }
+                       T_QUIET;
+                       T_ASSERT_POSIX_ZERO(pthread_cond_wait(&context->cond, &context->mutex), "[%ld] pthread_rwlock_unlock", context->count);
                        --context->waiters;
                        --context->count;
                } else {
                        loop = false;
                }
-               
-               res = pthread_mutex_unlock(&context->mutex);
-               if (res) {
-                       fprintf(stderr, "[%ld] pthread_mutex_unlock: %s\n", context->count, strerror(res));
-                       abort();
-               }
+
        }
 
+       T_QUIET;
+       T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context->mutex), "[%ld] pthread_mutex_unlock", context->count);
+
        return NULL;
 }
 
-int main(int argc, char *argv[])
+T_DECL(cond, "pthread_cond",
+               T_META_ALL_VALID_ARCHS(YES), T_META_TIMEOUT(120), T_META_CHECK_LEAKS(NO))
 {
        struct context context = {
                .cond = PTHREAD_COND_INITIALIZER,
                .mutex = PTHREAD_MUTEX_INITIALIZER,
+               .ready_cond = PTHREAD_COND_INITIALIZER,
                .waiters = 0,
-               .count = 500000,
+               .count = 50000 * dt_ncpu(),
+               .ready = false,
        };
        int i;
        int res;
        int threads = 2;
        pthread_t p[threads];
        for (i = 0; i < threads; ++i) {
-               res = pthread_create(&p[i], NULL, wait_thread, &context);
-               assert(res == 0);
+               T_QUIET;
+               T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context.mutex), "pthread_mutex_lock");
+
+               context.ready = false;
+
+               T_QUIET;
+               T_ASSERT_POSIX_ZERO(pthread_create(&p[i], NULL, wait_thread, &context), "pthread_create");
+
+               do {
+                       // mutex will be dropped and allow consumer thread to acquire
+                       T_QUIET;
+                       T_ASSERT_POSIX_ZERO(pthread_cond_wait(&context.ready_cond, &context.mutex), "pthread_cond_wait");
+               } while (context.ready == false);
+
+               T_QUIET;
+               T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context.mutex), "pthread_mutex_lock");
+
+               T_LOG("Thread %d ready.", i);
        }
 
+       T_LOG("All threads ready.");
+
        long half = context.count / 2;
 
        bool loop = true;
        while (loop) {
-               res = pthread_mutex_lock(&context.mutex);
-               if (res) {
-                       fprintf(stderr, "[%ld] pthread_mutex_lock: %s\n", context.count, strerror(res));
-                       abort();
-               }
+               T_QUIET;
+               T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&context.mutex), "[%ld] pthread_mutex_lock", context.count);
                if (context.waiters) {
                        char *str;
                        if (context.count > half) {
@@ -88,27 +106,20 @@ int main(int argc, char *argv[])
                                str = "pthread_cond_signal";
                                res = pthread_cond_signal(&context.cond);
                        }
-                       if (res != 0) {
-                               fprintf(stderr, "[%ld] %s: %s\n", context.count, str, strerror(res));
-                               abort();
-                       }
+                       T_QUIET;
+                       T_ASSERT_POSIX_ZERO(res, "[%ld] %s", context.count, str);
                }
                if (context.count <= 0) {
                        loop = false;
+                       T_PASS("Completed stres test successfully.");
                }
-               
-               res = pthread_mutex_unlock(&context.mutex);
-               if (res) {
-                       fprintf(stderr, "[%ld] pthread_mutex_unlock: %s\n", context.count, strerror(res));
-                       abort();
-               }
+
+               T_QUIET;
+               T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&context.mutex),
+                               "[%ld] pthread_mutex_unlock", context.count);
        }
-       
-       
+
        for (i = 0; i < threads; ++i) {
-               res = pthread_join(p[i], NULL);
-               assert(res == 0);
+               T_ASSERT_POSIX_ZERO(pthread_join(p[i], NULL), NULL);
        }
-
-       return 0;
 }