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

📄 pthread_support.c

📁 linux下建立JAVA虚拟机的源码KAFFE
💻 C
📖 第 1 页 / 共 4 页
字号:
      GC_release_mark_lock();#   endif    GC_remove_all_threads_but_me();#   ifdef PARALLEL_MARK      /* Turn off parallel marking in the child, since we are probably 	*/      /* just going to exec, and we would have to restart mark threads.	*/        GC_markers = 1;        GC_parallel = FALSE;#   endif /* PARALLEL_MARK */    UNLOCK();}#endif /* HANDLE_FORK */#if defined(GC_DGUX386_THREADS)/* Return the number of processors, or i<= 0 if it can't be determined. */int GC_get_nprocs(){    /* <takis@XFree86.Org> */    int numCpus;    struct dg_sys_info_pm_info pm_sysinfo;    int status =0;    status = dg_sys_info((long int *) &pm_sysinfo,	DG_SYS_INFO_PM_INFO_TYPE, DG_SYS_INFO_PM_CURRENT_VERSION);    if (status < 0)       /* set -1 for error */       numCpus = -1;    else      /* Active CPUs */      numCpus = pm_sysinfo.idle_vp_count;#  ifdef DEBUG_THREADS    GC_printf1("Number of active CPUs in this system: %d\n", numCpus);#  endif    return(numCpus);}#endif /* GC_DGUX386_THREADS *//* We hold the allocation lock.	*/void GC_thr_init(){#   ifndef GC_DARWIN_THREADS      int dummy;#   endif    GC_thread t;    if (GC_thr_initialized) return;    GC_thr_initialized = TRUE;    #   ifdef HANDLE_FORK      /* Prepare for a possible fork.	*/        pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,	  	       GC_fork_child_proc);#   endif /* HANDLE_FORK */    /* Add the initial thread, so we can stop it.	*/      t = GC_new_thread(pthread_self());#     ifdef GC_DARWIN_THREADS         t -> stop_info.mach_thread = mach_thread_self();#     else         t -> stop_info.stack_ptr = (ptr_t)(&dummy);#     endif      t -> flags = DETACHED | MAIN_THREAD;    GC_stop_init();    /* Set GC_nprocs.  */      {	char * nprocs_string = GETENV("GC_NPROCS");	GC_nprocs = -1;	if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);      }      if (GC_nprocs <= 0) {#       if defined(GC_HPUX_THREADS)	  GC_nprocs = pthread_num_processors_np();#       endif#	if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS)	  GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);	  if (GC_nprocs <= 0) GC_nprocs = 1;#	endif#       if defined(GC_IRIX_THREADS)	  GC_nprocs = sysconf(_SC_NPROC_ONLN);	  if (GC_nprocs <= 0) GC_nprocs = 1;#       endif#       if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)	  int ncpus = 1;	  size_t len = sizeof(ncpus);	  sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);	  GC_nprocs = ncpus;#       endif#	if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)          GC_nprocs = GC_get_nprocs();#	endif      }      if (GC_nprocs <= 0) {	WARN("GC_get_nprocs() returned %ld\n", GC_nprocs);	GC_nprocs = 2;#	ifdef PARALLEL_MARK	  GC_markers = 1;#	endif      } else {#	ifdef PARALLEL_MARK          {	    char * markers_string = GETENV("GC_MARKERS");	    if (markers_string != NULL) {	      GC_markers = atoi(markers_string);	    } else {	      GC_markers = GC_nprocs;	    }          }#	endif      }#   ifdef PARALLEL_MARK#     ifdef CONDPRINT        if (GC_print_stats) {          GC_printf2("Number of processors = %ld, "		 "number of marker threads = %ld\n", GC_nprocs, GC_markers);	}#     endif      if (GC_markers == 1) {	GC_parallel = FALSE;#	ifdef CONDPRINT	  if (GC_print_stats) {	    GC_printf0("Single marker thread, turning off parallel marking\n");	  }#	endif      } else {	GC_parallel = TRUE;	/* Disable true incremental collection, but generational is OK.	*/	GC_time_limit = GC_TIME_UNLIMITED;      }      /* If we are using a parallel marker, actually start helper threads.  */        if (GC_parallel) start_mark_threads();#   endif}/* Perform all initializations, including those that	*//* may require allocation.				*//* Called without allocation lock.			*//* Must be called before a second thread is created.	*//* Called without allocation lock.			*/void GC_init_parallel(){    if (parallel_initialized) return;    parallel_initialized = TRUE;    /* GC_init() calls us back, so set flag first.	*/    if (!GC_is_initialized) GC_init();    /* Initialize thread local free lists if used.	*/#   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)      LOCK();      GC_init_thread_local(GC_lookup_thread(pthread_self()));      UNLOCK();#   endif}#if !defined(GC_DARWIN_THREADS)int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset){    sigset_t fudged_set;        if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) {        fudged_set = *set;        sigdelset(&fudged_set, SIG_SUSPEND);        set = &fudged_set;    }    return(REAL_FUNC(pthread_sigmask)(how, set, oset));}#endif /* !GC_DARWIN_THREADS *//* Wrappers for functions that are likely to block for an appreciable	*//* length of time.  Must be called in pairs, if at all.			*//* Nothing much beyond the system call itself should be executed	*//* between these.							*/void GC_start_blocking(void) {#   define SP_SLOP 128    GC_thread me;    LOCK();    me = GC_lookup_thread(pthread_self());    GC_ASSERT(!(me -> thread_blocked));#   ifdef SPARC	me -> stop_info.stack_ptr = (ptr_t)GC_save_regs_in_stack();#   else#   ifndef GC_DARWIN_THREADS	me -> stop_info.stack_ptr = (ptr_t)GC_approx_sp();#   endif#   endif#   ifdef IA64	me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack() + SP_SLOP;#   endif    /* Add some slop to the stack pointer, since the wrapped call may 	*/    /* end up pushing more callee-save registers.			*/#   ifndef GC_DARWIN_THREADS#   ifdef STACK_GROWS_UP	me -> stop_info.stack_ptr += SP_SLOP;#   else	me -> stop_info.stack_ptr -= SP_SLOP;#   endif#   endif    me -> thread_blocked = TRUE;    UNLOCK();}void GC_end_blocking(void) {    GC_thread me;    LOCK();   /* This will block if the world is stopped.	*/    me = GC_lookup_thread(pthread_self());    GC_ASSERT(me -> thread_blocked);    me -> thread_blocked = FALSE;    UNLOCK();}    #if defined(GC_DGUX386_THREADS)#define __d10_sleep sleep#endif /* GC_DGUX386_THREADS *//* A wrapper for the standard C sleep function	*/int WRAP_FUNC(sleep) (unsigned int seconds){    int result;    GC_start_blocking();    result = REAL_FUNC(sleep)(seconds);    GC_end_blocking();    return result;}struct start_info {    void *(*start_routine)(void *);    void *arg;    word flags;    sem_t registered;   	/* 1 ==> in our thread table, but 	*/				/* parent hasn't yet noticed.		*/};/* Called at thread exit.				*//* Never called for main thread.  That's OK, since it	*//* results in at most a tiny one-time leak.  And 	*//* linuxthreads doesn't reclaim the main threads 	*//* resources or id anyway.				*/void GC_thread_exit_proc(void *arg){    GC_thread me;    LOCK();    me = GC_lookup_thread(pthread_self());    GC_destroy_thread_local(me);    if (me -> flags & DETACHED) {    	GC_delete_thread(pthread_self());    } else {	me -> flags |= FINISHED;    }#   if defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_SPECIFIC) \       && !defined(USE_COMPILER_TLS) && !defined(DBG_HDRS_ALL)      GC_remove_specific(GC_thread_key);#   endif    /* The following may run the GC from "nonexistent" thread.	*/    GC_wait_for_gc_completion(FALSE);    UNLOCK();}int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval){    int result;    GC_thread thread_gc_id;        LOCK();    thread_gc_id = GC_lookup_thread(thread);    /* This is guaranteed to be the intended one, since the thread id	*/    /* cant have been recycled by pthreads.				*/    UNLOCK();    result = REAL_FUNC(pthread_join)(thread, retval);# if defined (GC_FREEBSD_THREADS)    /* On FreeBSD, the wrapped pthread_join() sometimes returns (what       appears to be) a spurious EINTR which caused the test and real code       to gratuitously fail.  Having looked at system pthread library source       code, I see how this return code may be generated.  In one path of       code, pthread_join() just returns the errno setting of the thread       being joined.  This does not match the POSIX specification or the       local man pages thus I have taken the liberty to catch this one       spurious return value properly conditionalized on GC_FREEBSD_THREADS. */    if (result == EINTR) result = 0;# endif    if (result == 0) {        LOCK();        /* Here the pthread thread id may have been recycled. */        GC_delete_gc_thread(thread, thread_gc_id);        UNLOCK();    }    return result;}intWRAP_FUNC(pthread_detach)(pthread_t thread){    int result;    GC_thread thread_gc_id;        LOCK();    thread_gc_id = GC_lookup_thread(thread);    UNLOCK();    result = REAL_FUNC(pthread_detach)(thread);    if (result == 0) {      LOCK();      thread_gc_id -> flags |= DETACHED;      /* Here the pthread thread id may have been recycled. */      if (thread_gc_id -> flags & FINISHED) {        GC_delete_gc_thread(thread, thread_gc_id);      }      UNLOCK();    }    return result;}GC_bool GC_in_thread_creation = FALSE;void * GC_start_routine(void * arg){    int dummy;    struct start_info * si = arg;    void * result;    GC_thread me;    pthread_t my_pthread;    void *(*start)(void *);    void *start_arg;    my_pthread = pthread_self();#   ifdef DEBUG_THREADS        GC_printf1("Starting thread 0x%lx\n", my_pthread);        GC_printf1("pid = %ld\n", (long) getpid());        GC_printf1("sp = 0x%lx\n", (long) &arg);#   endif    LOCK();    GC_in_thread_creation = TRUE;    me = GC_new_thread(my_pthread);    GC_in_thread_creation = FALSE;#ifdef GC_DARWIN_THREADS    me -> stop_info.mach_thread = mach_thread_self();#else    me -> stop_info.stack_ptr = 0;#endif    me -> flags = si -> flags;    /* me -> stack_end = GC_linux_stack_base(); -- currently (11/99)	*/    /* doesn't work because the stack base in /proc/self/stat is the 	*/    /* one for the main thread.  There is a strong argument that that's	*/    /* a kernel bug, but a pervasive one.				*/#   ifdef STACK_GROWS_DOWN      me -> stack_end = (ptr_t)(((word)(&dummy) + (GC_page_size - 1))		                & ~(GC_page_size - 1));#	  ifndef GC_DARWIN_THREADS        me -> stop_info.stack_ptr = me -> stack_end - 0x10;#	  endif	/* Needs to be plausible, since an asynchronous stack mark	*/	/* should not crash.						*/#   else      me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1));      me -> stop_info.stack_ptr = me -> stack_end + 0x10;#   endif    /* This is dubious, since we may be more than a page into the stack, */    /* and hence skip some of it, though it's not clear that matters.	 */#   ifdef IA64      me -> backing_store_end = (ptr_t)			(GC_save_regs_in_stack() & ~(GC_page_size - 1));      /* This is also < 100% convincing.  We should also read this 	*/      /* from /proc, but the hook to do so isn't there yet.		*/#   endif /* IA64 */    UNLOCK();    start = si -> start_routine;#   ifdef DEBUG_THREADS	GC_printf1("start_routine = 0x%lx\n", start);#   endif    start_arg = si -> arg;    sem_post(&(si -> registered));	/* Last action on si.	*/    					/* OK to deallocate.	*/    pthread_cleanup_push(GC_thread_exit_proc, 0);#   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL) 	LOCK();        GC_init_thread_local(me);	UNLOCK();#   endif    result = (*start)(start_arg);#if DEBUG_THREADS        GC_printf1("Finishing thread 0x%x\n", pthread_self());#endif    me -> status = result;    pthread_cleanup_pop(1);    /* Cleanup acquires lock, ensuring that we can't exit		*/    /* while a collection that thinks we're alive is trying to stop     */    /* us.								*/    return(result);}intWRAP_FUNC(pthread_create)(pthread_t *new_thread,		  const pthread_attr_t *attr,                  void *(*start_routine)(void *), void *arg){    int result;

⌨️ 快捷键说明

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