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

📄 win32_threads.c

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 C
📖 第 1 页 / 共 4 页
字号:
    GC_ASSERT(I_HOLD_LOCK());    if (GC_thr_initialized) return;    GC_main_thread = GetCurrentThreadId();    GC_thr_initialized = TRUE;    /* Add the initial thread, so we can stop it.	*/    sb_result = GC_get_stack_base(&sb);    GC_ASSERT(sb_result == GC_SUCCESS);    GC_register_my_thread(&sb);}#ifdef GC_PTHREADSstruct start_info {    void *(*start_routine)(void *);    void *arg;    GC_bool detached;};int GC_pthread_join(pthread_t pthread_id, void **retval) {    int result;    int i;    GC_thread joinee;#   if DEBUG_CYGWIN_THREADS      GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",		(int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);#   endif#   if DEBUG_WIN32_PTHREADS      GC_printf("thread 0x%x(0x%x) is joining thread 0x%x.\n",		(int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);#   endif    if (!parallel_initialized) GC_init_parallel();    /* Thread being joined might not have registered itself yet. */    /* After the join,thread id may have been recycled.		 */    /* FIXME: It would be better if this worked more like	 */    /* pthread_support.c.					 */    #ifndef GC_WIN32_PTHREADS      while ((joinee = GC_lookup_pthread(pthread_id)) == 0) Sleep(10);    #endif    result = pthread_join(pthread_id, retval);    #ifdef GC_WIN32_PTHREADS      /* win32_pthreads id are unique */      joinee = GC_lookup_pthread(pthread_id);    #endif    if (!GC_win32_dll_threads) {      LOCK();      GC_delete_gc_thread(joinee);      UNLOCK();    } /* otherwise dllmain handles it.	*/#   if DEBUG_CYGWIN_THREADS      GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",		 (int)pthread_self(), GetCurrentThreadId(), (int)pthread_id);#   endif#   if DEBUG_WIN32_PTHREADS      GC_printf("thread 0x%x(0x%x) completed join with thread 0x%x.\n",		(int)(pthread_self()).p, GetCurrentThreadId(), pthread_id.p);#   endif    return result;}/* Cygwin-pthreads calls CreateThread internally, but it's not * easily interceptible by us.. *   so intercept pthread_create instead */intGC_pthread_create(pthread_t *new_thread,		  const pthread_attr_t *attr,                  void *(*start_routine)(void *), void *arg) {    int result;    struct start_info * si;    if (!parallel_initialized) GC_init_parallel();    		/* make sure GC is initialized (i.e. main thread is attached) */    if (GC_win32_dll_threads) {      return pthread_create(new_thread, attr, start_routine, arg);    }        /* This is otherwise saved only in an area mmapped by the thread */    /* library, which isn't visible to the collector.		 */    si = GC_malloc_uncollectable(sizeof(struct start_info));     if (0 == si) return(EAGAIN);    si -> start_routine = start_routine;    si -> arg = arg;    if (attr != 0 &&        pthread_attr_getdetachstate(attr, &si->detached)	== PTHREAD_CREATE_DETACHED) {      si->detached = TRUE;    }#   if DEBUG_CYGWIN_THREADS      GC_printf("About to create a thread from 0x%x(0x%x)\n",		(int)pthread_self(), GetCurrentThreadId);#   endif#   if DEBUG_WIN32_PTHREADS      GC_printf("About to create a thread from 0x%x(0x%x)\n",		(int)(pthread_self()).p, GetCurrentThreadId());#   endif    GC_need_to_lock = TRUE;    result = pthread_create(new_thread, attr, GC_pthread_start, si);     if (result) { /* failure */      	GC_free(si);    }     return(result);}void * GC_pthread_start_inner(struct GC_stack_base *sb, void * arg){    struct start_info * si = arg;    void * result;    void *(*start)(void *);    void *start_arg;    DWORD thread_id = GetCurrentThreadId();    pthread_t pthread_id = pthread_self();    GC_thread me;    GC_bool detached;    int i;#   if DEBUG_CYGWIN_THREADS      GC_printf("thread 0x%x(0x%x) starting...\n",(int)pthread_id,		      				  thread_id);#   endif#   if DEBUG_WIN32_PTHREADS      GC_printf("thread 0x%x(0x%x) starting...\n",(int) pthread_id.p,      						  thread_id);#   endif    GC_ASSERT(!GC_win32_dll_threads);    /* If a GC occurs before the thread is registered, that GC will	*/    /* ignore this thread.  That's fine, since it will block trying to  */    /* acquire the allocation lock, and won't yet hold interesting 	*/    /* pointers.							*/    LOCK();    /* We register the thread here instead of in the parent, so that	*/    /* we don't need to hold the allocation lock during pthread_create. */    me = GC_register_my_thread_inner(sb, thread_id);    SET_PTHREAD_MAP_CACHE(pthread_id, thread_id);    UNLOCK();    start = si -> start_routine;    start_arg = si -> arg;    if (si-> detached) me -> flags |= DETACHED;    me -> pthread_id = pthread_id;    GC_free(si); /* was allocated uncollectable */    pthread_cleanup_push(GC_thread_exit_proc, (void *)me);    result = (*start)(start_arg);    me -> status = result;    pthread_cleanup_pop(1);#   if DEBUG_CYGWIN_THREADS      GC_printf("thread 0x%x(0x%x) returned from start routine.\n",		(int)pthread_self(),GetCurrentThreadId());#   endif#   if DEBUG_WIN32_PTHREADS      GC_printf("thread 0x%x(0x%x) returned from start routine.\n",		(int)(pthread_self()).p, GetCurrentThreadId());#   endif    return(result);}void * GC_pthread_start(void * arg){    return GC_call_with_stack_base(GC_pthread_start_inner, arg);}void GC_thread_exit_proc(void *arg){    GC_thread me = (GC_thread)arg;    int i;    GC_ASSERT(!GC_win32_dll_threads);#   if DEBUG_CYGWIN_THREADS      GC_printf("thread 0x%x(0x%x) called pthread_exit().\n",		(int)pthread_self(),GetCurrentThreadId());#   endif#   if DEBUG_WIN32_PTHREADS      GC_printf("thread 0x%x(0x%x) called pthread_exit().\n",		(int)(pthread_self()).p,GetCurrentThreadId());#   endif    LOCK();#   if defined(THREAD_LOCAL_ALLOC)      GC_destroy_thread_local(&(me->tlfs));#   endif    if (me -> flags & DETACHED) {      GC_delete_thread(GetCurrentThreadId());    } else {      /* deallocate it as part of join */      me -> flags |= FINISHED;    }    UNLOCK();}#ifndef GC_WIN32_PTHREADS/* win32 pthread does not support sigmask *//* nothing required here... */int GC_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) {  if (!parallel_initialized) GC_init_parallel();  return pthread_sigmask(how, set, oset);}#endifint GC_pthread_detach(pthread_t thread){    int result;    GC_thread thread_gc_id;        if (!parallel_initialized) GC_init_parallel();    LOCK();    thread_gc_id = GC_lookup_pthread(thread);    UNLOCK();    result = 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_gc_id);      }      UNLOCK();    }    return result;}#else /* !GC_PTHREADS *//* * We avoid acquiring locks here, since this doesn't seem to be preemptable. * This may run with an uninitialized collector, in which case we don't do much. * This implies that no threads other than the main one should be created * with an uninitialized collector.  (The alternative of initializing * the collector here seems dangerous, since DllMain is limited in what it * can do.) */#ifdef GC_DLLGC_API BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved){  struct GC_stack_base sb;  DWORD thread_id;  int sb_result;  static int entry_count = 0;  if (parallel_initialized && !GC_win32_dll_threads) return TRUE;  switch (reason) {   case DLL_THREAD_ATTACH:    GC_ASSERT(entry_count == 0 || parallel_initialized);    ++entry_count; /* and fall through: */   case DLL_PROCESS_ATTACH:    /* This may run with the collector uninitialized. */    thread_id = GetCurrentThreadId();    if (parallel_initialized && GC_main_thread != thread_id) {	/* Don't lock here.	*/        sb_result = GC_get_stack_base(&sb);        GC_ASSERT(sb_result == GC_SUCCESS);#       ifdef THREAD_LOCAL_ALLOC	  ABORT("Cannot initialize thread local cache from DllMain");#       endif	GC_register_my_thread_inner(&sb, thread_id);    } /* o.w. we already did it during GC_thr_init(), called by GC_init() */    break;   case DLL_THREAD_DETACH:    /* We are hopefully running in the context of the exiting thread.	*/    GC_ASSERT(parallel_initialized);    if (!GC_win32_dll_threads) return TRUE;    GC_delete_thread(GetCurrentThreadId());    break;   case DLL_PROCESS_DETACH:    {      int i;      if (!GC_win32_dll_threads) return TRUE;      for (i = 0; i <= GC_get_max_thread_index(); ++i)      {          if (AO_load(&(dll_thread_table[i].in_use)))	    GC_delete_gc_thread(dll_thread_table + i);      }      GC_deinit();      DeleteCriticalSection(&GC_allocate_ml);    }    break;  }  return TRUE;}#endif /* GC_DLL */#endif /* !GC_PTHREADS */# endif /* !MSWINCE *//* Perform all initializations, including those that	*//* may require allocation.				*//* Called without allocation lock.			*//* Must be called before a second thread is created.	*/void GC_init_parallel(void){    if (parallel_initialized) return;    parallel_initialized = TRUE;    /* GC_init() calls us back, so set flag first.	*/        if (!GC_is_initialized) GC_init();    if (GC_win32_dll_threads) {      GC_need_to_lock = TRUE;  	/* Cannot intercept thread creation.  Hence we don't know if other	*/	/* threads exist.  However, client is not allowed to create other	*/	/* threads before collector initialization.  Thus it's OK not to	*/	/* lock before this.							*/    }    /* Initialize thread local free lists if used.	*/#   if defined(THREAD_LOCAL_ALLOC)      LOCK();      GC_init_thread_local(&(GC_lookup_thread(GetCurrentThreadId())->tlfs));      UNLOCK();#   endif}#if defined(USE_PTHREAD_LOCKS)  /* Support for pthread locking code.		*/  /* Pthread_mutex_try_lock may not win here,	*/  /* due to builtinsupport for spinning first?	*/volatile GC_bool GC_collecting = 0;			/* A hint that we're in the collector and       */                        /* holding the allocation lock for an           */                        /* extended period.                             */void GC_lock(void){    pthread_mutex_lock(&GC_allocate_ml);}#endif /* USE_PTHREAD ... */# if defined(THREAD_LOCAL_ALLOC)/* Add thread-local allocation support.  Microsoft uses __declspec(thread) *//* We must explicitly mark ptrfree and gcj free lists, since the free 	*//* list links wouldn't otherwise be found.  We also set them in the 	*//* normal free lists, since that involves touching less memory than if	*//* we scanned them normally.						*/void GC_mark_thread_local_free_lists(void){    int i;    GC_thread p;        for (i = 0; i < THREAD_TABLE_SZ; ++i) {      for (p = GC_threads[i]; 0 != p; p = p -> next) {	GC_mark_thread_local_fls_for(&(p->tlfs));      }    }}#if defined(GC_ASSERTIONS)    /* Check that all thread-local free-lists are completely marked.	*/    /* also check that thread-specific-data structures are marked.	*/    void GC_check_tls(void) {	int i;	GC_thread p;		for (i = 0; i < THREAD_TABLE_SZ; ++i) {	  for (p = GC_threads[i]; 0 != p; p = p -> next) {	    GC_check_tls_for(&(p->tlfs));	  }	}#       if defined(USE_CUSTOM_SPECIFIC)	  if (GC_thread_key != 0)	    GC_check_tsd_marks(GC_thread_key);#	endif     }#endif /* GC_ASSERTIONS */#endif /* THREAD_LOCAL_ALLOC ... */#endif /* GC_WIN32_THREADS */

⌨️ 快捷键说明

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