#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
};