1 #include "private/pthread_support.h"
3 /* derived from pthread_stop_world.c */
5 # if defined(GC_OPENBSD_THREADS)
7 #define THREAD_EQUAL(id1, id2) pthread_equal(id1, id2)
9 /* We hold allocation lock. Should do exactly the right thing if the */
10 /* world is stopped. Should not fail if it isn't. */
11 void GC_push_all_stacks()
13 GC_bool found_me = FALSE;
18 pthread_t me = pthread_self();
20 if (!GC_thr_initialized) GC_thr_init();
22 GC_printf("Pushing stacks from thread 0x%x\n", (unsigned) me);
24 for (i = 0; i < THREAD_TABLE_SZ; i++) {
25 for (p = GC_threads[i]; p != 0; p = p -> next) {
26 if (p -> flags & FINISHED) continue;
28 if (THREAD_EQUAL(p -> id, me)) {
30 lo = (ptr_t)GC_save_regs_in_stack();
36 lo = p -> stop_info.stack_ptr;
38 if ((p -> flags & MAIN_THREAD) == 0) {
41 /* The original stack. */
45 GC_printf("Stack for thread 0x%x = [%p,%p)\n",
46 (unsigned)(p -> id), lo, hi);
48 if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n");
49 # ifdef STACK_GROWS_UP
50 /* We got them backwards! */
51 GC_push_all_stack(hi, lo);
53 GC_push_all_stack(lo, hi);
57 if (!found_me && !GC_in_thread_creation)
58 ABORT("Collecting from unknown thread.");
61 /* We hold the allocation lock. Suspend all threads that might */
62 /* still be running. */
68 pthread_t my_thread = pthread_self();
70 for (i = 0; i < THREAD_TABLE_SZ; i++) {
71 for (p = GC_threads[i]; p != 0; p = p -> next) {
72 if (!THREAD_EQUAL(p -> id, my_thread)) {
73 if (p -> flags & FINISHED) continue;
74 if (p -> thread_blocked) /* Will wait */ continue;
76 GC_printf("Suspending thread 0x%x\n",
80 if (pthread_suspend_np(p -> id) != 0)
81 ABORT("pthread_suspend_np failed");
84 * This will only work for userland pthreads. It will
85 * fail badly on rthreads. Perhaps we should consider
86 * a pthread_sp_np() function that returns the stack
87 * pointer for a suspended thread and implement in
88 * both pthreads and rthreads.
90 p -> stop_info.stack_ptr = *(ptr_t*)((char *)p -> id + UTHREAD_SP_OFFSET);
100 GC_ASSERT(I_HOLD_LOCK());
102 GC_printf("Stopping the world from 0x%x\n", (unsigned)pthread_self());
105 /* Make sure all free list construction has stopped before we start. */
106 /* No new construction can start, since free list construction is */
107 /* required to acquire and release the GC lock before it starts, */
108 /* and we have the lock. */
109 # ifdef PARALLEL_MARK
110 GC_acquire_mark_lock();
111 GC_ASSERT(GC_fl_builder_count == 0);
112 /* We should have previously waited for it to become zero. */
113 # endif /* PARALLEL_MARK */
117 # ifdef PARALLEL_MARK
118 GC_release_mark_lock();
121 GC_printf("World stopped from 0x%x\n", (unsigned)pthread_self());
125 /* Caller holds allocation lock, and has held it continuously since */
126 /* the world stopped. */
127 void GC_start_world()
129 pthread_t my_thread = pthread_self();
131 register GC_thread p;
135 GC_printf("World starting\n");
138 for (i = 0; i < THREAD_TABLE_SZ; i++) {
139 for (p = GC_threads[i]; p != 0; p = p -> next) {
140 if (!THREAD_EQUAL(p -> id, my_thread)) {
141 if (p -> flags & FINISHED) continue;
142 if (p -> thread_blocked) continue;
144 GC_printf("Resuming thread 0x%x\n",
145 (unsigned)(p -> id));
148 if (pthread_resume_np(p -> id) != 0)
149 ABORT("pthread_kill failed");
154 GC_printf("World started\n");
158 void GC_stop_init() {