Merge pull request #3023 from lambdageek/dev/monoerror-minisig
[mono-project.git] / libgc / openbsd_stop_world.c
bloba4c927e6a3cf0eb3df466dc4e1136ec8f55b7767
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;
14 size_t nthreads = 0;
15 int i;
16 GC_thread p;
17 ptr_t lo, hi;
18 pthread_t me = pthread_self();
20 if (!GC_thr_initialized) GC_thr_init();
21 # if DEBUG_THREADS
22 GC_printf("Pushing stacks from thread 0x%x\n", (unsigned) me);
23 # endif
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;
27 ++nthreads;
28 if (THREAD_EQUAL(p -> id, me)) {
29 # ifdef SPARC
30 lo = (ptr_t)GC_save_regs_in_stack();
31 # else
32 lo = GC_approx_sp();
33 # endif
34 found_me = TRUE;
35 } else {
36 lo = p -> stop_info.stack_ptr;
38 if ((p -> flags & MAIN_THREAD) == 0) {
39 hi = p -> stack_end;
40 } else {
41 /* The original stack. */
42 hi = GC_stackbottom;
44 # if DEBUG_THREADS
45 GC_printf("Stack for thread 0x%x = [%p,%p)\n",
46 (unsigned)(p -> id), lo, hi);
47 # endif
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);
52 # else
53 GC_push_all_stack(lo, hi);
54 # endif
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. */
63 void GC_suspend_all()
65 int i;
66 GC_thread p;
67 int result;
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;
75 # if DEBUG_THREADS
76 GC_printf("Suspending thread 0x%x\n",
77 (unsigned)(p -> id));
78 # endif
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);
96 void GC_stop_world()
98 int i;
100 GC_ASSERT(I_HOLD_LOCK());
101 # if DEBUG_THREADS
102 GC_printf("Stopping the world from 0x%x\n", (unsigned)pthread_self());
103 # endif
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 */
115 GC_suspend_all();
117 # ifdef PARALLEL_MARK
118 GC_release_mark_lock();
119 # endif
120 #if DEBUG_THREADS
121 GC_printf("World stopped from 0x%x\n", (unsigned)pthread_self());
122 #endif
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();
130 register int i;
131 register GC_thread p;
132 register int result;
134 # if DEBUG_THREADS
135 GC_printf("World starting\n");
136 # endif
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;
143 #if DEBUG_THREADS
144 GC_printf("Resuming thread 0x%x\n",
145 (unsigned)(p -> id));
146 #endif
148 if (pthread_resume_np(p -> id) != 0)
149 ABORT("pthread_kill failed");
153 # if DEBUG_THREADS
154 GC_printf("World started\n");
155 # endif
158 void GC_stop_init() {
161 #endif