⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pthread_stop_world.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 2 页
字号:
    #if DEBUG_THREADS        GC_printf1("Pushing stacks from thread 0x%lx\n", (unsigned long) me);    #endif    for (i = 0; i < THREAD_TABLE_SZ; i++) {      for (p = GC_threads[i]; p != 0; p = p -> next) {        if (p -> flags & FINISHED) continue;        if (pthread_equal(p -> id, me)) {#  	    ifdef SPARC	        lo = (ptr_t)GC_save_regs_in_stack();#  	    else 	        lo = GC_approx_sp();#           endif	    found_me = TRUE;	    IF_IA64(bs_hi = (ptr_t)GC_save_regs_in_stack();)	} else {	    lo = p -> stop_info.stack_ptr;	    IF_IA64(bs_hi = p -> backing_store_ptr;)	}        if ((p -> flags & MAIN_THREAD) == 0) {	    hi = p -> stack_end;	    IF_IA64(bs_lo = p -> backing_store_end);        } else {            /* The original stack. */            hi = GC_stackbottom;	    IF_IA64(bs_lo = BACKING_STORE_BASE;)        }        #if DEBUG_THREADS            GC_printf3("Stack for thread 0x%lx = [%lx,%lx)\n",    	        (unsigned long) p -> id,		(unsigned long) lo, (unsigned long) hi);        #endif	if (0 == lo) ABORT("GC_push_all_stacks: sp not set!\n");#       ifdef STACK_GROWS_UP	  /* We got them backwards! */          GC_push_all_stack(hi, lo);#       else          GC_push_all_stack(lo, hi);#	endif#	ifdef IA64#         if DEBUG_THREADS            GC_printf3("Reg stack for thread 0x%lx = [%lx,%lx)\n",    	        (unsigned long) p -> id,		(unsigned long) bs_lo, (unsigned long) bs_hi);#	  endif          if (pthread_equal(p -> id, me)) {	    GC_push_all_eager(bs_lo, bs_hi);	  } else {	    GC_push_all_stack(bs_lo, bs_hi);	  }#	endif      }    }    if (!found_me && !GC_in_thread_creation)      ABORT("Collecting from unknown thread.");}/* There seems to be a very rare thread stopping problem.  To help us  *//* debug that, we save the ids of the stopping thread. */pthread_t GC_stopping_thread;int GC_stopping_pid;/* We hold the allocation lock.  Suspend all threads that might	*//* still be running.  Return the number of suspend signals that	*//* were sent. */int GC_suspend_all(){    int n_live_threads = 0;    int i;    GC_thread p;    int result;    pthread_t my_thread = pthread_self();        GC_stopping_thread = my_thread;    /* debugging only.      */    GC_stopping_pid = getpid();                /* debugging only.      */    for (i = 0; i < THREAD_TABLE_SZ; i++) {      for (p = GC_threads[i]; p != 0; p = p -> next) {        if (p -> id != my_thread) {            if (p -> flags & FINISHED) continue;            if (p -> stop_info.last_stop_count == GC_stop_count) continue;	    if (p -> thread_blocked) /* Will wait */ continue;            n_live_threads++;	    #if DEBUG_THREADS	      GC_printf1("Sending suspend signal to 0x%lx\n", p -> id);	    #endif                result = pthread_kill(p -> id, SIG_SUSPEND);	    switch(result) {                case ESRCH:                    /* Not really there anymore.  Possible? */                    n_live_threads--;                    break;                case 0:                    break;                default:                    ABORT("pthread_kill failed");            }        }      }    }    return n_live_threads;}/* Caller holds allocation lock.	*/void GC_stop_world(){    int i;    int n_live_threads;    int code;    #if DEBUG_THREADS    GC_printf1("Stopping the world from 0x%lx\n", pthread_self());    #endif           /* Make sure all free list construction has stopped before we start. */    /* No new construction can start, since free list construction is	*/    /* required to acquire and release the GC lock before it starts,	*/    /* and we have the lock.						*/#   ifdef PARALLEL_MARK      GC_acquire_mark_lock();      GC_ASSERT(GC_fl_builder_count == 0);      /* We should have previously waited for it to become zero. */#   endif /* PARALLEL_MARK */    ++GC_stop_count;    GC_world_is_stopped = TRUE;    n_live_threads = GC_suspend_all();      if (GC_retry_signals) {	  unsigned long wait_usecs = 0;  /* Total wait since retry.	*/#	  define WAIT_UNIT 3000#	  define RETRY_INTERVAL 100000	  for (;;) {	      int ack_count;	      sem_getvalue(&GC_suspend_ack_sem, &ack_count);	      if (ack_count == n_live_threads) break;	      if (wait_usecs > RETRY_INTERVAL) {		  int newly_sent = GC_suspend_all();#                 ifdef CONDPRINT		    if (GC_print_stats) {		      GC_printf1("Resent %ld signals after timeout\n",				 newly_sent);		    }#                 endif		  sem_getvalue(&GC_suspend_ack_sem, &ack_count);		  if (newly_sent < n_live_threads - ack_count) {		      WARN("Lost some threads during GC_stop_world?!\n",0);		      n_live_threads = ack_count + newly_sent;		  }		  wait_usecs = 0;	      }	      usleep(WAIT_UNIT);	      wait_usecs += WAIT_UNIT;	  }      }    for (i = 0; i < n_live_threads; i++) {	  while (0 != (code = sem_wait(&GC_suspend_ack_sem))) {	      if (errno != EINTR) {	         GC_err_printf1("Sem_wait returned %ld\n", (unsigned long)code);	         ABORT("sem_wait for handler failed");	      }	  }    }#   ifdef PARALLEL_MARK      GC_release_mark_lock();#   endif    #if DEBUG_THREADS      GC_printf1("World stopped from 0x%lx\n", pthread_self());    #endif    GC_stopping_thread = 0;  /* debugging only */}/* Caller holds allocation lock, and has held it continuously since	*//* the world stopped.							*/void GC_start_world(){    pthread_t my_thread = pthread_self();    register int i;    register GC_thread p;    register int n_live_threads = 0;    register int result;#   if DEBUG_THREADS      GC_printf0("World starting\n");#   endif    GC_world_is_stopped = FALSE;    for (i = 0; i < THREAD_TABLE_SZ; i++) {      for (p = GC_threads[i]; p != 0; p = p -> next) {        if (p -> id != my_thread) {            if (p -> flags & FINISHED) continue;	    if (p -> thread_blocked) continue;            n_live_threads++;	    #if DEBUG_THREADS	      GC_printf1("Sending restart signal to 0x%lx\n", p -> id);	    #endif            result = pthread_kill(p -> id, SIG_THR_RESTART);	    switch(result) {                case ESRCH:                    /* Not really there anymore.  Possible? */                    n_live_threads--;                    break;                case 0:                    break;                default:                    ABORT("pthread_kill failed");            }        }      }    }    #if DEBUG_THREADS      GC_printf0("World started\n");    #endif}void GC_stop_init() {    struct sigaction act;        if (sem_init(&GC_suspend_ack_sem, 0, 0) != 0)        ABORT("sem_init failed");    act.sa_flags = SA_RESTART;    if (sigfillset(&act.sa_mask) != 0) {    	ABORT("sigfillset() failed");    }    GC_remove_allowed_signals(&act.sa_mask);    /* SIG_THR_RESTART is set in the resulting mask.		*/    /* It is unmasked by the handler when necessary. 		*/    act.sa_handler = GC_suspend_handler;    if (sigaction(SIG_SUSPEND, &act, NULL) != 0) {    	ABORT("Cannot set SIG_SUSPEND handler");    }    act.sa_handler = GC_restart_handler;    if (sigaction(SIG_THR_RESTART, &act, NULL) != 0) {    	ABORT("Cannot set SIG_THR_RESTART handler");    }    /* Inititialize suspend_handler_mask. It excludes SIG_THR_RESTART. */      if (sigfillset(&suspend_handler_mask) != 0) ABORT("sigfillset() failed");      GC_remove_allowed_signals(&suspend_handler_mask);      if (sigdelset(&suspend_handler_mask, SIG_THR_RESTART) != 0)	  ABORT("sigdelset() failed");    /* Check for GC_RETRY_SIGNALS.	*/      if (0 != GETENV("GC_RETRY_SIGNALS")) {	  GC_retry_signals = TRUE;      }      if (0 != GETENV("GC_NO_RETRY_SIGNALS")) {	  GC_retry_signals = FALSE;      }#     ifdef CONDPRINT          if (GC_print_stats && GC_retry_signals) {              GC_printf0("Will retry suspend signal if necessary.\n");	  }#     endif}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -