Browse Source

better windows locking

David Rose 19 years ago
parent
commit
9ce524fc89

+ 1 - 1
dtool/Config.Win32.pp

@@ -8,7 +8,7 @@
 
 
 // What additional flags should we pass to interrogate?
 // What additional flags should we pass to interrogate?
 // NSPR versions prior to 4.4 used _declspec instead of __declspec.
 // NSPR versions prior to 4.4 used _declspec instead of __declspec.
-#define SYSTEM_IGATE_FLAGS -longlong __int64 -D_X86_ -DWIN32_VC -D"_declspec(param)=" -D"__declspec(param)=" -D_near  -D_far -D__near  -D__far -D_WIN32 -D__stdcall
+#define SYSTEM_IGATE_FLAGS -longlong __int64 -D_X86_ -DWIN32_VC -D"_declspec(param)=" -D"__declspec(param)=" -D_near  -D_far -D__near  -D__far -D_WIN32 -D__stdcall -Dvolatile=
 
 
 // Is the platform big-endian (like an SGI workstation) or
 // Is the platform big-endian (like an SGI workstation) or
 // little-endian (like a PC)?  Define this to the empty string to
 // little-endian (like a PC)?  Define this to the empty string to

+ 1 - 1
dtool/src/dtoolbase/atomicAdjust.h

@@ -27,7 +27,7 @@
 #include "atomicAdjustDummyImpl.h"
 #include "atomicAdjustDummyImpl.h"
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 typedef AtomicAdjustDummyImpl AtomicAdjust;
 
 
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(_M_IX86)
 // For an i386 architecture, we'll always use the i386 implementation.
 // For an i386 architecture, we'll always use the i386 implementation.
 // It should be safe for any OS, and it might be a bit faster than
 // It should be safe for any OS, and it might be a bit faster than
 // any OS-provided calls.
 // any OS-provided calls.

+ 43 - 4
dtool/src/dtoolbase/atomicAdjustI386Impl.I

