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