112
116
/* Protects access to m_locks hash. */
113
117
mysql_mutex_t m_mutex;
119
Cache of (unused) MDL_lock objects available for re-use.
121
On some systems (e.g. Windows XP) constructing/destructing
122
MDL_lock objects can be fairly expensive. We use this cache
123
to avoid these costs in scenarios in which they can have
124
significant negative effect on performance. For example, when
125
there is only one thread constantly executing statements in
126
auto-commit mode and thus constantly causing creation/
127
destruction of MDL_lock objects for the tables it uses.
129
Note that this cache contains only MDL_object_lock objects.
131
Protected by m_mutex mutex.
133
typedef I_P_List<MDL_object_lock, MDL_object_lock_cache_adapter,
136
Lock_cache m_unused_locks_cache;
114
137
/** Pre-allocated MDL_lock object for GLOBAL namespace. */
115
138
MDL_lock *m_global_lock;
116
139
/** Pre-allocated MDL_lock object for COMMIT namespace. */
414
438
uint m_ref_usage;
415
439
uint m_ref_release;
416
440
bool m_is_destroyed;
442
We use the same idea and an additional version counter to support
443
caching of unused MDL_lock object for further re-use.
444
This counter is incremented while holding both MDL_map::m_mutex and
445
MDL_lock::m_rwlock locks each time when a MDL_lock is moved from
446
the hash to the unused objects list (or destroyed).
447
A thread, which has found a MDL_lock object for the key in the hash
448
and then released the MDL_map::m_mutex before acquiring the
449
MDL_lock::m_rwlock, can determine that this object was moved to the
450
unused objects list (or destroyed) while it held no locks by comparing
451
the version value which it read while holding the MDL_map::m_mutex
452
with the value read after acquiring the MDL_lock::m_rwlock.
453
Note that since it takes several years to overflow this counter such
454
theoretically possible overflows should not have any practical effects.
462
502
: MDL_lock(key_arg)
506
Reset unused MDL_object_lock object to represent the lock context for a
509
void reset(const MDL_key *new_key)
511
/* We need to change only object's key. */
512
key.mdl_key_init(new_key);
513
/* m_granted and m_waiting should be already in the empty/initial state. */
514
DBUG_ASSERT(is_empty());
515
/* Object should not be marked as destroyed. */
516
DBUG_ASSERT(! m_is_destroyed);
518
Values of the rest of the fields should be preserved between old and
519
new versions of the object. E.g., m_version and m_ref_usage/release
520
should be kept intact to properly handle possible remaining references
521
to the old version of the object.
465
525
virtual const bitmap_t *incompatible_granted_types_bitmap() const
467
527
return m_granted_incompatible;
480
540
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
481
541
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
544
/** Members for linking the object into the list of unused objects. */
545
MDL_object_lock *next_in_cache, **prev_in_cache;
550
Helper class for linking MDL_object_lock objects into the unused objects list.
552
class MDL_object_lock_cache_adapter :
553
public I_P_List_adapter<MDL_object_lock, &MDL_object_lock::next_in_cache,
554
&MDL_object_lock::prev_in_cache>
485
559
static MDL_map mdl_locks;
561
Start-up parameter for the maximum size of the unused MDL_lock objects cache.
563
ulong mdl_locks_cache_size;
615
698
mdl_key->length())))
617
lock= MDL_lock::create(mdl_key);
700
MDL_object_lock *unused_lock= NULL;
703
No lock object found so we need to create a new one
704
or reuse an existing unused object.
706
if (mdl_key->mdl_namespace() != MDL_key::SCHEMA &&
707
m_unused_locks_cache.elements())
710
We need a MDL_object_lock type of object and the unused objects
711
cache has some. Get the first object from the cache and set a new
714
DBUG_ASSERT(mdl_key->mdl_namespace() != MDL_key::GLOBAL &&
715
mdl_key->mdl_namespace() != MDL_key::COMMIT);
717
unused_lock= m_unused_locks_cache.pop_front();
718
unused_lock->reset(mdl_key);
724
lock= MDL_lock::create(mdl_key);
618
727
if (!lock || my_hash_insert(&m_locks, (uchar*)lock))
732
Note that we can't easily destroy an object from cache here as it
733
still might be referenced by other threads. So we simply put it
736
m_unused_locks_cache.push_front(unused_lock);
740
MDL_lock::destroy(lock);
620
742
mysql_mutex_unlock(&m_mutex);
621
MDL_lock::destroy(lock);
651
774
m_is_destroyed is FALSE.
653
776
lock->m_ref_usage++;
777
/* Read value of the version counter under protection of m_mutex lock. */
778
version= lock->m_version;
654
779
mysql_mutex_unlock(&m_mutex);
656
781
mysql_prlock_wrlock(&lock->m_rwlock);
657
782
lock->m_ref_release++;
658
if (unlikely(lock->m_is_destroyed))
784
if (unlikely(lock->m_version != version))
661
Object was released while we held no mutex, we need to
662
release it if no others hold references to it, while our own
663
reference count ensured that the object as such haven't got
664
its memory released yet. We can also safely compare
665
m_ref_usage and m_ref_release since the object is no longer
666
present in the hash so no one will be able to find it and
667
increment m_ref_usage anymore.
787
If the current value of version differs from one that was read while
788
we held m_mutex mutex, this MDL_lock object was moved to the unused
789
objects list or destroyed while we held no locks.
790
We should retry our search. But first we should destroy the MDL_lock
669
uint ref_usage= lock->m_ref_usage;
670
uint ref_release= lock->m_ref_release;
671
mysql_prlock_unlock(&lock->m_rwlock);
672
if (ref_usage == ref_release)
673
MDL_lock::destroy(lock);
793
if (unlikely(lock->m_is_destroyed))
796
Object was released while we held no locks, we need to
797
release it if no others hold references to it, while our own
798
reference count ensured that the object as such haven't got
799
its memory released yet. We can also safely compare
800
m_ref_usage and m_ref_release since the object is no longer
801
present in the hash (or unused objects list) so no one will
802
be able to find it and increment m_ref_usage anymore.
804
uint ref_usage= lock->m_ref_usage;
805
uint ref_release= lock->m_ref_release;
806
mysql_prlock_unlock(&lock->m_rwlock);
807
if (ref_usage == ref_release)
808
MDL_lock::destroy(lock);
813
Object was not destroyed but its version has changed.
814
This means that it was moved to the unused objects list
815
(and even might be already re-used). So now it might
816
correspond to a different key, therefore we should simply
819
mysql_prlock_unlock(&lock->m_rwlock);
702
Destroy the MDL_lock object, but ensure that anyone that is
703
holding a reference to the object is not remaining, if so he
704
has the responsibility to release it.
706
Setting of m_is_destroyed to TRUE while holding _both_
707
mdl_locks.m_mutex and MDL_lock::m_rwlock mutexes transfers the
708
protection of m_ref_usage from mdl_locks.m_mutex to
709
MDL_lock::m_rwlock while removal of object from the hash makes
710
it read-only. Therefore whoever acquires MDL_lock::m_rwlock next
711
will see most up to date version of m_ref_usage.
713
This means that when m_is_destroyed is TRUE and we hold the
714
MDL_lock::m_rwlock we can safely read the m_ref_usage
717
846
mysql_mutex_lock(&m_mutex);
718
847
my_hash_delete(&m_locks, (uchar*) lock);
719
lock->m_is_destroyed= TRUE;
720
ref_usage= lock->m_ref_usage;
721
ref_release= lock->m_ref_release;
722
mysql_prlock_unlock(&lock->m_rwlock);
723
mysql_mutex_unlock(&m_mutex);
724
if (ref_usage == ref_release)
725
MDL_lock::destroy(lock);
849
To let threads holding references to the MDL_lock object know that it was
850
moved to the list of unused objects or destroyed, we increment the version
851
counter under protection of both MDL_map::m_mutex and MDL_lock::m_rwlock
852
locks. This allows us to read the version value while having either one
857
if ((lock->key.mdl_namespace() != MDL_key::SCHEMA) &&
858
(m_unused_locks_cache.elements() < mdl_locks_cache_size))
861
This is an object of MDL_object_lock type and the cache of unused
862
objects has not reached its maximum size yet. So instead of destroying
863
object we move it to the list of unused objects to allow its later
864
re-use with possibly different key. Any threads holding references to
865
this object (owning MDL_map::m_mutex or MDL_lock::m_rwlock) will notice
866
this thanks to the fact that we have changed the MDL_lock::m_version
869
DBUG_ASSERT(lock->key.mdl_namespace() != MDL_key::GLOBAL &&
870
lock->key.mdl_namespace() != MDL_key::COMMIT);
872
m_unused_locks_cache.push_front((MDL_object_lock*)lock);
873
mysql_mutex_unlock(&m_mutex);
874
mysql_prlock_unlock(&lock->m_rwlock);
879
Destroy the MDL_lock object, but ensure that anyone that is
880
holding a reference to the object is not remaining, if so he
881
has the responsibility to release it.
883
Setting of m_is_destroyed to TRUE while holding _both_
884
mdl_locks.m_mutex and MDL_lock::m_rwlock mutexes transfers the
885
protection of m_ref_usage from mdl_locks.m_mutex to
886
MDL_lock::m_rwlock while removal of the object from the hash
887
(and cache of unused objects) makes it read-only. Therefore
888
whoever acquires MDL_lock::m_rwlock next will see the most up
889
to date version of m_ref_usage.
891
This means that when m_is_destroyed is TRUE and we hold the
892
MDL_lock::m_rwlock we can safely read the m_ref_usage
895
uint ref_usage, ref_release;
897
lock->m_is_destroyed= TRUE;
898
ref_usage= lock->m_ref_usage;
899
ref_release= lock->m_ref_release;
900
mysql_mutex_unlock(&m_mutex);
901
mysql_prlock_unlock(&lock->m_rwlock);
902
if (ref_usage == ref_release)
903
MDL_lock::destroy(lock);