]> git.saurik.com Git - apple/libpthread.git/blob - tests/mutex_try.c
libpthread-330.230.1.tar.gz
[apple/libpthread.git] / tests / mutex_try.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <pthread.h>
6 #include <stdlib.h>
7
8 #include "darwintest_defaults.h"
9
10 struct ctx {
11 volatile int last_holder;
12 volatile int quit;
13 int iterations[2];
14 pthread_mutex_t l;
15 };
16
17 static void *
18 job(struct ctx *ctx, int idx)
19 {
20 int ret;
21 while (!ctx->quit) {
22 ret = pthread_mutex_trylock(&ctx->l);
23 T_QUIET; T_ASSERT_TRUE(ret == EBUSY || ret == 0, "trylock");
24
25 if (ret == EBUSY) {
26 T_QUIET; T_ASSERT_POSIX_ZERO(pthread_mutex_lock(&ctx->l),
27 "pthread_mutex_lock");
28 // we know that the other thread was just holding the lock
29 T_QUIET; T_ASSERT_EQ(ctx->last_holder, !idx,
30 "expecting oppsosite last holder after failed trylock");
31 }
32
33 ctx->last_holder = idx;
34 ctx->iterations[idx]++;
35
36 T_QUIET; T_ASSERT_POSIX_ZERO(pthread_mutex_unlock(&ctx->l),
37 "pthread_mutex_unlock");
38 }
39 return NULL;
40 }
41
42 static void *
43 job1(void *ctx)
44 {
45 return job((struct ctx *)ctx, 0);
46 }
47
48 static void *
49 job2(void *ctx)
50 {
51 return job((struct ctx *)ctx, 1);
52 }
53
54 T_DECL(mutex_trylock, "pthread_mutex_trylock",
55 T_META_ALL_VALID_ARCHS(YES))
56 {
57 // This testcase spins up two threads with identical jobs. They try-lock
58 // the same mutex. If that fails, they check that the last holder of the
59 // lock is the other thread.
60 const int test_duration = 10; // sec
61 struct ctx ctx = {0};
62
63 pthread_t t1, t2;
64
65 T_ASSERT_POSIX_ZERO(pthread_mutex_init(&ctx.l, NULL),
66 "pthread_mutex_init");
67 T_ASSERT_POSIX_ZERO(pthread_create(&t1, NULL, job1, &ctx),
68 "pthread_create 1");
69 T_ASSERT_POSIX_ZERO(pthread_create(&t2, NULL, job2, &ctx),
70 "pthread_create 2");
71
72 sleep(test_duration);
73
74 ctx.quit = 1;
75 T_ASSERT_POSIX_ZERO(pthread_join(t1, NULL), "pthread join 1");
76 T_ASSERT_POSIX_ZERO(pthread_join(t2, NULL), "pthread join 2");
77
78 T_LOG("after %d seconds iterations 0: %d, 1: %d. Exiting\n",
79 test_duration, ctx.iterations[0], ctx.iterations[1]);
80 }