]>
Commit | Line | Data |
---|---|---|
8972963c A |
1 | // TEST_CFLAGS -framework Foundation |
2 | ||
7af964d1 A |
3 | #include "test.h" |
4 | ||
5 | #include <Foundation/Foundation.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 | ||
25 | objc_registerThreadWithCollector(); | |
26 | ||
27 | // non-blocking sync_enter | |
28 | err = objc_sync_enter(obj); | |
29 | testassert(err == OBJC_SYNC_SUCCESS); | |
30 | ||
31 | semaphore_signal(go); | |
32 | // main thread: sync_exit of object locked on some other thread | |
33 | semaphore_wait(stop); | |
34 | ||
35 | err = objc_sync_exit(obj); | |
36 | testassert(err == OBJC_SYNC_SUCCESS); | |
37 | err = objc_sync_enter(obj); | |
38 | testassert(err == OBJC_SYNC_SUCCESS); | |
39 | ||
40 | semaphore_signal(go); | |
41 | // main thread: blocking sync_enter | |
42 | testassert(WAIT_SEC/3*3 == WAIT_SEC); | |
43 | sleep(WAIT_SEC/3); | |
44 | // recursive enter while someone waits | |
45 | err = objc_sync_enter(obj); | |
46 | testassert(err == OBJC_SYNC_SUCCESS); | |
47 | sleep(WAIT_SEC/3); | |
48 | // recursive exit while someone waits | |
49 | err = objc_sync_exit(obj); | |
50 | testassert(err == OBJC_SYNC_SUCCESS); | |
51 | sleep(WAIT_SEC/3); | |
52 | // sync_exit while someone waits | |
53 | err = objc_sync_exit(obj); | |
54 | testassert(err == OBJC_SYNC_SUCCESS); | |
55 | ||
56 | return NULL; | |
57 | } | |
58 | ||
59 | int main() | |
60 | { | |
61 | pthread_t th; | |
62 | int err; | |
63 | struct timeval start, end; | |
64 | ||
65 | obj = [[NSObject alloc] init]; | |
66 | ||
67 | // sync_exit of never-locked object | |
68 | err = objc_sync_exit(obj); | |
69 | testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); | |
70 | ||
71 | semaphore_create(mach_task_self(), &go, 0, 0); | |
72 | semaphore_create(mach_task_self(), &stop, 0, 0); | |
73 | pthread_create(&th, NULL, &thread, NULL); | |
74 | semaphore_wait(go); | |
75 | ||
76 | // sync_exit of object locked on some other thread | |
77 | err = objc_sync_exit(obj); | |
78 | testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); | |
79 | ||
80 | semaphore_signal(stop); | |
81 | semaphore_wait(go); | |
82 | ||
83 | // blocking sync_enter | |
84 | gettimeofday(&start, NULL); | |
85 | err = objc_sync_enter(obj); | |
86 | gettimeofday(&end, NULL); | |
87 | testassert(err == OBJC_SYNC_SUCCESS); | |
88 | // should have waited more than WAIT_SEC but less than WAIT_SEC+1 | |
89 | // fixme hack: sleep(1) is ending 500 usec too early on x86_64 buildbot | |
90 | testassert(end.tv_sec*1000000LL+end.tv_usec >= | |
91 | start.tv_sec*1000000LL+start.tv_usec + WAIT_SEC*1000000LL | |
92 | - 3*500 /*hack*/); | |
93 | testassert(end.tv_sec*1000000LL+end.tv_usec < | |
94 | start.tv_sec*1000000LL+start.tv_usec + (1+WAIT_SEC)*1000000LL); | |
95 | ||
96 | err = objc_sync_exit(obj); | |
97 | testassert(err == OBJC_SYNC_SUCCESS); | |
98 | ||
99 | err = objc_sync_exit(obj); | |
100 | testassert(err == OBJC_SYNC_NOT_OWNING_THREAD_ERROR); | |
101 | ||
102 | succeed(__FILE__); | |
103 | } |