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

📄 gc_locks.h

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 H
📖 第 1 页 / 共 2 页
字号:
#  endif /* !GC_CLEAR_DEFINED */#  if !defined(GC_TEST_AND_SET_DEFINED)#    define USE_PTHREAD_LOCKS#  endif#  if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \      && !defined(GC_IRIX_THREADS) && !defined(GC_WIN32_THREADS)#    define NO_THREAD (pthread_t)(-1)#    include <pthread.h>#    if defined(PARALLEL_MARK)       /* We need compare-and-swap to update mark bits, where it's	*/      /* performance critical.  If USE_MARK_BYTES is defined, it is	*/      /* no longer needed for this purpose.  However we use it in	*/      /* either case to implement atomic fetch-and-add, though that's	*/      /* less performance critical, and could perhaps be done with	*/      /* a lock.							*/#     if defined(GENERIC_COMPARE_AND_SWAP)	/* Probably not useful, except for debugging.	*/	/* We do use GENERIC_COMPARE_AND_SWAP on PA_RISC, but we 	*/	/* minimize its use.						*/	extern pthread_mutex_t GC_compare_and_swap_lock;	/* Note that if GC_word updates are not atomic, a concurrent 	*/	/* reader should acquire GC_compare_and_swap_lock.  On 		*/	/* currently supported platforms, such updates are atomic.	*/	extern GC_bool GC_compare_and_exchange(volatile GC_word *addr,					       GC_word old, GC_word new_val);#     endif /* GENERIC_COMPARE_AND_SWAP */#     if defined(I386)#      if !defined(GENERIC_COMPARE_AND_SWAP)         /* Returns TRUE if the comparison succeeded. */         inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,		  				       GC_word old,						       GC_word new_val)          {	   char result;	   __asm__ __volatile__("lock; cmpxchgl %2, %0; setz %1"	    	: "+m"(*(addr)), "=r"(result)		: "r" (new_val), "a"(old) : "memory");	   return (GC_bool) result;         }#      endif /* !GENERIC_COMPARE_AND_SWAP */       inline static void GC_memory_barrier()       {	 /* We believe the processor ensures at least processor	*/	 /* consistent ordering.  Thus a compiler barrier	*/	 /* should suffice.					*/         __asm__ __volatile__("" : : : "memory");       }#     endif /* I386 */#     if defined(POWERPC)#      if !defined(GENERIC_COMPARE_AND_SWAP)        /* Returns TRUE if the comparison succeeded. */        inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,            GC_word old, GC_word new_val)         {            int result, dummy;            __asm__ __volatile__(                "1:\tlwarx %0,0,%5\n"                  "\tcmpw %0,%4\n"                  "\tbne  2f\n"                  "\tstwcx. %3,0,%2\n"                  "\tbne- 1b\n"                  "\tsync\n"                  "\tli %1, 1\n"                  "\tb 3f\n"                "2:\tli %1, 0\n"                "3:\t\n"                :  "=&r" (dummy), "=r" (result), "=p" (addr)                :  "r" (new_val), "r" (old), "2"(addr)                : "cr0","memory");            return (GC_bool) result;        }#      endif /* !GENERIC_COMPARE_AND_SWAP */        inline static void GC_memory_barrier()        {            __asm__ __volatile__("sync" : : : "memory");        }#     endif /* POWERPC */#     if defined(IA64)#      if !defined(GENERIC_COMPARE_AND_SWAP)         inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,						       GC_word old,						       GC_word new_val) 	 {	   return __sync_bool_compare_and_swap (addr, old, new_val);         }#      endif /* !GENERIC_COMPARE_AND_SWAP */#      if 0	/* Shouldn't be needed; we use volatile stores instead. */        inline static void GC_memory_barrier()        {          __sync_synchronize ();        }#      endif /* 0 */#     endif /* IA64 */#     if defined(ALPHA)#      if !defined(GENERIC_COMPARE_AND_SWAP)#        if defined(__GNUC__)           inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,						         GC_word old, GC_word new_val) 	   {	     unsigned long was_equal;             unsigned long temp;             __asm__ __volatile__(                             "1:     ldq_l %0,%1\n"                             "       cmpeq %0,%4,%2\n"			     "	     mov %3,%0\n"                             "       beq %2,2f\n"                             "       stq_c %0,%1\n"                             "       beq %0,1b\n"                             "2:\n"                             "       mb\n"                             :"=&r" (temp), "=m" (*addr), "=&r" (was_equal)                             : "r" (new_val), "Ir" (old)			     :"memory");             return was_equal;           }#        else /* !__GNUC__ */           inline static GC_bool GC_compare_and_exchange(volatile GC_word *addr,						         GC_word old, GC_word new_val) 	  {	    return __CMP_STORE_QUAD(addr, old, new_val, addr);          }#        endif /* !__GNUC__ */#      endif /* !GENERIC_COMPARE_AND_SWAP */#      ifdef __GNUC__         inline static void GC_memory_barrier()         {           __asm__ __volatile__("mb" : : : "memory");         }#      else#	 define GC_memory_barrier() asm("mb")#      endif /* !__GNUC__ */#     endif /* ALPHA */#     if defined(S390)#      if !defined(GENERIC_COMPARE_AND_SWAP)         inline static GC_bool GC_compare_and_exchange(volatile C_word *addr,                                         GC_word old, GC_word new_val)         {           int retval;           __asm__ __volatile__ (#            ifndef __s390x__               "     cs  %1,%2,0(%3)\n"#            else               "     csg %1,%2,0(%3)\n"#            endif             "     ipm %0\n"             "     srl %0,28\n"             : "=&d" (retval), "+d" (old)             : "d" (new_val), "a" (addr)             : "cc", "memory");           return retval == 0;         }#      endif#     endif#     if !defined(GENERIC_COMPARE_AND_SWAP)        /* Returns the original value of *addr.	*/        inline static GC_word GC_atomic_add(volatile GC_word *addr,					    GC_word how_much)        {	  GC_word old;	  do {	    old = *addr;	  } while (!GC_compare_and_exchange(addr, old, old+how_much));          return old;        }#     else /* GENERIC_COMPARE_AND_SWAP */	/* So long as a GC_word can be atomically updated, it should	*/	/* be OK to read *addr without a lock.				*/	extern GC_word GC_atomic_add(volatile GC_word *addr, GC_word how_much);#     endif /* GENERIC_COMPARE_AND_SWAP */#    endif /* PARALLEL_MARK */#    if !defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_LOCKS)      /* In the THREAD_LOCAL_ALLOC case, the allocation lock tends to	*/      /* be held for long periods, if it is held at all.  Thus spinning	*/      /* and sleeping for fixed periods are likely to result in 	*/      /* significant wasted time.  We thus rely mostly on queued locks. */#     define USE_SPIN_LOCK      extern volatile unsigned int GC_allocate_lock;      extern void GC_lock(void);	/* Allocation lock holder.  Only set if acquired by client through */	/* GC_call_with_alloc_lock.					   */#     ifdef GC_ASSERTIONS#        define LOCK() \		{ if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); \		  SET_LOCK_HOLDER(); }#        define UNLOCK() \		{ GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \	          GC_clear(&GC_allocate_lock); }#     else#        define LOCK() \		{ if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }#        define UNLOCK() \		GC_clear(&GC_allocate_lock)#     endif /* !GC_ASSERTIONS */#     if 0	/* Another alternative for OSF1 might be:		*/#       include <sys/mman.h>        extern msemaphore GC_allocate_semaphore;#       define LOCK() { if (msem_lock(&GC_allocate_semaphore, MSEM_IF_NOWAIT) \ 			    != 0) GC_lock(); else GC_allocate_lock = 1; }        /* The following is INCORRECT, since the memory model is too weak. */	/* Is this true?  Presumably msem_unlock has the right semantics?  */	/*		- HB						   */#       define UNLOCK() { GC_allocate_lock = 0; \                          msem_unlock(&GC_allocate_semaphore, 0); }#     endif /* 0 */#    else /* THREAD_LOCAL_ALLOC  || USE_PTHREAD_LOCKS */#      ifndef USE_PTHREAD_LOCKS#        define USE_PTHREAD_LOCKS#      endif#    endif /* THREAD_LOCAL_ALLOC */#   ifdef USE_PTHREAD_LOCKS#      include <pthread.h>       extern pthread_mutex_t GC_allocate_ml;#      ifdef GC_ASSERTIONS#        define LOCK() \		{ GC_lock(); \		  SET_LOCK_HOLDER(); }#        define UNLOCK() \		{ GC_ASSERT(I_HOLD_LOCK()); UNSET_LOCK_HOLDER(); \	          pthread_mutex_unlock(&GC_allocate_ml); }#      else /* !GC_ASSERTIONS */#        if defined(NO_PTHREAD_TRYLOCK)#          define LOCK() GC_lock();#        else /* !defined(NO_PTHREAD_TRYLOCK) */#        define LOCK() \	   { if (0 != pthread_mutex_trylock(&GC_allocate_ml)) GC_lock(); }#        endif#        define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)#      endif /* !GC_ASSERTIONS */#   endif /* USE_PTHREAD_LOCKS */#   define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()#   define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD#   define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))    extern VOLATILE GC_bool GC_collecting;#   define ENTER_GC() GC_collecting = 1;#   define EXIT_GC() GC_collecting = 0;    extern void GC_lock(void);    extern pthread_t GC_lock_holder;#   ifdef GC_ASSERTIONS      extern pthread_t GC_mark_lock_holder;#   endif#  endif /* GC_PTHREADS with linux_threads.c implementation */#  if defined(GC_IRIX_THREADS)#    include <pthread.h>     /* This probably should never be included, but I can't test	*/     /* on Irix anymore.						*/#    include <mutex.h>     extern volatile unsigned int GC_allocate_lock;	/* This is not a mutex because mutexes that obey the (optional) 	*/	/* POSIX scheduling rules are subject to convoys in high contention	*/	/* applications.  This is basically a spin lock.			*/     extern pthread_t GC_lock_holder;     extern void GC_lock(void);	/* Allocation lock holder.  Only set if acquired by client through */	/* GC_call_with_alloc_lock.					   */#    define SET_LOCK_HOLDER() GC_lock_holder = pthread_self()#    define NO_THREAD (pthread_t)(-1)#    define UNSET_LOCK_HOLDER() GC_lock_holder = NO_THREAD#    define I_HOLD_LOCK() (pthread_equal(GC_lock_holder, pthread_self()))#    define LOCK() { if (GC_test_and_set(&GC_allocate_lock)) GC_lock(); }#    define UNLOCK() GC_clear(&GC_allocate_lock);     extern VOLATILE GC_bool GC_collecting;#    define ENTER_GC() \		{ \		    GC_collecting = 1; \		}#    define EXIT_GC() GC_collecting = 0;#  endif /* GC_IRIX_THREADS */#  if defined(GC_WIN32_THREADS)#    if defined(GC_PTHREADS)#      include <pthread.h>       extern pthread_mutex_t GC_allocate_ml;#      define LOCK()   pthread_mutex_lock(&GC_allocate_ml)#      define UNLOCK() pthread_mutex_unlock(&GC_allocate_ml)#    else#      include <windows.h>       GC_API CRITICAL_SECTION GC_allocate_ml;#      define LOCK() EnterCriticalSection(&GC_allocate_ml);#      define UNLOCK() LeaveCriticalSection(&GC_allocate_ml);#    endif#  endif#  ifndef SET_LOCK_HOLDER#      define SET_LOCK_HOLDER()#      define UNSET_LOCK_HOLDER()#      define I_HOLD_LOCK() FALSE		/* Used on platforms were locks can be reacquired,	*/		/* so it doesn't matter if we lie.			*/#  endif# else /* !THREADS */#    define LOCK()#    define UNLOCK()# endif /* !THREADS */# ifndef SET_LOCK_HOLDER#   define SET_LOCK_HOLDER()#   define UNSET_LOCK_HOLDER()#   define I_HOLD_LOCK() FALSE		/* Used on platforms were locks can be reacquired,	*/		/* so it doesn't matter if we lie.			*/# endif# ifndef ENTER_GC#   define ENTER_GC()#   define EXIT_GC()# endif# ifndef DCL_LOCK_STATE#   define DCL_LOCK_STATE# endif# ifndef FASTLOCK#   define FASTLOCK() LOCK()#   define FASTLOCK_SUCCEEDED() TRUE#   define FASTUNLOCK() UNLOCK()# endif#endif /* GC_LOCKS_H */

⌨️ 快捷键说明

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