List:Commits« Previous MessageNext Message »
From:Guilhem Bichot Date:May 19 2009 8:09pm
Subject:review of WL#2360 Performance Schema (use of atomic operations)
View as plain text  
Bonjour Marc,

In a few places the P_S code makes use of atomic operations to guarantee 
  thread-safe operations on some structures. A grep for my_atomic in 
storage/perfschema says that this happens: when registering classes, 
when initializing/destroying instances, when inserting into 
EVENTS_WAITS_HISTORY_LONG. The typical sequence is simply:
my_atomic_cas32(& a, & b, c);
or
my_atomic_add32(& d, e);

On some platforms (including Linux-x86[-64]-with-gcc), the my_atomic 
operations above directly use CPU-supported atomic instructions (like 
CMPXCHG for CAS), and the my_atomic_* functions above expand to those 
instructions, all is fine.
But on others, my_atomic rather uses a mutex to achieve atomicity.
So the sequence has to be, like in waiting_threads.c:

     my_atomic_rwlock_wrlock(&(LOCK));
     my_atomic_add32(&(VAR), 1);
     my_atomic_rwlock_wrunlock(&(LOCK));

where LOCK is a my_atomic_rwlock_t and VAR is uint32.

1) if atomic ops use CPU-supported atomic instructions, 
my_atomic_rwlock_t is a dummy type, my_atomic_rwlock_*() are empty 
macros, and the CPU-supported atomic instruction is inside my_atomic_add32()
2) if atomic ops use a mutex, my_atomic_rwlock_t is a mutex type, 
my_atomic_rwlock_wrlock() locks this mutex, my_atomic_add32 merely does 
(*VAR)++, and my_atomic_rwlock_wrunlock() unlocks this mutex.

So, what you have to do in your P_S code is always follow this 3-command 
sequence; currently on a platform where 2) applies, we have unprotected 
operations which could lead to problems. You will have to add 
my_atomic_rwlock_t objects: at most 1 for writing to mutex_class_array 
(and 1 for rwlock_class_array, 1 for cond, 1 for thread, 1 for file), 1 
for create_mutex&destroy_mutex (and 1 for rwlock, 1 for cond, etc), 1 
for EVENTS_WAITS_HISTORY_LONG, that's the maximum. But you don't need to 
have those 5+5+1, for example as registering is a very infrequent 
operations I'd use 1 for the 5 class arrays. I would use a separate 1 
for the very frequent operations of inserting into 
EVENTS_WAITS_HISTORY_LONG). As for init/destroy of instances, I don't know.
I don't expect a mutex deadlock to happen because the my_atomic_rwlock_t 
objects for your atomic objects will always be acquired last (no mutex 
will be acquired while they are held).

For details on my_atomic: include/my_atomic.h.
You can force atomic ops to use a mutex with "./configure 
--with-atomic-ops=rwlocks" (see configure.in).

-- 
Mr. Guilhem Bichot <guilhem@stripped>
Sun Microsystems / MySQL, Lead Software Engineer
Bordeaux, France
www.sun.com / www.mysql.com
Thread
review of WL#2360 Performance Schema (use of atomic operations)Guilhem Bichot19 May
  • Re: review of WL#2360 Performance Schema (use of atomic operations)Marc Alff19 May
    • Re: review of WL#2360 Performance Schema (use of atomic operations)Guilhem Bichot20 May
    • Re: review of WL#2360 Performance Schema (use of atomic operations)Michael Widenius7 Jun