List:Commits« Previous MessageNext Message »
From:Marc Alff Date:June 7 2009 6:17pm
Subject:bzr commit into mysql-6.0-perfschema branch (marc.alff:3167)
View as plain text  
#At file:///home/malff/BZR-TREE/mysql-6.0-perfschema/ based on revid:marc.alff@stripped

 3167 Marc Alff	2009-06-07
      Cleanup of PFS_atomic
      modified:
        storage/perfschema/pfs_atomic.cc
        storage/perfschema/pfs_atomic.h

=== modified file 'storage/perfschema/pfs_atomic.cc'
--- a/storage/perfschema/pfs_atomic.cc	2009-06-06 03:08:19 +0000
+++ b/storage/perfschema/pfs_atomic.cc	2009-06-07 18:17:35 +0000
@@ -21,24 +21,86 @@
 #include <my_global.h>
 #include "pfs_atomic.h"
 
-#ifdef PFS_ATOMIC_MODE_MUTEX
-static pthread_mutex_t PFS_atomic::m_mutex_array[256];
+#ifdef SAFE_MUTEX
+/*
+  Using SAFE_MUTEX is impossible, because of recursion.
+  - code locks mutex X
+    - P_S records the event
+      - P_S needs an atomic counter A
+        - safe mutex called for m_mutex[hash(A)]
+          - safe mutex allocates/free memory
+            - safe mutex locks THR_LOCK_malloc
+              - P_S records the event
+                - P_S needs an atomic counter B
+                  - safe mutex called for m_mutex[hash(B)]
+
+  When hash(A) == hash(B), safe_mutex complains rightly that
+  the mutex is already locked.
+  In some cases, A == B, in particular for events_waits_history_long_index.
+
+  In short, the implementation of PFS_atomic should not cause events
+  to be recorded in the performance schema.
+
+  Also, because SAFE_MUTEX redefines pthread_mutex_t, etc,
+  this code is not inlined in pfs_atomic.h, but located here in pfs_atomic.cc.
+
+  What is needed is a plain, unmodified, pthread_mutex_t.
+*/
+#undef pthread_mutex_t
+#undef pthread_mutex_init
+#undef pthread_mutex_destroy
+#undef pthread_mutex_lock
+#undef pthread_mutex_unlock
+#endif
+
+#ifdef MY_ATOMIC_MODE_RWLOCKS
+/**
+  Internal mutex array.
+  Using a single mutex for all atomic operations would be a bottleneck.
+  Using a mutex per performance schema structure would be too costly in
+  memory, and use too many mutex.
+  The PFS_atomic implementation computes a hash value from the
+  atomic variable, to spread the bottleneck across 256 buckets,
+  while still providing --transparently for the caller-- an atomic
+  operation.
+*/
+static pthread_mutex_t m_mutex_array[256];
+
+static inline pthread_mutex_t *get_mutex(volatile void *ptr)
+{
+  /*
+    Divide an address by 8 to remove alignment,
+    modulo 256 to fall in the array.
+  */
+  uint index= (((intptr) ptr) >> 3) & 0xFF;
+  pthread_mutex_t *result= &m_mutex_array[index];
+  return result;
+}
+
+void PFS_atomic::lock(volatile void *ptr)
+{
+  pthread_mutex_lock(get_mutex(ptr));
+}
+
+void PFS_atomic::unlock(volatile void *ptr)
+{
+  pthread_mutex_unlock(get_mutex(ptr));
+}
 #endif
 
 void PFS_atomic::init()
 {
-#ifdef PFS_ATOMIC_MODE_MUTEX
+#ifdef MY_ATOMIC_MODE_RWLOCKS
   uint i;
 
   for (i=0; i< array_elements(m_mutex_array); i++)
-    pthread_mutex_init(& m_mutex_array[i]);
+    pthread_mutex_init(& m_mutex_array[i], NULL);
 #endif
 }
 
