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() {