]> git.saurik.com Git - apple/objc4.git/blob - test/synchronized.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / synchronized.m
1 // TEST_CONFIG
2
3 #include "test.h"
4
5 #include <Foundation/NSObject.h>
6 #include <mach/mach.h>
7 #include <pthread.h>
8 #include <sys/time.h>
9 #include <objc/runtime.h>
10 #include <objc/objc-sync.h>
11
12 // Basic @synchronized tests.
13
14
15 #define WAIT_SEC 3
16
17 static id obj;
18 static semaphore_t go;
19 static semaphore_t stop;
20
21 void *thread(void *arg __unused)
22 {
23 int err;
24 BOOL locked;
25
26 // non-blocking sync_enter
27 err = objc_sync_enter(obj);
28 testassert(err == OBJC_SYNC_SUCCESS);
29
30 // recursive try_sync_enter
31 locked = objc_sync_try_enter(obj);
32 testassert(locked);
33 err = objc_sync_exit(obj);
34 testassert(err == OBJC_SYNC_SUCCESS);
35
36 semaphore_signal(go);
37 // main thread: sync_exit of object locked on some other thread
38 semaphore_wait(stop);
39
40 err = objc_sync_exit(obj);
41 testassert(err == OBJC_SYNC_SUCCESS);
42 err = objc_sync_enter(obj);
43 testassert(err == OBJC_SYNC_SUCCESS);
44
45 semaphore_signal(go);
46 // main thread: blocking sync_enter
47 testassert(WAIT_SEC/3*3 == WAIT_SEC);
48 sleep(WAIT_SEC/3);
49 // recursive enter while someone waits
50 err = objc_sync_enter(obj);
51 testassert(err == OBJC_SYNC_SUCCESS);
52 sleep(WAIT_SEC/3);
53 // recursive exit while someone waits
54 err = objc_sync_exit(obj);
55 testassert(err == OBJC_SYNC_SUCCESS);
56 sleep(WAIT_SEC/3);
57 // sync_exit while someone waits
58 err = objc_sync_exit(obj);
59 testassert(err == OBJC_SYNC_SUCCESS);
60
61 return NULL;
62 }
63
64 int main()
65 {
66 pthread_t th;
67 int err;
68 struct timeval start, end;
69 BOOL locked;
70
71 obj = [[NSObject alloc] init];
72
73 // sync_exit of never-locked object
74 err = objc_sync_exit(obj);
75 testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR);
76
77 semaphore_create(mach_task_self(), &go, 0, 0);
78 semaphore_create(mach_task_self(), &stop, 0, 0);
79 pthread_create(&th, NULL, &thread, NULL);
80 semaphore_wait(go);
81
82 // sync_exit of object locked on some other thread
83 err = objc_sync_exit(obj);
84 testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR);
85
86 semaphore_signal(stop);
87 semaphore_wait(go);
88
89 // contended try_sync_enter
90 locked = objc_sync_try_enter(obj);
91 testassert(!locked);
92
93 // blocking sync_enter
94 gettimeofday(&start, NULL);
95 err = objc_sync_enter(obj);
96 gettimeofday(&end, NULL);
97 testassert(err == OBJC_SYNC_SUCCESS);
98 // should have waited more than WAIT_SEC but less than WAIT_SEC+1
99 // fixme hack: sleep(1) is ending 500 usec too early on x86_64 buildbot
100 // (rdar://6456975)
101 testassert(end.tv_sec*1000000LL+end.tv_usec >=
102 start.tv_sec*1000000LL+start.tv_usec + WAIT_SEC*1000000LL
103 - 3*500 /*hack*/);
104 testassert(end.tv_sec*1000000LL+end.tv_usec <
105 start.tv_sec*1000000LL+start.tv_usec + (1+WAIT_SEC)*1000000LL);
106
107 err = objc_sync_exit(obj);
108 testassert(err == OBJC_SYNC_SUCCESS);
109
110 err = objc_sync_exit(obj);
111 testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR);
112
113 succeed(__FILE__);
114 }