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

📄 pthread_stop_world.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 2 页
字号:
	    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_printf("Stack for thread 0x%x = [%p,%p)\n",    	              (unsigned)(p -> id), lo, 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_printf("Reg stack for thread 0x%x = [%lx,%lx)\n",    	              (unsigned)p -> id, bs_lo, bs_hi);#	  endif          if (THREAD_EQUAL(p -> id, me)) {	    /* FIXME:  This may add an unbounded number of entries,	*/	    /* and hence overflow the mark stack, which is bad.		*/	    GC_push_all_eager(bs_lo, bs_hi);	  } else {	    GC_push_all_stack(bs_lo, bs_hi);	  }#	endif      }    }    if (GC_print_stats == VERBOSE) {	GC_log_printf("Pushed %d thread stacks\n", nthreads);    }    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 (!THREAD_EQUAL(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_printf("Sending suspend signal to 0x%x\n",			(unsigned)(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;}void GC_stop_world(){    int i;    int n_live_threads;    int code;    GC_ASSERT(I_HOLD_LOCK());#   if DEBUG_THREADS      GC_printf("Stopping the world from 0x%x\n", (unsigned)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 */    AO_store(&GC_stop_count, GC_stop_count+1);    	/* Only concurrent reads are possible. */    AO_store_release(&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();		  if (GC_print_stats) {		      GC_log_printf("Resent %d signals after timeout\n",				newly_sent);		  }		  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++) {	retry:	  if (0 != (code = sem_wait(&GC_suspend_ack_sem))) {	      /* On Linux, sem_wait is documented to always return zero.*/	      /* But the documentation appears to be incorrect.		*/	      if (errno == EINTR) {		/* Seems to happen with some versions of gdb.	*/		goto retry;	      }	      ABORT("sem_wait for handler failed");	  }    }#   ifdef PARALLEL_MARK      GC_release_mark_lock();#   endif    #if DEBUG_THREADS      GC_printf("World stopped from 0x%x\n", (unsigned)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;#   ifdef GC_NETBSD_THREADS_WORKAROUND      int code;#   endif#   if DEBUG_THREADS      GC_printf("World starting\n");#   endif    AO_store(&GC_world_is_stopped, FALSE);    for (i = 0; i < THREAD_TABLE_SZ; i++) {      for (p = GC_threads[i]; p != 0; p = p -> next) {        if (!THREAD_EQUAL(p -> id, my_thread)) {            if (p -> flags & FINISHED) continue;	    if (p -> thread_blocked) continue;            n_live_threads++;	    #if DEBUG_THREADS	      GC_printf("Sending restart signal to 0x%x\n",			(unsigned)(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");            }        }      }    }#   ifdef GC_NETBSD_THREADS_WORKAROUND      for (i = 0; i < n_live_threads; i++)	while (0 != (code = sem_wait(&GC_restart_ack_sem)))	    if (errno != EINTR) {		GC_err_printf1("sem_wait() returned %ld\n",			       (unsigned long)code);		ABORT("sem_wait() for restart handler failed");	    }#    endif#    if DEBUG_THREADS      GC_printf("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");#   ifdef GC_NETBSD_THREADS_WORKAROUND      if (sem_init(&GC_restart_ack_sem, 0, 0) != 0)	ABORT("sem_init failed");#   endif    act.sa_flags = SA_RESTART | SA_SIGINFO;    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_sigaction = GC_suspend_handler;    if (sigaction(SIG_SUSPEND, &act, NULL) != 0) {    	ABORT("Cannot set SIG_SUSPEND handler");    }    act.sa_flags &= ~ SA_SIGINFO;    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;      }      if (GC_print_stats && GC_retry_signals) {          GC_log_printf("Will retry suspend signal if necessary.\n");      }}#endif

⌨️ 快捷键说明

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