[BACK]Return to darwin_stop_world.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

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>