@@ -24,7 +24,15 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void AtomicAdjustI386Impl::
 INLINE void AtomicAdjustI386Impl::
 inc(volatile PN_int32 &var) {
 inc(volatile PN_int32 &var) {
-#ifndef __EDG__
+#ifdef _M_IX86
+  // Windows case
+  volatile PN_int32 *var_ptr = &var;
+  __asm {
+    mov edx, var_ptr;
+    lock inc dword ptr [edx];
+  }
+#elif !defined(__EDG__)
+  // GCC case
   __asm__ __volatile__("lock; incl %0"
   __asm__ __volatile__("lock; incl %0"
                        :"=m" (var)
                        :"=m" (var)
                        :"m" (&var));
                        :"m" (&var));
@@ -41,7 +49,16 @@ inc(volatile PN_int32 &var) {
 INLINE bool AtomicAdjustI386Impl::
 INLINE bool AtomicAdjustI386Impl::
 dec(volatile PN_int32 &var) {
 dec(volatile PN_int32 &var) {
   unsigned char c;
   unsigned char c;
-#ifndef __EDG__
+#ifdef _M_IX86
+  // Windows case
+  volatile PN_int32 *var_ptr = &var;
+  __asm {
+    mov edx, var_ptr;
+    lock dec dword ptr [edx];
+    sete c;
+  }
+#elif !defined(__EDG__)
+  // GCC case
   __asm__ __volatile__("lock; decl %0; sete %1"
   __asm__ __volatile__("lock; decl %0; sete %1"
                        :"=m" (var), "=qm" (c)
                        :"=m" (var), "=qm" (c)
                        :"m" (&var) : "memory");
                        :"m" (&var) : "memory");
@@ -126,7 +143,18 @@ INLINE PN_int32 AtomicAdjustI386Impl::
 compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
 compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
                      PN_int32 new_value) {
                      PN_int32 new_value) {
   PN_int32 prev;
   PN_int32 prev;
-#ifndef __EDG__
+#ifdef _M_IX86
+  // Windows case
+  volatile PN_int32 *mem_ptr = &mem;
+  __asm {
+    mov edx, mem_ptr;
+    mov ecx, new_value;
+    mov eax, old_value;
+    lock cmpxchg dword ptr [edx], ecx;
+    mov prev, eax;
+  }
+#elif !defined(__EDG__)
+  // GCC case
   __asm__ __volatile__("lock; cmpxchgl %1,%2"
   __asm__ __volatile__("lock; cmpxchgl %1,%2"
                        : "=a"(prev)
                        : "=a"(prev)
                        : "r"(new_value), "m"(mem), "0"(old_value)
                        : "r"(new_value), "m"(mem), "0"(old_value)
@@ -146,7 +174,18 @@ INLINE void *AtomicAdjustI386Impl::
 compare_and_exchange_ptr(void * volatile &mem, void *old_value,
 compare_and_exchange_ptr(void * volatile &mem, void *old_value,
                          void *new_value) {
                          void *new_value) {
   void *prev;
   void *prev;
-#ifndef __EDG__
+#ifdef _M_IX86
+  // Windows case
+  void * volatile *mem_ptr = &mem;
+  __asm {
+    mov edx, mem_ptr;
+    mov ecx, new_value;
+    mov eax, old_value;
+    lock cmpxchg dword ptr [edx], ecx;
+    mov prev, eax;
+  }
+#elif !defined(__EDG__)
+  // GCC case
   __asm__ __volatile__("lock; cmpxchgl %1,%2"
   __asm__ __volatile__("lock; cmpxchgl %1,%2"
                        : "=a"(prev)
                        : "=a"(prev)
                        : "r"(new_value), "m"(mem), "0"(old_value)
                        : "r"(new_value), "m"(mem), "0"(old_value)

+ 1 - 1
dtool/src/dtoolbase/atomicAdjustI386Impl.h

@@ -22,7 +22,7 @@
 #include "dtoolbase.h"
 #include "dtoolbase.h"
 #include "selectThreadImpl.h"
 #include "selectThreadImpl.h"
 
 
-#if defined(__i386__)
+#if defined(__i386__) || defined(_M_IX86)
 
 
 #include "numeric_types.h"
 #include "numeric_types.h"
 
 

+ 32 - 0
dtool/src/dtoolbase/atomicAdjustPosixImpl.I

@@ -75,3 +75,35 @@ get(const PN_int32 &var) {
   pthread_mutex_unlock(&_mutex);
   pthread_mutex_unlock(&_mutex);
   return orig_value;
   return orig_value;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustPosixImpl::set_ptr
+//       Access: Public, Static
+//  Description: Atomically changes the indicated variable and
+//               returns the original value.
+////////////////////////////////////////////////////////////////////
+INLINE void *AtomicAdjustPosixImpl::
+set_ptr(void *&var, void *new_value) {
+  pthread_mutex_lock(&_mutex);
+  void *orig_value = var;
+  var = new_value;
+  pthread_mutex_unlock(&_mutex);
+  return orig_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustPosixImpl::get_ptr
+//       Access: Public, Static
+//  Description: Atomically retrieves the snapshot value of the
+//               indicated variable.  This is the only guaranteed safe
+//               way to retrieve the value that other threads might be
+//               asynchronously setting, incrementing, or decrementing
+//               (via other AtomicAjust methods).
+////////////////////////////////////////////////////////////////////
+INLINE void *AtomicAdjustPosixImpl::
+get_ptr(const void *&var) {
+  pthread_mutex_lock(&_mutex);
+  void *orig_value = var;
+  pthread_mutex_unlock(&_mutex);
+  return orig_value;
+}

+ 3 - 0
dtool/src/dtoolbase/atomicAdjustPosixImpl.h

@@ -39,6 +39,9 @@ public:
   INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
   INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
   INLINE static PN_int32 get(const PN_int32 &var);
   INLINE static PN_int32 get(const PN_int32 &var);
 
 
+  INLINE static void *set_ptr(void *&var, void *new_value);
+  INLINE static void *get_ptr(void * const &var);
+
 private:
 private:
   static pthread_mutex_t _mutex;
   static pthread_mutex_t _mutex;
 };
 };

+ 42 - 0
dtool/src/dtoolbase/atomicAdjustWin32Impl.I

@@ -90,3 +90,45 @@ INLINE void *AtomicAdjustWin32Impl::
 get_ptr(void * const &var) {
 get_ptr(void * const &var) {
   return var;
   return var;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustWin32Impl::compare_and_exchange
+//       Access: Public, Static
+//  Description: Atomic compare and exchange.  
+//
+//               If mem is equal to old_value, store new_value in mem.
+//               In either case, return the original value of mem.
+//               The caller can test for success by comparing
+//               return_value == old_value.
+//
+//               The atomic function expressed in pseudo-code:
+//
+//                 orig_value = mem;
+//                 if (mem == old_value) {
+//                   mem = new_value;
+//                 }
+//                 return orig_value;
+//
+////////////////////////////////////////////////////////////////////
+INLINE PN_int32 AtomicAdjustWin32Impl::
+compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
+                     PN_int32 new_value) {
+  // Note that the AtomicAdjust parameter order is different from
+  // Windows convention!
+  return InterlockedCompareExchange((volatile LONG *)&mem, new_value, old_value);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AtomicAdjustWin32Impl::compare_and_exchange_ptr
+//       Access: Public, Static
+//  Description: Atomic compare and exchange.  
+//
+//               As above, but works on pointers instead of integers.
+////////////////////////////////////////////////////////////////////
+INLINE void *AtomicAdjustWin32Impl::
+compare_and_exchange_ptr(void * volatile &mem, void *old_value,
+                         void *new_value) {
+  // Note that the AtomicAdjust parameter order is different from
+  // Windows convention!
+  return InterlockedCompareExchangePointer(&mem, new_value, old_value);
+}

+ 11 - 0
dtool/src/dtoolbase/atomicAdjustWin32Impl.h

@@ -28,6 +28,9 @@
 
 
 #include <windows.h>
 #include <windows.h>
 
 
+#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
+#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : AtomicAdjustWin32Impl
 //       Class : AtomicAdjustWin32Impl
 // Description : Uses Windows native calls to implement atomic
 // Description : Uses Windows native calls to implement atomic
@@ -42,6 +45,14 @@ public:
 
 
   INLINE static void *set_ptr(void *&var, void *new_value);
   INLINE static void *set_ptr(void *&var, void *new_value);
   INLINE static void *get_ptr(void * const &var);
   INLINE static void *get_ptr(void * const &var);
+
+  INLINE static PN_int32 compare_and_exchange(volatile PN_int32 &mem, 
+                                              PN_int32 old_value,
+                                              PN_int32 new_value);
+
+  INLINE static void *compare_and_exchange_ptr(void * volatile &mem, 
+                                               void *old_value,
+                                               void *new_value);
 };
 };
 
 
 #include "atomicAdjustWin32Impl.I"
 #include "atomicAdjustWin32Impl.I"

+ 1 - 0
dtool/src/interrogate/interrogate.cxx

@@ -22,6 +22,7 @@
 #include "interrogateDatabase.h"
 #include "interrogateDatabase.h"
 #include "cppGlobals.h"
 #include "cppGlobals.h"
 #include "pnotify.h"
 #include "pnotify.h"
+#include "atomicAdjust.h"
 #include <time.h>
 #include <time.h>
 
 
 // If our system getopt() doesn't come with getopt_long_only(), then use
 // If our system getopt() doesn't come with getopt_long_only(), then use