1 // rdar://6401639, waiting for rdar://5648998
8 #define _OBJC_PRIVATE_H_
9 #include <objc/objc-gdb.h>
11 #warning this test needs to be augmented for the side table machienery
13 @interface Super { id isa; } @end
17 +class { return self; }
18 +(int)method { return 1; }
19 +(int)method2 { return 1; }
25 void *thread(void *arg __unused)
27 objc_registerThreadWithCollector();
29 semaphore_signal(sema);
33 _objc_flush_caches(0, YES);
40 void stopAllThreads(void)
42 mach_msg_type_number_t count, i;
43 thread_act_array_t list;
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]);
53 void startAllThreads(void)
55 mach_msg_type_number_t count, i;
56 thread_act_array_t list;
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]);
67 static void cycle(int mode, int *good, int *bad)
70 if (gdb_objc_startDebuggerMode(mode)) {
74 if (mode == OBJC_DEBUGMODE_FULL) {
75 // will crash without full write locks
76 _objc_flush_caches(0, YES);
78 gdb_objc_endDebuggerMode();
97 testassert(STOPS > 200);
99 // Uncontended debugger mode
100 testassert(gdb_objc_startDebuggerMode(0));
101 gdb_objc_endDebuggerMode();
103 // Uncontended full debugger mode
104 testassert(gdb_objc_startDebuggerMode(OBJC_DEBUGMODE_FULL));
105 gdb_objc_endDebuggerMode();
107 // Nested debugger mode
108 testassert(gdb_objc_startDebuggerMode(0));
109 testassert(gdb_objc_startDebuggerMode(0));
110 gdb_objc_endDebuggerMode();
111 gdb_objc_endDebuggerMode();
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();
119 // Check that debugger mode sometimes works and sometimes doesn't
120 // when contending with another runtime-manipulating thread.
122 semaphore_create(mach_task_self(), &sema, 0, 0);
124 for (i = 0; i < THREADS; i++) {
126 pthread_create(&th, NULL, &thread, NULL);
127 semaphore_wait(sema);
132 int good0 = 0, bad0 = 0;
133 for (i = 0; i < STOPS; i++) {
134 cycle(0, &good0, &bad0);
136 testprintf("good0 %d, bad0 %d\n", good0, bad0);
138 int goodF = 0, badF = 0;
139 for (i = 0; i < STOPS; i++) {
140 cycle(OBJC_DEBUGMODE_FULL, &goodF, &badF);
142 testprintf("goodF %d, badF %d\n", goodF, badF);
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.
149 if (good0 > STOPS/100 && bad0 > STOPS/100 && good0 > 1 && bad0 > 1 &&
150 goodF > STOPS/100 && badF > STOPS/100 && goodF > 1 && badF > 1
152 && good0 > goodF /* not reliable enough in old runtime */
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);