Annotation of OpenXM_contrib2/asir2000/gc/darwin_stop_world.c, Revision 1.1
1.1 ! noro 1: #include "private/pthread_support.h"
! 2:
! 3: # if defined(GC_DARWIN_THREADS)
! 4:
! 5: #define DEBUG_THREADS 0
! 6:
! 7: /* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
! 8: Page 49:
! 9: "The space beneath the stack pointer, where a new stack frame would normally
! 10: be allocated, is called the red zone. This area as shown in Figure 3-2 may
! 11: be used for any purpose as long as a new stack frame does not need to be
! 12: added to the stack."
! 13:
! 14: Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then
! 15: it must set up a stack frame just like routines that call other routines."
! 16: */
! 17: #define PPC_RED_ZONE_SIZE 224
! 18:
! 19: void GC_push_all_stacks() {
! 20: int i;
! 21: kern_return_t r;
! 22: GC_thread p;
! 23: pthread_t me;
! 24: ptr_t lo, hi;
! 25: # if defined(POWERPC)
! 26: ppc_thread_state_t state;
! 27: # else
! 28: # error FIXME for non-ppc OS X
! 29: # endif
! 30: mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
! 31:
! 32: me = pthread_self();
! 33: if (!GC_thr_initialized) GC_thr_init();
! 34:
! 35: for(i=0;i<THREAD_TABLE_SZ;i++) {
! 36: for(p=GC_threads[i];p!=0;p=p->next) {
! 37: if(p -> flags & FINISHED) continue;
! 38: if(pthread_equal(p->id,me)) {
! 39: lo = GC_approx_sp();
! 40: } else {
! 41: /* Get the thread state (registers, etc) */
! 42: r = thread_get_state(
! 43: p->stop_info.mach_thread,
! 44: MACHINE_THREAD_STATE,
! 45: (natural_t*)&state,
! 46: &thread_state_count);
! 47: if(r != KERN_SUCCESS) ABORT("thread_get_state failed");
! 48:
! 49: #ifdef POWERPC
! 50: lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE);
! 51:
! 52: GC_push_one(state.r0);
! 53: GC_push_one(state.r2);
! 54: GC_push_one(state.r3);
! 55: GC_push_one(state.r4);
! 56: GC_push_one(state.r5);
! 57: GC_push_one(state.r6);
! 58: GC_push_one(state.r7);
! 59: GC_push_one(state.r8);
! 60: GC_push_one(state.r9);
! 61: GC_push_one(state.r10);
! 62: GC_push_one(state.r11);
! 63: GC_push_one(state.r12);
! 64: GC_push_one(state.r13);
! 65: GC_push_one(state.r14);
! 66: GC_push_one(state.r15);
! 67: GC_push_one(state.r16);
! 68: GC_push_one(state.r17);
! 69: GC_push_one(state.r18);
! 70: GC_push_one(state.r19);
! 71: GC_push_one(state.r20);
! 72: GC_push_one(state.r21);
! 73: GC_push_one(state.r22);
! 74: GC_push_one(state.r23);
! 75: GC_push_one(state.r24);
! 76: GC_push_one(state.r25);
! 77: GC_push_one(state.r26);
! 78: GC_push_one(state.r27);
! 79: GC_push_one(state.r28);
! 80: GC_push_one(state.r29);
! 81: GC_push_one(state.r30);
! 82: GC_push_one(state.r31);
! 83: #else
! 84: # error FIXME for non-PPC darwin
! 85: #endif /* !POWERPC */
! 86: } /* p != me */
! 87: if(p->flags & MAIN_THREAD)
! 88: hi = GC_stackbottom;
! 89: else
! 90: hi = p->stack_end;
! 91: #if DEBUG_THREADS
! 92: GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n",
! 93: (unsigned long) p -> id,
! 94: (unsigned long) lo,
! 95: (unsigned long) hi
! 96: );
! 97: #endif
! 98: GC_push_all_stack(lo,hi);
! 99: } /* for(p=GC_threads[i]...) */
! 100: } /* for(i=0;i<THREAD_TABLE_SZ...) */
! 101: }
! 102:
! 103: /* Caller holds allocation lock. */
! 104: void GC_stop_world()
! 105: {
! 106: int i;
! 107: GC_thread p;
! 108: pthread_t my_thread = pthread_self();
! 109: kern_return_t kern_result;
! 110:
! 111: #if DEBUG_THREADS
! 112: GC_printf1("Stopping the world from 0x%lx\n", pthread_self());
! 113: #endif
! 114:
! 115: /* Make sure all free list construction has stopped before we start. */
! 116: /* No new construction can start, since free list construction is */
! 117: /* required to acquire and release the GC lock before it starts, */
! 118: /* and we have the lock. */
! 119: # ifdef PARALLEL_MARK
! 120: GC_acquire_mark_lock();
! 121: GC_ASSERT(GC_fl_builder_count == 0);
! 122: /* We should have previously waited for it to become zero. */
! 123: # endif /* PARALLEL_MARK */
! 124:
! 125: for (i = 0; i < THREAD_TABLE_SZ; i++) {
! 126: for (p = GC_threads[i]; p != 0; p = p -> next) {
! 127: if (p -> id == my_thread) continue;
! 128: if (p -> flags & FINISHED) continue;
! 129: if (p -> thread_blocked) /* Will wait */ continue;
! 130:
! 131: #if DEBUG_THREADS
! 132: GC_printf1("Suspending thread 0x%lx\n", p -> id);
! 133: #endif
! 134:
! 135: /* Suspend the thread */
! 136: kern_result = thread_suspend(p->stop_info.mach_thread);
! 137: if(kern_result != KERN_SUCCESS) ABORT("thread_suspend failed");
! 138:
! 139: /* abort any mach calls */
! 140: kern_result = thread_abort(p->stop_info.mach_thread);
! 141: /* This shouldn't really be fatal, I don't think. The documentation is kind of unclear */
! 142: if(kern_result != KERN_SUCCESS) GC_printf1("thread_abort_safely failed (%ul)",kern_result);
! 143: }
! 144: }
! 145:
! 146: # ifdef MPROTECT_VDB
! 147: if(GC_incremental) {
! 148: extern void GC_mprotect_stop();
! 149: GC_mprotect_stop();
! 150: }
! 151: # endif
! 152:
! 153: # ifdef PARALLEL_MARK
! 154: GC_release_mark_lock();
! 155: # endif
! 156: #if DEBUG_THREADS
! 157: GC_printf1("World stopped from 0x%lx\n", pthread_self());
! 158: #endif
! 159: }
! 160:
! 161: /* Caller holds allocation lock, and has held it continuously since */
! 162: /* the world stopped. */
! 163: void GC_start_world()
! 164: {
! 165: pthread_t my_thread = pthread_self();
! 166: int i;
! 167: GC_thread p;
! 168: kern_return_t kern_result;
! 169:
! 170: # if DEBUG_THREADS
! 171: GC_printf0("World starting\n");
! 172: # endif
! 173:
! 174: # ifdef MPROTECT_VDB
! 175: if(GC_incremental) {
! 176: extern void GC_mprotect_resume();
! 177: GC_mprotect_resume();
! 178: }
! 179: # endif
! 180:
! 181: for (i = 0; i < THREAD_TABLE_SZ; i++) {
! 182: for (p = GC_threads[i]; p != 0; p = p -> next) {
! 183: if (p -> id == my_thread) continue;
! 184: if (p -> flags & FINISHED) continue;
! 185: if (p -> thread_blocked) continue;
! 186:
! 187: #if DEBUG_THREADS
! 188: GC_printf1("Resuming 0x%lx\n", p -> id);
! 189: #endif
! 190:
! 191: /* Resume the thread */
! 192: kern_result = thread_resume(p->stop_info.mach_thread);
! 193: if(kern_result != KERN_SUCCESS) ABORT("thread_resume failed");
! 194: }
! 195: }
! 196: #if DEBUG_THREADS
! 197: GC_printf0("World started\n");
! 198: #endif
! 199: }
! 200:
! 201: void GC_stop_init() {
! 202:
! 203: }
! 204:
! 205: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>