Merge branch 'atsushi'
[mono.git] / libgc / darwin_stop_world.c
1 #include "private/pthread_support.h"
2
3 # if defined(GC_DARWIN_THREADS)
4
5 #include <AvailabilityMacros.h>
6 #include "mono/utils/mono-compiler.h"
7
8 #ifdef MONO_DEBUGGER_SUPPORTED
9 #include "include/libgc-mono-debugger.h"
10 #endif
11
12 /* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
13    Page 49:
14    "The space beneath the stack pointer, where a new stack frame would normally
15    be allocated, is called the red zone. This area as shown in Figure 3-2 may
16    be used for any purpose as long as a new stack frame does not need to be
17    added to the stack."
18    
19    Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
20    it must set up a stack frame just like routines that call other routines."
21 */
22 #ifdef POWERPC
23 # if CPP_WORDSZ == 32
24 #   define PPC_RED_ZONE_SIZE 224
25 # elif CPP_WORDSZ == 64
26 #   define PPC_RED_ZONE_SIZE 320
27 # endif
28 #endif
29
30 typedef struct StackFrame {
31   unsigned long savedSP;
32   unsigned long savedCR;
33   unsigned long savedLR;
34   unsigned long reserved[2];
35   unsigned long savedRTOC;
36 } StackFrame;
37
38 unsigned long FindTopOfStack(unsigned int stack_start) {
39   StackFrame    *frame;
40   
41   if (stack_start == 0) {
42 # ifdef POWERPC
43 #   if CPP_WORDSZ == 32
44       __asm__ volatile("lwz     %0,0(r1)" : "=r" (frame));
45 #   else
46       __asm__ volatile("ldz     %0,0(r1)" : "=r" (frame));
47 #   endif
48 # endif
49   } else {
50     frame = (StackFrame *)stack_start;
51   }
52
53 # ifdef DEBUG_THREADS
54     /* GC_printf1("FindTopOfStack start at sp = %p\n", frame); */
55 # endif
56   do {
57     if (frame->savedSP == 0) break;
58                 /* if there are no more stack frames, stop */
59
60     frame = (StackFrame*)frame->savedSP;
61
62     /* we do these next two checks after going to the next frame
63        because the LR for the first stack frame in the loop
64        is not set up on purpose, so we shouldn't check it. */
65     if ((frame->savedLR & ~3) == 0) break; /* if the next LR is bogus, stop */
66     if ((~(frame->savedLR) & ~3) == 0) break; /* ditto */
67   } while (1); 
68
69 # ifdef DEBUG_THREADS
70     /* GC_printf1("FindTopOfStack finish at sp = %p\n", frame); */
71 # endif
72
73   return (unsigned long)frame;
74 }       
75
76 #ifdef DARWIN_DONT_PARSE_STACK
77 void GC_push_all_stacks() {
78   int i;
79   kern_return_t r;
80   GC_thread p;
81   pthread_t me;
82   ptr_t lo, hi;
83 #if defined(POWERPC)
84   ppc_thread_state_t state;
85   mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
86 #elif defined(I386)
87   i386_thread_state_t state;
88   mach_msg_type_number_t thread_state_count = i386_THREAD_STATE_COUNT;
89 #elif defined(ARM)
90   arm_thread_state_t state;
91   mach_msg_type_number_t thread_state_count = ARM_THREAD_STATE_COUNT;
92 #elif defined(X86_64)
93   x86_thread_state64_t state;
94   mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT;
95 #else
96 # error FIXME for non-x86 || ppc architectures
97   mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
98 #endif
99   
100   me = pthread_self();
101   if (!GC_thr_initialized) GC_thr_init();
102   
103   for(i=0;i<THREAD_TABLE_SZ;i++) {
104     for(p=GC_threads[i];p!=0;p=p->next) {
105       if(p -> flags & FINISHED) continue;
106       if(pthread_equal(p->id,me)) {
107         lo = GC_approx_sp();
108       } else {
109         /* Get the thread state (registers, etc) */
110         r = thread_get_state(
111                              p->stop_info.mach_thread,
112                              GC_MACH_THREAD_STATE_FLAVOR,
113                              (natural_t*)&state,
114                              &thread_state_count);
115         if(r != KERN_SUCCESS) continue;
116         
117 #if defined(I386)
118 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
119
120         lo = state.__esp;
121
122         GC_push_one(state.__eax); 
123         GC_push_one(state.__ebx); 
124         GC_push_one(state.__ecx); 
125         GC_push_one(state.__edx); 
126         GC_push_one(state.__edi); 
127         GC_push_one(state.__esi); 
128         GC_push_one(state.__ebp); 
129 #else
130         lo = state.esp;
131
132         GC_push_one(state.eax); 
133         GC_push_one(state.ebx); 
134         GC_push_one(state.ecx); 
135         GC_push_one(state.edx); 
136         GC_push_one(state.edi); 
137         GC_push_one(state.esi); 
138         GC_push_one(state.ebp); 
139 #endif
140 #elif defined(X86_64)
141           lo = state.__rsp;
142           GC_push_one(state.__rax);
143           GC_push_one(state.__rbx);
144           GC_push_one(state.__rcx);
145           GC_push_one(state.__rdx);
146           GC_push_one(state.__rdi);
147           GC_push_one(state.__rsi);
148           GC_push_one(state.__rbp);
149           GC_push_one(state.__r8);
150           GC_push_one(state.__r9);
151           GC_push_one(state.__r10);
152           GC_push_one(state.__r11);
153           GC_push_one(state.__r12);
154           GC_push_one(state.__r13);
155           GC_push_one(state.__r14);
156           GC_push_one(state.__r15);
157 #elif defined(POWERPC)
158 #if defined(_STRUCT_PPC_EXCEPTION_STATE) && defined(__DARWIN_UNIX03)
159         lo = (void*)(state.__r1 - PPC_RED_ZONE_SIZE);
160         
161         GC_push_one(state.__r0); 
162         GC_push_one(state.__r2); 
163         GC_push_one(state.__r3); 
164         GC_push_one(state.__r4); 
165         GC_push_one(state.__r5); 
166         GC_push_one(state.__r6); 
167         GC_push_one(state.__r7); 
168         GC_push_one(state.__r8); 
169         GC_push_one(state.__r9); 
170         GC_push_one(state.__r10); 
171         GC_push_one(state.__r11); 
172         GC_push_one(state.__r12); 
173         GC_push_one(state.__r13); 
174         GC_push_one(state.__r14); 
175         GC_push_one(state.__r15); 
176         GC_push_one(state.__r16); 
177         GC_push_one(state.__r17); 
178         GC_push_one(state.__r18); 
179         GC_push_one(state.__r19); 
180         GC_push_one(state.__r20); 
181         GC_push_one(state.__r21); 
182         GC_push_one(state.__r22); 
183         GC_push_one(state.__r23); 
184         GC_push_one(state.__r24); 
185         GC_push_one(state.__r25); 
186         GC_push_one(state.__r26); 
187         GC_push_one(state.__r27); 
188         GC_push_one(state.__r28); 
189         GC_push_one(state.__r29); 
190         GC_push_one(state.__r30); 
191         GC_push_one(state.__r31);
192 #else
193         lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE);
194         
195         GC_push_one(state.r0); 
196         GC_push_one(state.r2); 
197         GC_push_one(state.r3); 
198         GC_push_one(state.r4); 
199         GC_push_one(state.r5); 
200         GC_push_one(state.r6); 
201         GC_push_one(state.r7); 
202         GC_push_one(state.r8); 
203         GC_push_one(state.r9); 
204         GC_push_one(state.r10); 
205         GC_push_one(state.r11); 
206         GC_push_one(state.r12); 
207         GC_push_one(state.r13); 
208         GC_push_one(state.r14); 
209         GC_push_one(state.r15); 
210         GC_push_one(state.r16); 
211         GC_push_one(state.r17); 
212         GC_push_one(state.r18); 
213         GC_push_one(state.r19); 
214         GC_push_one(state.r20); 
215         GC_push_one(state.r21); 
216         GC_push_one(state.r22); 
217         GC_push_one(state.r23); 
218         GC_push_one(state.r24); 
219         GC_push_one(state.r25); 
220         GC_push_one(state.r26); 
221         GC_push_one(state.r27); 
222         GC_push_one(state.r28); 
223         GC_push_one(state.r29); 
224         GC_push_one(state.r30); 
225         GC_push_one(state.r31);
226 #endif
227 #elif defined(ARM)
228         lo = (void*)state.__sp;
229
230         GC_push_one(state.__r[0]);
231         GC_push_one(state.__r[1]);
232         GC_push_one(state.__r[2]);
233         GC_push_one(state.__r[3]);
234         GC_push_one(state.__r[4]);
235         GC_push_one(state.__r[5]);
236         GC_push_one(state.__r[6]);
237         GC_push_one(state.__r[7]);
238         GC_push_one(state.__r[8]);
239         GC_push_one(state.__r[9]);
240         GC_push_one(state.__r[10]);
241         GC_push_one(state.__r[11]);
242         GC_push_one(state.__r[12]);
243         /* GC_push_one(state.__sp);  */
244         GC_push_one(state.__lr);
245         GC_push_one(state.__pc);
246         GC_push_one(state.__cpsr);
247 #else
248 # error FIXME for non-x86 || ppc architectures
249 #endif
250       } /* p != me */
251       if(p->flags & MAIN_THREAD)
252         hi = GC_stackbottom;
253       else
254         hi = p->stack_end;
255 #if DEBUG_THREADS
256       GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
257                  (unsigned long) p -> id,
258                  (unsigned long) lo,
259                  (unsigned long) hi
260                  );
261 #endif
262       GC_push_all_stack(lo,hi);
263     } /* for(p=GC_threads[i]...) */
264   } /* for(i=0;i<THREAD_TABLE_SZ...) */
265 }
266
267 #else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */
268
269 void GC_push_all_stacks() {
270     int i;
271         task_t my_task;
272     kern_return_t r;
273     mach_port_t me;
274     ptr_t lo, hi;
275     thread_act_array_t act_list = 0;
276     mach_msg_type_number_t listcount = 0;
277
278     me = mach_thread_self();
279     if (!GC_thr_initialized) GC_thr_init();
280     
281         my_task = current_task();
282     r = task_threads(my_task, &act_list, &listcount);
283     if(r != KERN_SUCCESS) ABORT("task_threads failed");
284     for(i = 0; i < listcount; i++) {
285       thread_act_t thread = act_list[i];
286       if (thread == me) {
287         lo = GC_approx_sp();
288         hi = (ptr_t)FindTopOfStack(0);
289       } else {
290 #     if defined(POWERPC)
291 #      if CPP_WORDSZ == 32
292         ppc_thread_state_t info;
293 #      else
294         ppc_thread_state64_t info;
295 #      endif
296         mach_msg_type_number_t outCount = THREAD_STATE_MAX;
297         r = thread_get_state(thread, GC_MACH_THREAD_STATE_FLAVOR,
298                              (natural_t *)&info, &outCount);
299         if(r != KERN_SUCCESS) continue;
300
301 #if defined(_STRUCT_PPC_EXCEPTION_STATE)
302         lo = (void*)(info.__r1 - PPC_RED_ZONE_SIZE);
303         hi = (ptr_t)FindTopOfStack(info.__r1);
304
305         GC_push_one(info.__r0); 
306         GC_push_one(info.__r2); 
307         GC_push_one(info.__r3); 
308         GC_push_one(info.__r4); 
309         GC_push_one(info.__r5); 
310         GC_push_one(info.__r6); 
311         GC_push_one(info.__r7); 
312         GC_push_one(info.__r8); 
313         GC_push_one(info.__r9); 
314         GC_push_one(info.__r10); 
315         GC_push_one(info.__r11); 
316         GC_push_one(info.__r12); 
317         GC_push_one(info.__r13); 
318         GC_push_one(info.__r14); 
319         GC_push_one(info.__r15); 
320         GC_push_one(info.__r16); 
321         GC_push_one(info.__r17); 
322         GC_push_one(info.__r18); 
323         GC_push_one(info.__r19); 
324         GC_push_one(info.__r20); 
325         GC_push_one(info.__r21); 
326         GC_push_one(info.__r22); 
327         GC_push_one(info.__r23); 
328         GC_push_one(info.__r24); 
329         GC_push_one(info.__r25); 
330         GC_push_one(info.__r26); 
331         GC_push_one(info.__r27); 
332         GC_push_one(info.__r28); 
333         GC_push_one(info.__r29); 
334         GC_push_one(info.__r30); 
335         GC_push_one(info.__r31);
336 #else
337         lo = (void*)(info.r1 - PPC_RED_ZONE_SIZE);
338         hi = (ptr_t)FindTopOfStack(info.r1);
339
340         GC_push_one(info.r0); 
341         GC_push_one(info.r2); 
342         GC_push_one(info.r3); 
343         GC_push_one(info.r4); 
344         GC_push_one(info.r5); 
345         GC_push_one(info.r6); 
346         GC_push_one(info.r7); 
347         GC_push_one(info.r8); 
348         GC_push_one(info.r9); 
349         GC_push_one(info.r10); 
350         GC_push_one(info.r11); 
351         GC_push_one(info.r12); 
352         GC_push_one(info.r13); 
353         GC_push_one(info.r14); 
354         GC_push_one(info.r15); 
355         GC_push_one(info.r16); 
356         GC_push_one(info.r17); 
357         GC_push_one(info.r18); 
358         GC_push_one(info.r19); 
359         GC_push_one(info.r20); 
360         GC_push_one(info.r21); 
361         GC_push_one(info.r22); 
362         GC_push_one(info.r23); 
363         GC_push_one(info.r24); 
364         GC_push_one(info.r25); 
365         GC_push_one(info.r26); 
366         GC_push_one(info.r27); 
367         GC_push_one(info.r28); 
368         GC_push_one(info.r29); 
369         GC_push_one(info.r30); 
370         GC_push_one(info.r31);
371 #endif
372 #      elif defined(I386) /* !POWERPC */
373         /* FIXME: Remove after testing: */
374         WARN("This is completely untested and likely will not work\n", 0);
375         i386_thread_state_t info;
376         mach_msg_type_number_t outCount = THREAD_STATE_MAX;
377         r = thread_get_state(thread, GC_MACH_THREAD_STATE_FLAVOR,
378                              (natural_t *)&info, &outCount);
379         if(r != KERN_SUCCESS) continue;
380
381 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
382         lo = (void*)info.__esp;
383         hi = (ptr_t)FindTopOfStack(info.__esp);
384
385         GC_push_one(info.__eax); 
386         GC_push_one(info.__ebx); 
387         GC_push_one(info.__ecx); 
388         GC_push_one(info.__edx); 
389         GC_push_one(info.__edi); 
390         GC_push_one(info.__esi); 
391         GC_push_one(info.__ebp);
392         /* GC_push_one(info.__esp);  */
393         GC_push_one(info.__ss); 
394         GC_push_one(info.__eip); 
395         GC_push_one(info.__cs); 
396         GC_push_one(info.__ds); 
397         GC_push_one(info.__es); 
398         GC_push_one(info.__fs); 
399         GC_push_one(info.__gs); 
400 #else
401         lo = (void*)info.esp;
402         hi = (ptr_t)FindTopOfStack(info.esp);
403
404         GC_push_one(info.eax); 
405         GC_push_one(info.ebx); 
406         GC_push_one(info.ecx); 
407         GC_push_one(info.edx); 
408         GC_push_one(info.edi); 
409         GC_push_one(info.esi); 
410         GC_push_one(info.ebp);
411         /* GC_push_one(info.esp);  */
412         GC_push_one(info.ss); 
413         GC_push_one(info.eip); 
414         GC_push_one(info.cs); 
415         GC_push_one(info.ds); 
416         GC_push_one(info.es); 
417         GC_push_one(info.fs); 
418         GC_push_one(info.gs); 
419 #endif
420 #      elif defined(ARM) /* !I386 */
421         arm_thread_state_t info;
422         mach_msg_type_number_t outCount = THREAD_STATE_MAX;
423         r = thread_get_state(thread, GC_MACH_THREAD_STATE_FLAVOR,
424                              (natural_t *)&info, &outCount);
425         if(r != KERN_SUCCESS) continue;
426
427         lo = (void*)info.__sp;
428         hi = (ptr_t)FindTopOfStack(info.__sp);
429
430         GC_push_one(info.__r[0]); 
431         GC_push_one(info.__r[1]); 
432         GC_push_one(info.__r[2]); 
433         GC_push_one(info.__r[3]); 
434         GC_push_one(info.__r[4]); 
435         GC_push_one(info.__r[5]); 
436         GC_push_one(info.__r[6]); 
437         GC_push_one(info.__r[7]); 
438         GC_push_one(info.__r[8]); 
439         GC_push_one(info.__r[9]); 
440         GC_push_one(info.__r[10]); 
441         GC_push_one(info.__r[11]); 
442         GC_push_one(info.__r[12]); 
443         /* GC_push_one(info.__sp);  */
444         GC_push_one(info.__lr); 
445         GC_push_one(info.__pc); 
446         GC_push_one(info.__cpsr); 
447 #      endif /* !ARM */
448       }
449 #     if DEBUG_THREADS
450        GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
451                   (unsigned long) thread,
452                   (unsigned long) lo,
453                   (unsigned long) hi
454                  );
455 #     endif
456       GC_push_all_stack(lo, hi);
457           mach_port_deallocate(my_task, thread);
458     } /* for(p=GC_threads[i]...) */
459     vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount);
460         mach_port_deallocate(my_task, me);
461 }
462 #endif /* !DARWIN_DONT_PARSE_STACK */
463
464 static mach_port_t GC_mach_handler_thread;
465 static int GC_use_mach_handler_thread = 0;
466
467 #define SUSPEND_THREADS_SIZE 2048
468 static struct GC_mach_thread GC_mach_threads[SUSPEND_THREADS_SIZE];
469 static int GC_mach_threads_count;
470
471 void GC_stop_init() {
472   int i;
473
474   for (i = 0; i < SUSPEND_THREADS_SIZE; i++) {
475     GC_mach_threads[i].thread = 0;
476     GC_mach_threads[i].already_suspended = 0;
477   }
478   GC_mach_threads_count = 0;
479 }
480
481 /* returns true if there's a thread in act_list that wasn't in old_list */
482 int GC_suspend_thread_list(thread_act_array_t act_list, int count, 
483                            thread_act_array_t old_list, int old_count) {
484   mach_port_t my_thread = mach_thread_self();
485   int i, j;
486
487   int changed = 0;
488
489   for(i = 0; i < count; i++) {
490     thread_act_t thread = act_list[i];
491 #   if DEBUG_THREADS 
492       GC_printf1("Attempting to suspend thread %p\n", thread);
493 #   endif
494     /* find the current thread in the old list */
495     int found = 0;
496     for(j = 0; j < old_count; j++) {
497       thread_act_t old_thread = old_list[j];
498       if (old_thread == thread) {
499         found = 1;
500         break;
501       }
502     }
503     if (!found) {
504       /* add it to the GC_mach_threads list */
505       GC_mach_threads[GC_mach_threads_count].thread = thread;
506       /* default is not suspended */
507       GC_mach_threads[GC_mach_threads_count].already_suspended = 0;
508       changed = 1;
509     }      
510
511     if (thread != my_thread &&
512         (!GC_use_mach_handler_thread
513          || (GC_use_mach_handler_thread
514              && GC_mach_handler_thread != thread))) {
515       struct thread_basic_info info;
516       mach_msg_type_number_t outCount = THREAD_INFO_MAX;
517       kern_return_t kern_result = thread_info(thread, THREAD_BASIC_INFO,
518                                 (thread_info_t)&info, &outCount);
519       if(kern_result != KERN_SUCCESS) {
520         /* the thread may have quit since the thread_threads () call 
521          * we mark already_suspended so it's not dealt with anymore later
522          */
523         if (!found) {
524           GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
525           GC_mach_threads_count++;
526         }
527         continue;
528       }
529 #     if DEBUG_THREADS
530         GC_printf2("Thread state for 0x%lx = %d\n", thread, info.run_state);
531 #     endif
532       if (!found) {
533         GC_mach_threads[GC_mach_threads_count].already_suspended = info.suspend_count;
534       }
535       if (info.suspend_count) continue;
536       
537 #     if DEBUG_THREADS
538         GC_printf1("Suspending 0x%lx\n", thread);
539 #     endif
540       /* Suspend the thread */
541       kern_result = thread_suspend(thread);
542       if(kern_result != KERN_SUCCESS) {
543         /* the thread may have quit since the thread_threads () call 
544          * we mark already_suspended so it's not dealt with anymore later
545          */
546         if (!found) {
547           GC_mach_threads[GC_mach_threads_count].already_suspended = TRUE;
548           GC_mach_threads_count++;
549         }
550         continue;
551       }
552     } 
553     if (!found) GC_mach_threads_count++;
554   }
555   
556   mach_port_deallocate(current_task(), my_thread);
557   return changed;
558 }
559
560
561 /* Caller holds allocation lock.        */
562 void GC_stop_world()
563 {
564   int i, changes;
565     GC_thread p;
566         task_t my_task = current_task();
567     mach_port_t my_thread = mach_thread_self();
568     kern_return_t kern_result;
569     thread_act_array_t act_list, prev_list;
570     mach_msg_type_number_t listcount, prevcount;
571     
572 #   if DEBUG_THREADS
573       GC_printf1("Stopping the world from 0x%lx\n", mach_thread_self());
574 #   endif
575
576     /* clear out the mach threads list table */
577     GC_stop_init(); 
578        
579     /* Make sure all free list construction has stopped before we start. */
580     /* No new construction can start, since free list construction is   */
581     /* required to acquire and release the GC lock before it starts,    */
582     /* and we have the lock.                                            */
583 #   ifdef PARALLEL_MARK
584       GC_acquire_mark_lock();
585       GC_ASSERT(GC_fl_builder_count == 0);
586       /* We should have previously waited for it to become zero. */
587 #   endif /* PARALLEL_MARK */
588
589       /* Loop stopping threads until you have gone over the whole list
590          twice without a new one appearing. thread_create() won't
591          return (and thus the thread stop) until the new thread
592          exists, so there is no window whereby you could stop a
593          thread, recognise it is stopped, but then have a new thread
594          it created before stopping show up later.
595       */
596       
597       changes = 1;
598       prev_list = NULL;
599       prevcount = 0;
600       do {
601         int result;               
602         kern_result = task_threads(my_task, &act_list, &listcount);
603         
604         if(kern_result == KERN_SUCCESS) {       
605                 result = GC_suspend_thread_list(act_list, listcount,
606                                                                                 prev_list, prevcount);
607                 changes = result;
608                 
609                 if(prev_list != NULL) {
610                         for(i = 0; i < prevcount; i++)
611                                 mach_port_deallocate(my_task, prev_list[i]);
612                         
613                         vm_deallocate(my_task, (vm_address_t)prev_list, sizeof(thread_t) * prevcount);
614                 }
615                 
616                 prev_list = act_list;
617                 prevcount = listcount;
618         }               
619       } while (changes);
620      
621           for(i = 0; i < listcount; i++)
622                   mach_port_deallocate(my_task, act_list[i]);
623           
624           vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount);
625           
626  
627 #   ifdef MPROTECT_VDB
628       if(GC_incremental) {
629         extern void GC_mprotect_stop();
630         GC_mprotect_stop();
631       }
632 #   endif
633     
634 #   ifdef PARALLEL_MARK
635       GC_release_mark_lock();
636 #   endif
637     #if DEBUG_THREADS
638       GC_printf1("World stopped from 0x%lx\n", my_thread);
639     #endif
640           
641           mach_port_deallocate(my_task, my_thread);
642 }
643
644 /* Caller holds allocation lock, and has held it continuously since     */
645 /* the world stopped.                                                   */
646 void GC_start_world()
647 {
648   task_t my_task = current_task();
649   mach_port_t my_thread = mach_thread_self();
650   int i, j;
651   GC_thread p;
652   kern_return_t kern_result;
653   thread_act_array_t act_list;
654   mach_msg_type_number_t listcount;
655   struct thread_basic_info info;
656   mach_msg_type_number_t outCount = THREAD_INFO_MAX;
657   
658 #   if DEBUG_THREADS
659       GC_printf0("World starting\n");
660 #   endif
661
662 #   ifdef MPROTECT_VDB
663       if(GC_incremental) {
664         extern void GC_mprotect_resume();
665         GC_mprotect_resume();
666       }
667 #   endif
668
669     kern_result = task_threads(my_task, &act_list, &listcount);
670     for(i = 0; i < listcount; i++) {
671       thread_act_t thread = act_list[i];
672       if (thread != my_thread &&
673           (!GC_use_mach_handler_thread ||
674            (GC_use_mach_handler_thread && GC_mach_handler_thread != thread))) {
675         for(j = 0; j < GC_mach_threads_count; j++) {
676           if (thread == GC_mach_threads[j].thread) {
677             if (GC_mach_threads[j].already_suspended) {
678 #             if DEBUG_THREADS
679                 GC_printf1("Not resuming already suspended thread %p\n", thread);
680 #             endif
681               continue;
682             }
683             kern_result = thread_info(thread, THREAD_BASIC_INFO,
684                                       (thread_info_t)&info, &outCount);
685             if(kern_result != KERN_SUCCESS) continue;
686 #           if DEBUG_THREADS
687               GC_printf2("Thread state for 0x%lx = %d\n", thread,
688                          info.run_state);
689               GC_printf1("Resuming 0x%lx\n", thread);
690 #           endif
691             /* Resume the thread */
692             kern_result = thread_resume(thread);
693             if(kern_result != KERN_SUCCESS) continue;
694           } 
695         }
696       }
697           
698           mach_port_deallocate(my_task, thread);
699     }
700     vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount);
701         
702         mach_port_deallocate(my_task, my_thread);
703 #   if DEBUG_THREADS
704      GC_printf0("World started\n");
705 #   endif
706 }
707
708 void GC_darwin_register_mach_handler_thread(mach_port_t thread) {
709   GC_mach_handler_thread = thread;
710   GC_use_mach_handler_thread = 1;
711 }
712
713 #ifdef MONO_DEBUGGER_SUPPORTED
714 GCThreadFunctions *gc_thread_vtable = NULL;
715
716 void *
717 GC_mono_debugger_get_stack_ptr (void)
718 {
719         GC_thread me;
720
721         me = GC_lookup_thread (pthread_self ());
722         return &me->stop_info.stack_ptr;
723 }
724 #endif
725
726 #endif