-
 void PFS_atomic::cleanup()
 {
-#ifdef PFS_ATOMIC_MODE_MUTEX
+#ifdef MY_ATOMIC_MODE_RWLOCKS
   uint i;
 
   for (i=0; i< array_elements(m_mutex_array); i++)

=== modified file 'storage/perfschema/pfs_atomic.h'
--- a/storage/perfschema/pfs_atomic.h	2009-06-06 03:08:19 +0000
+++ b/storage/perfschema/pfs_atomic.h	2009-06-07 18:17:35 +0000
@@ -23,22 +23,8 @@
 
 #include <my_atomic.h>
 
-#ifdef MY_ATOMIC_MODE_RWLOCKS
-  #define PFS_ATOMIC_MODE_MUTEX
-#endif
-
 /**
   Helper for atomic operations.
-  This class works around the following limitations of my_atomic:
-  - unsigned values are not supported (minor)
-  - not all platforms are supported (major)
-  - for unsupported platforms, the my_atomic implementation
-  does not use mutexes internally (in its own implementation),
-  but forces the caller to implement a work around.
-  See in particular my_atomic_rwlock_rdlock(), my_atomic_rwlock_wrlock()
-  and my_atomic_rwlock_wrunlock().
-  For the performance schema, we do not want to use a my_atomic_rwlock_t
-  for each record that has atomic attributes.
 */
 class PFS_atomic
 {
@@ -50,13 +36,9 @@ public:
   static inline int32 load_32(volatile int32 *ptr)
   {
     int32 result;
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     result= my_atomic_load32(ptr);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
     return result;
   }
 
@@ -64,51 +46,35 @@ public:
   static inline uint32 load_u32(volatile uint32 *ptr)
   {
     uint32 result;
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     result= (uint32) my_atomic_load32((int32*) ptr);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
     return result;
   }
 
   /** Atomic store. */
   static inline void store_32(volatile int32 *ptr, int32 value)
   {
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     my_atomic_store32(ptr, value);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
   }
 
   /** Atomic store. */
   static inline void store_u32(volatile uint32 *ptr, uint32 value)
   {
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     my_atomic_store32((int32*) ptr, (int32) value);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
   }
 
   /** Atomic add. */
   static inline int32 add_32(volatile int32 *ptr, int32 value)
   {
     int32 result;
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     result= my_atomic_add32(ptr, value);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
     return result;
   }
 
@@ -116,13 +82,9 @@ public:
   static inline uint32 add_u32(volatile uint32 *ptr, uint32 value)
   {
     uint32 result;
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     result= (uint32) my_atomic_add32((int32*) ptr, (int32) value);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
     return result;
   }
 
@@ -130,13 +92,9 @@ public:
   static inline bool cas_32(volatile int32 *ptr, int32 *old_value, int32 new_value)
   {
     bool result;
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     result= my_atomic_cas32(ptr, old_value, new_value);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
     return result;
   }
 
@@ -144,41 +102,21 @@ public:
   static inline bool cas_u32(volatile uint32 *ptr, uint32 *old_value, uint32 new_value)
   {
     bool result;
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_t *mutex= lock_mutex(ptr);
-#endif
+    lock(ptr);
     result= my_atomic_cas32((int32*) ptr, (int32*) old_value, (uint32) new_value);
-#ifdef PFS_ATOMIC_MODE_MUTEX
-    pthread_mutex_unlock(mutex);
-#endif
+    unlock(ptr);
     return result;
   }
 
-#ifdef PFS_ATOMIC_MODE_MUTEX
 private:
-  static inline pthread_mutex_t *lock_mutex(void *ptr)
-  {
-    /*
-      Divide an address by 8 to remove alignment,
-      modulo 256 to fall in the array.
-    */
-    uint index= (((intptr) ptr) >> 3) & 0xFF;
-    pthread_mutex_t *result= &m_mutex_array[index];
-    pthread_mutex_lock(result);
-    return result;
-  }
-
-  /**
-    Internal mutex array.
-    Using a single mutex for all atomic operations would be a bottleneck.
-    Using a mutex per performance schema structure would be too costly in
-    memory, and use too many mutexes.
-    The PFS_atomic implementation computes a hash value from the
-    atomic variable, to spread the bottleneck across 256 buckets,
-    while still providing --transparently for the caller-- an atomic
-    operation.
-  */
-  static pthread_mutex_t m_mutex_array[256];
+#ifdef MY_ATOMIC_MODE_RWLOCKS
+  static void lock(volatile void *ptr);
+  static void unlock(volatile void *ptr);
+#else
+  static inline void lock(volatile void *ptr)
+  {}
+  static inline void unlock(volatile void *ptr)
+  {}
 #endif
 };
 

Thread
bzr commit into mysql-6.0-perfschema branch (marc.alff:3167) Marc Alff7 Jun
  • Re: bzr commit into mysql-6.0-perfschema branch (marc.alff:3167)Guilhem Bichot8 Jun
    • Re: bzr commit into mysql-6.0-perfschema branch (marc.alff:3167)Marc Alff8 Jun
    • Re: bzr commit into mysql-6.0-perfschema branch (marc.alff:3167)Sergei Golubchik3 Jul