]> git.saurik.com Git - apple/objc4.git/blob - test/debuggerMode.m
aef2faf0c7b42a6eac8ff9f9e0b007847fade707
[apple/objc4.git] / test / debuggerMode.m
1 // rdar://6401639, waiting for rdar://5648998
2 // TEST_DISABLED
3
4 #include "test.h"
5 #include <objc/objc.h>
6 #include <mach/mach.h>
7 #include <pthread.h>
8 #define _OBJC_PRIVATE_H_
9 #include <objc/objc-gdb.h>
10
11 #warning this test needs to be augmented for the side table machienery
12
13 @interface Super { id isa; } @end
14
15 @implementation Super
16 +(void)initialize { }
17 +class { return self; }
18 +(int)method { return 1; }
19 +(int)method2 { return 1; }
20 @end
21
22
23 semaphore_t sema;
24
25 void *thread(void *arg __unused)
26 {
27 objc_registerThreadWithCollector();
28
29 semaphore_signal(sema);
30 testprintf("hi\n");
31 while (1) {
32 [Super method];
33 _objc_flush_caches(0, YES);
34 }
35
36 return NULL;
37 }
38
39
40 void stopAllThreads(void)
41 {
42 mach_msg_type_number_t count, i;
43 thread_act_array_t list;
44
45 task_threads(mach_task_self(), &list, &count);
46 for (i = 0; i < count; i++) {
47 if (list[i] == mach_thread_self()) continue;
48 thread_suspend(list[i]);
49 mach_port_deallocate(mach_task_self(), list[i]);
50 }
51 }
52
53 void startAllThreads(void)
54 {
55 mach_msg_type_number_t count, i;
56 thread_act_array_t list;
57
58 task_threads(mach_task_self(), &list, &count);
59 for (i = 0; i < count; i++) {
60 if (list[i] == mach_thread_self()) continue;
61 thread_resume(list[i]);
62 mach_port_deallocate(mach_task_self(), list[i]);
63 }
64 }
65
66
67 static void cycle(int mode, int *good, int *bad)
68 {
69 stopAllThreads();
70 if (gdb_objc_startDebuggerMode(mode)) {
71 testprintf("good\n");
72 [Super method];
73 [Super method2];
74 if (mode == OBJC_DEBUGMODE_FULL) {
75 // will crash without full write locks
76 _objc_flush_caches(0, YES);
77 }
78 gdb_objc_endDebuggerMode();
79 ++*good;
80 } else {
81 testprintf("bad\n");
82 ++*bad;
83 }
84 startAllThreads();
85 sched_yield();
86 }
87
88
89 int main()
90 {
91 #define STOPS 10000
92 #define THREADS 1
93 int i;
94
95 [Super class];
96
97 testassert(STOPS > 200);
98
99 // Uncontended debugger mode
100 testassert(gdb_objc_startDebuggerMode(0));
101 gdb_objc_endDebuggerMode();
102
103 // Uncontended full debugger mode
104 testassert(gdb_objc_startDebuggerMode(OBJC_DEBUGMODE_FULL));
105 gdb_objc_endDebuggerMode();
106
107 // Nested debugger mode
108 testassert(gdb_objc_startDebuggerMode(0));
109 testassert(gdb_objc_startDebuggerMode(0));
110 gdb_objc_endDebuggerMode();
111 gdb_objc_endDebuggerMode();
112
113 // Nested full debugger mode
114 testassert(gdb_objc_startDebuggerMode(OBJC_DEBUGMODE_FULL));
115 testassert(gdb_objc_startDebuggerMode(OBJC_DEBUGMODE_FULL));
116 gdb_objc_endDebuggerMode();
117 gdb_objc_endDebuggerMode();
118
119 // Check that debugger mode sometimes works and sometimes doesn't
120 // when contending with another runtime-manipulating thread.
121
122 semaphore_create(mach_task_self(), &sema, 0, 0);
123
124 for (i = 0; i < THREADS; i++) {
125 pthread_t th;
126 pthread_create(&th, NULL, &thread, NULL);
127 semaphore_wait(sema);
128 }
129
130 testprintf("go\n");
131
132 int good0 = 0, bad0 = 0;
133 for (i = 0; i < STOPS; i++) {
134 cycle(0, &good0, &bad0);
135 }
136 testprintf("good0 %d, bad0 %d\n", good0, bad0);
137
138 int goodF = 0, badF = 0;
139 for (i = 0; i < STOPS; i++) {
140 cycle(OBJC_DEBUGMODE_FULL, &goodF, &badF);
141 }
142 testprintf("goodF %d, badF %d\n", goodF, badF);
143
144 // Require at least 1% each of good and bad.
145 // Also require more than one each (exactly one is likely
146 // a bug wherein the locks got stuck the first time).
147 // Also require that FULL worked less often.
148
149 if (good0 > STOPS/100 && bad0 > STOPS/100 && good0 > 1 && bad0 > 1 &&
150 goodF > STOPS/100 && badF > STOPS/100 && goodF > 1 && badF > 1
151 #ifdef __OBJC2__
152 && good0 > goodF /* not reliable enough in old runtime */
153 #endif
154 )
155 {
156 succeed(__FILE__);
157 }
158
159 fail("good0=%d/%d bad0=%d/%d goodF=%d/%d badF=%d/%d (required at least %d/%d good)",
160 good0, STOPS, bad0, STOPS, goodF, STOPS, badF, STOPS, STOPS/100, STOPS);
161 }