Commit a2bd936c authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-33161 Function pointer signature mismatch in LF_HASH

In cmake -DWITH_UBSAN=ON builds with clang but not with GCC,
-fsanitize=undefined will flag several runtime errors on
function pointer mismatch related to the lock-free hash table LF_HASH.

Let us use matching function signatures and remove function pointer
casts in order to avoid potential bugs due to undefined behaviour.

These errors could be caught at compilation time by
-Wcast-function-type-strict, which is available starting with clang-16,
but not available in any version of GCC as of now. The old GCC flag
-Wcast-function-type is enabled as part of -Wextra, but it specifically
does not catch these errors.

Reviewed by: Vladislav Vaintroub
parent 246c0b3a
...@@ -242,8 +242,10 @@ void lf_pinbox_put_pins(LF_PINS *pins) ...@@ -242,8 +242,10 @@ void lf_pinbox_put_pins(LF_PINS *pins)
return; return;
} }
static int ptr_cmp(void **a, void **b) static int ptr_cmp(const void *pa, const void *pb)
{ {
const void *const*a= pa;
const void *const*b= pb;
return *a < *b ? -1 : *a == *b ? 0 : 1; return *a < *b ? -1 : *a == *b ? 0 : 1;
} }
...@@ -283,8 +285,10 @@ struct st_harvester { ...@@ -283,8 +285,10 @@ struct st_harvester {
callback forlf_dynarray_iterate: callback forlf_dynarray_iterate:
scan all pins of all threads and accumulate all pins scan all pins of all threads and accumulate all pins
*/ */
static int harvest_pins(LF_PINS *el, struct st_harvester *hv) static int harvest_pins(void *e, void *h)
{ {
LF_PINS *el= e;
struct st_harvester *hv= h;
int i; int i;
LF_PINS *el_end= el+MY_MIN(hv->npins, LF_DYNARRAY_LEVEL_LENGTH); LF_PINS *el_end= el+MY_MIN(hv->npins, LF_DYNARRAY_LEVEL_LENGTH);
for (; el < el_end; el++) for (; el < el_end; el++)
...@@ -310,8 +314,9 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv) ...@@ -310,8 +314,9 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv)
callback forlf_dynarray_iterate: callback forlf_dynarray_iterate:
scan all pins of all threads and see if addr is present there scan all pins of all threads and see if addr is present there
*/ */
static int match_pins(LF_PINS *el, void *addr) static int match_pins(void *e, void *addr)
{ {
LF_PINS *el= e;
int i; int i;
LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH; LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH;
for (; el < el_end; el++) for (; el < el_end; el++)
...@@ -352,13 +357,12 @@ static void lf_pinbox_real_free(LF_PINS *pins) ...@@ -352,13 +357,12 @@ static void lf_pinbox_real_free(LF_PINS *pins)
hv.granary= addr; hv.granary= addr;
hv.npins= npins; hv.npins= npins;
/* scan the dynarray and accumulate all pinned addresses */ /* scan the dynarray and accumulate all pinned addresses */
lf_dynarray_iterate(&pinbox->pinarray, lf_dynarray_iterate(&pinbox->pinarray, harvest_pins, &hv);
(lf_dynarray_func)harvest_pins, &hv);
npins= (int)(hv.granary-addr); npins= (int)(hv.granary-addr);
/* and sort them */ /* and sort them */
if (npins) if (npins)
qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); qsort(addr, npins, sizeof(void *), ptr_cmp);
} }
} }
#endif #endif
...@@ -387,8 +391,7 @@ static void lf_pinbox_real_free(LF_PINS *pins) ...@@ -387,8 +391,7 @@ static void lf_pinbox_real_free(LF_PINS *pins)
} }
else /* no alloca - no cookie. linear search here */ else /* no alloca - no cookie. linear search here */
{ {
if (lf_dynarray_iterate(&pinbox->pinarray, if (lf_dynarray_iterate(&pinbox->pinarray, match_pins, cur))
(lf_dynarray_func)match_pins, cur))
goto found; goto found;
} }
} }
...@@ -416,10 +419,11 @@ static void lf_pinbox_real_free(LF_PINS *pins) ...@@ -416,10 +419,11 @@ static void lf_pinbox_real_free(LF_PINS *pins)
'first' and 'last' are the ends of the linked list of nodes: 'first' and 'last' are the ends of the linked list of nodes:
first->el->el->....->el->last. Use first==last to free only one element. first->el->el->....->el->last. Use first==last to free only one element.
*/ */
static void alloc_free(uchar *first, static void alloc_free(void *f, void *l, void *alloc)
uchar volatile *last,
LF_ALLOCATOR *allocator)
{ {
uchar *first= f;
uchar volatile *last= l;
LF_ALLOCATOR *allocator= alloc;
/* /*
we need a union here to access type-punned pointer reliably. we need a union here to access type-punned pointer reliably.
otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop
...@@ -448,8 +452,7 @@ static void alloc_free(uchar *first, ...@@ -448,8 +452,7 @@ static void alloc_free(uchar *first,
*/ */
void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset) void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset)
{ {
lf_pinbox_init(&allocator->pinbox, free_ptr_offset, lf_pinbox_init(&allocator->pinbox, free_ptr_offset, alloc_free, allocator);
(lf_pinbox_free_func *)alloc_free, allocator);
allocator->top= 0; allocator->top= 0;
allocator->mallocs= 0; allocator->mallocs= 0;
allocator->element_size= size; allocator->element_size= size;
......
...@@ -62,14 +62,10 @@ my_bool safe_mutex_deadlock_detector= 1; /* On by default */ ...@@ -62,14 +62,10 @@ my_bool safe_mutex_deadlock_detector= 1; /* On by default */
static struct st_safe_mutex_create_info_t *safe_mutex_create_root= NULL; static struct st_safe_mutex_create_info_t *safe_mutex_create_root= NULL;
#endif #endif
static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, static my_bool add_used_to_locked_mutex(void *used, void *locked);
safe_mutex_deadlock_t *locked_mutex); static my_bool add_to_locked_mutex(void *locked, void *current);
static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, static my_bool remove_from_locked_mutex(void *m, void* remove);
safe_mutex_t *current_mutex); static my_bool remove_from_used_mutex(void *locked, void *m);
static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
safe_mutex_t *delete_mutex);
static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex,
safe_mutex_t *mutex);
static void print_deadlock_warning(safe_mutex_t *new_mutex, static void print_deadlock_warning(safe_mutex_t *new_mutex,
safe_mutex_t *conflicting_mutex); safe_mutex_t *conflicting_mutex);
#endif #endif
...@@ -373,8 +369,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file, ...@@ -373,8 +369,7 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
are now locking (C) in B->C, then we would add C into are now locking (C) in B->C, then we would add C into
B->locked_mutex and A->locked_mutex B->locked_mutex and A->locked_mutex
*/ */
my_hash_iterate(mutex_root->used_mutex, my_hash_iterate(mutex_root->used_mutex, add_used_to_locked_mutex,
(my_hash_walk_action) add_used_to_locked_mutex,
deadlock); deadlock);
/* /*
...@@ -654,12 +649,8 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp) ...@@ -654,12 +649,8 @@ void safe_mutex_free_deadlock_data(safe_mutex_t *mp)
if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION) && mp->used_mutex != NULL) if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION) && mp->used_mutex != NULL)
{ {
pthread_mutex_lock(&THR_LOCK_mutex); pthread_mutex_lock(&THR_LOCK_mutex);
my_hash_iterate(mp->used_mutex, my_hash_iterate(mp->used_mutex, remove_from_locked_mutex, mp);
(my_hash_walk_action) remove_from_locked_mutex, my_hash_iterate(mp->locked_mutex, remove_from_used_mutex, mp);
mp);
my_hash_iterate(mp->locked_mutex,
(my_hash_walk_action) remove_from_used_mutex,
mp);
pthread_mutex_unlock(&THR_LOCK_mutex); pthread_mutex_unlock(&THR_LOCK_mutex);
my_hash_free(mp->used_mutex); my_hash_free(mp->used_mutex);
...@@ -709,15 +700,15 @@ void safe_mutex_end(FILE *file __attribute__((unused))) ...@@ -709,15 +700,15 @@ void safe_mutex_end(FILE *file __attribute__((unused)))
#endif /* SAFE_MUTEX_DETECT_DESTROY */ #endif /* SAFE_MUTEX_DETECT_DESTROY */
} }
static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, static my_bool add_used_to_locked_mutex(void *used, void *locked)
safe_mutex_deadlock_t *locked_mutex)
{ {
safe_mutex_t *used_mutex= used;
safe_mutex_deadlock_t *locked_mutex= locked;
/* Add mutex to all parent of the current mutex */ /* Add mutex to all parent of the current mutex */
if (!locked_mutex->warning_only) if (!locked_mutex->warning_only)
{ {
(void) my_hash_iterate(locked_mutex->mutex->locked_mutex, (void) my_hash_iterate(locked_mutex->mutex->locked_mutex,
(my_hash_walk_action) add_to_locked_mutex, add_to_locked_mutex, used_mutex);
used_mutex);
/* mark that locked_mutex is locked after used_mutex */ /* mark that locked_mutex is locked after used_mutex */
(void) add_to_locked_mutex(locked_mutex, used_mutex); (void) add_to_locked_mutex(locked_mutex, used_mutex);
} }
...@@ -729,12 +720,13 @@ static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex, ...@@ -729,12 +720,13 @@ static my_bool add_used_to_locked_mutex(safe_mutex_t *used_mutex,
register that locked_mutex was locked after current_mutex register that locked_mutex was locked after current_mutex
*/ */
static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, static my_bool add_to_locked_mutex(void *locked, void *current)
safe_mutex_t *current_mutex)
{ {
safe_mutex_deadlock_t *locked_mutex= locked;
safe_mutex_t *current_mutex= current;
DBUG_ENTER("add_to_locked_mutex"); DBUG_ENTER("add_to_locked_mutex");
DBUG_PRINT("info", ("inserting 0x%lx into 0x%lx (id: %lu -> %lu)", DBUG_PRINT("info", ("inserting %p into %p (id: %lu -> %lu)",
(ulong) locked_mutex, (long) current_mutex, locked_mutex, current_mutex,
locked_mutex->id, current_mutex->id)); locked_mutex->id, current_mutex->id));
if (my_hash_insert(current_mutex->locked_mutex, (uchar*) locked_mutex)) if (my_hash_insert(current_mutex->locked_mutex, (uchar*) locked_mutex))
{ {
...@@ -762,13 +754,14 @@ static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex, ...@@ -762,13 +754,14 @@ static my_bool add_to_locked_mutex(safe_mutex_deadlock_t *locked_mutex,
When counter goes to 0, we delete the safe_mutex_deadlock_t entry. When counter goes to 0, we delete the safe_mutex_deadlock_t entry.
*/ */
static my_bool remove_from_locked_mutex(safe_mutex_t *mp, static my_bool remove_from_locked_mutex(void *m, void *remove)
safe_mutex_t *delete_mutex)
{ {
safe_mutex_t *mp= m;
safe_mutex_t *delete_mutex= remove;
safe_mutex_deadlock_t *found; safe_mutex_deadlock_t *found;
DBUG_ENTER("remove_from_locked_mutex"); DBUG_ENTER("remove_from_locked_mutex");
DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)",
(ulong) delete_mutex, (ulong) mp, delete_mutex, mp,
delete_mutex->id, mp->id)); delete_mutex->id, mp->id));
found= (safe_mutex_deadlock_t *) my_hash_search(mp->locked_mutex, found= (safe_mutex_deadlock_t *) my_hash_search(mp->locked_mutex,
...@@ -786,12 +779,13 @@ static my_bool remove_from_locked_mutex(safe_mutex_t *mp, ...@@ -786,12 +779,13 @@ static my_bool remove_from_locked_mutex(safe_mutex_t *mp,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
static my_bool remove_from_used_mutex(safe_mutex_deadlock_t *locked_mutex, static my_bool remove_from_used_mutex(void *locked, void *m)
safe_mutex_t *mutex)
{ {
safe_mutex_deadlock_t *locked_mutex= locked;
safe_mutex_t *mutex= m;
DBUG_ENTER("remove_from_used_mutex"); DBUG_ENTER("remove_from_used_mutex");
DBUG_PRINT("enter", ("delete_mutex: 0x%lx mutex: 0x%lx (id: %lu <- %lu)", DBUG_PRINT("enter", ("delete_mutex: %p mutex: %p (id: %lu <- %lu)",
(ulong) mutex, (ulong) locked_mutex, mutex, locked_mutex,
mutex->id, locked_mutex->id)); mutex->id, locked_mutex->id));
if (my_hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex)) if (my_hash_delete(locked_mutex->mutex->used_mutex, (uchar*) mutex))
{ {
......
...@@ -424,8 +424,10 @@ static void wt_resource_destroy(uchar *arg) ...@@ -424,8 +424,10 @@ static void wt_resource_destroy(uchar *arg)
It's called from lf_hash when an element is inserted. It's called from lf_hash when an element is inserted.
*/ */
static void wt_resource_init(LF_HASH *hash __attribute__((unused)), static void wt_resource_init(LF_HASH *hash __attribute__((unused)),
WT_RESOURCE *rc, WT_RESOURCE_ID *id) void *resource, const void *ident)
{ {
WT_RESOURCE *rc= resource;
const WT_RESOURCE_ID *id= ident;
DBUG_ENTER("wt_resource_init"); DBUG_ENTER("wt_resource_init");
rc->id= *id; rc->id= *id;
rc->waiter_count= 0; rc->waiter_count= 0;
......
...@@ -762,8 +762,10 @@ struct mdl_iterate_arg ...@@ -762,8 +762,10 @@ struct mdl_iterate_arg
}; };
static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg) static my_bool mdl_iterate_lock(void *lk, void *a)
{ {
MDL_lock *lock= static_cast<MDL_lock*>(lk);
mdl_iterate_arg *arg= static_cast<mdl_iterate_arg*>(a);
/* /*
We can skip check for m_strategy here, becase m_granted We can skip check for m_strategy here, becase m_granted
must be empty for such locks anyway. must be empty for such locks anyway.
...@@ -786,14 +788,13 @@ int mdl_iterate(mdl_iterator_callback callback, void *arg) ...@@ -786,14 +788,13 @@ int mdl_iterate(mdl_iterator_callback callback, void *arg)
{ {
DBUG_ENTER("mdl_iterate"); DBUG_ENTER("mdl_iterate");
mdl_iterate_arg argument= { callback, arg }; mdl_iterate_arg argument= { callback, arg };
LF_PINS *pins= mdl_locks.get_pins();
int res= 1; int res= 1;
if (pins) if (LF_PINS *pins= mdl_locks.get_pins())
{ {
res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) || res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) ||
lf_hash_iterate(&mdl_locks.m_locks, pins, lf_hash_iterate(&mdl_locks.m_locks, pins, mdl_iterate_lock,
(my_hash_walk_action) mdl_iterate_lock, &argument); &argument);
lf_hash_put_pins(pins); lf_hash_put_pins(pins);
} }
DBUG_RETURN(res); DBUG_RETURN(res);
......
...@@ -252,9 +252,10 @@ class list_open_tables_arg ...@@ -252,9 +252,10 @@ class list_open_tables_arg
}; };
static my_bool list_open_tables_callback(TDC_element *element, static my_bool list_open_tables_callback(void *el, void *a)
list_open_tables_arg *arg)
{ {
TDC_element *element= static_cast<TDC_element*>(el);
list_open_tables_arg *arg= static_cast<list_open_tables_arg*>(a);
const Lex_ident_db const Lex_ident_db
db= Lex_ident_db(Lex_cstring_strlen((const char*) element->m_key)); db= Lex_ident_db(Lex_cstring_strlen((const char*) element->m_key));
const char *table_name= db.str + db.length + 1; const char *table_name= db.str + db.length + 1;
...@@ -302,8 +303,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, ...@@ -302,8 +303,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd,
DBUG_ENTER("list_open_tables"); DBUG_ENTER("list_open_tables");
list_open_tables_arg argument(thd, db, wild); list_open_tables_arg argument(thd, db, wild);
if (tdc_iterate(thd, (my_hash_walk_action) list_open_tables_callback, if (tdc_iterate(thd, list_open_tables_callback, &argument, true))
&argument, true))
DBUG_RETURN(0); DBUG_RETURN(0);
DBUG_RETURN(argument.open_list); DBUG_RETURN(argument.open_list);
...@@ -462,9 +462,10 @@ struct tc_collect_arg ...@@ -462,9 +462,10 @@ struct tc_collect_arg
flush_tables_type flush_type; flush_tables_type flush_type;
}; };
static my_bool tc_collect_used_shares(TDC_element *element, static my_bool tc_collect_used_shares(void *el, void *a)
tc_collect_arg *arg)
{ {
TDC_element *element= static_cast<TDC_element*>(el);
tc_collect_arg *arg= static_cast<tc_collect_arg*>(a);
my_bool result= FALSE; my_bool result= FALSE;
DYNAMIC_ARRAY *shares= &arg->shares; DYNAMIC_ARRAY *shares= &arg->shares;
...@@ -573,8 +574,7 @@ bool flush_tables(THD *thd, flush_tables_type flag) ...@@ -573,8 +574,7 @@ bool flush_tables(THD *thd, flush_tables_type flag)
my_init_dynamic_array(PSI_INSTRUMENT_ME, &collect_arg.shares, my_init_dynamic_array(PSI_INSTRUMENT_ME, &collect_arg.shares,
sizeof(TABLE_SHARE*), 100, 100, MYF(0)); sizeof(TABLE_SHARE*), 100, 100, MYF(0));
collect_arg.flush_type= flag; collect_arg.flush_type= flag;
if (tdc_iterate(thd, (my_hash_walk_action) tc_collect_used_shares, if (tdc_iterate(thd, tc_collect_used_shares, &collect_arg, true))
&collect_arg, true))
{ {
/* Release already collected shares */ /* Release already collected shares */
for (uint i= 0 ; i < collect_arg.shares.elements ; i++) for (uint i= 0 ; i < collect_arg.shares.elements ; i++)
......
...@@ -133,9 +133,10 @@ struct close_cached_connection_tables_arg ...@@ -133,9 +133,10 @@ struct close_cached_connection_tables_arg
}; };
static my_bool close_cached_connection_tables_callback( static my_bool close_cached_connection_tables_callback(void *el, void *a)
TDC_element *element, close_cached_connection_tables_arg *arg)
{ {
TDC_element *element= static_cast<TDC_element*>(el);
auto arg= static_cast<close_cached_connection_tables_arg*>(a);
TABLE_LIST *tmp; TABLE_LIST *tmp;
mysql_mutex_lock(&element->LOCK_table_share); mysql_mutex_lock(&element->LOCK_table_share);
...@@ -188,9 +189,7 @@ static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection) ...@@ -188,9 +189,7 @@ static bool close_cached_connection_tables(THD *thd, LEX_CSTRING *connection)
close_cached_connection_tables_arg argument= { thd, connection, 0 }; close_cached_connection_tables_arg argument= { thd, connection, 0 };
DBUG_ENTER("close_cached_connections"); DBUG_ENTER("close_cached_connections");
if (tdc_iterate(thd, if (tdc_iterate(thd, close_cached_connection_tables_callback, &argument))
(my_hash_walk_action) close_cached_connection_tables_callback,
&argument))
DBUG_RETURN(true); DBUG_RETURN(true);
DBUG_RETURN(argument.tables ? DBUG_RETURN(argument.tables ?
......
...@@ -116,7 +116,7 @@ static void print_cached_tables(void) ...@@ -116,7 +116,7 @@ static void print_cached_tables(void)
/* purecov: begin tested */ /* purecov: begin tested */
puts("DB Table Version Thread Open Lock"); puts("DB Table Version Thread Open Lock");
tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true); tdc_iterate(0, print_cached_tables_callback, NULL, true);
fflush(stdout); fflush(stdout);
/* purecov: end */ /* purecov: end */
......
...@@ -309,7 +309,7 @@ void tc_purge() ...@@ -309,7 +309,7 @@ void tc_purge()
{ {
Share_free_tables::List purge_tables; Share_free_tables::List purge_tables;
tdc_iterate(0, (my_hash_walk_action) tc_purge_callback, &purge_tables); tdc_iterate(0, tc_purge_callback, &purge_tables);
while (auto table= purge_tables.pop_front()) while (auto table= purge_tables.pop_front())
intern_close_table(table); intern_close_table(table);
} }
...@@ -1126,7 +1126,7 @@ struct eliminate_duplicates_arg ...@@ -1126,7 +1126,7 @@ struct eliminate_duplicates_arg
static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length, static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length,
my_bool not_used __attribute__((unused))) my_bool)
{ {
LEX_STRING *key= (LEX_STRING *) element; LEX_STRING *key= (LEX_STRING *) element;
*length= key->length; *length= key->length;
...@@ -1134,9 +1134,10 @@ static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length, ...@@ -1134,9 +1134,10 @@ static uchar *eliminate_duplicates_get_key(const uchar *element, size_t *length,
} }
static my_bool eliminate_duplicates(TDC_element *element, static my_bool eliminate_duplicates(void *el, void *a)
eliminate_duplicates_arg *arg)
{ {
TDC_element *element= static_cast<TDC_element*>(el);
eliminate_duplicates_arg *arg= static_cast<eliminate_duplicates_arg*>(a);
LEX_STRING *key= (LEX_STRING *) alloc_root(&arg->root, sizeof(LEX_STRING)); LEX_STRING *key= (LEX_STRING *) alloc_root(&arg->root, sizeof(LEX_STRING));
if (!key || !(key->str= (char*) memdup_root(&arg->root, element->m_key, if (!key || !(key->str= (char*) memdup_root(&arg->root, element->m_key,
...@@ -1182,7 +1183,7 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument, ...@@ -1182,7 +1183,7 @@ int tdc_iterate(THD *thd, my_hash_walk_action action, void *argument,
hash_flags); hash_flags);
no_dups_argument.action= action; no_dups_argument.action= action;
no_dups_argument.argument= argument; no_dups_argument.argument= argument;
action= (my_hash_walk_action) eliminate_duplicates; action= eliminate_duplicates;
argument= &no_dups_argument; argument= &no_dups_argument;
} }
......
...@@ -126,10 +126,11 @@ class XID_cache_element ...@@ -126,10 +126,11 @@ class XID_cache_element
} }
return true; return true;
} }
static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), static void lf_hash_initializer(LF_HASH *, void *el, const void *ie)
XID_cache_element *element,
XID_cache_insert_element *new_element)
{ {
XID_cache_element *element= static_cast<XID_cache_element*>(el);
XID_cache_insert_element *new_element=
static_cast<XID_cache_insert_element*>(const_cast<void*>(ie));
DBUG_ASSERT(!element->is_set(ACQUIRED | RECOVERED)); DBUG_ASSERT(!element->is_set(ACQUIRED | RECOVERED));
element->rm_error= 0; element->rm_error= 0;
element->xa_state= new_element->xa_state; element->xa_state= new_element->xa_state;
...@@ -146,11 +147,11 @@ class XID_cache_element ...@@ -146,11 +147,11 @@ class XID_cache_element
DBUG_ASSERT(!reinterpret_cast<XID_cache_element*>(ptr + LF_HASH_OVERHEAD) DBUG_ASSERT(!reinterpret_cast<XID_cache_element*>(ptr + LF_HASH_OVERHEAD)
->is_set(ACQUIRED)); ->is_set(ACQUIRED));
} }
static uchar *key(const XID_cache_element *element, size_t *length, static uchar *key(const unsigned char *el, size_t *length, my_bool)
my_bool not_used __attribute__((unused)))
{ {
*length= element->xid.key_length(); const XID &xid= reinterpret_cast<const XID_cache_element*>(el)->xid;
return element->xid.key(); *length= xid.key_length();
return xid.key();
} }
}; };
...@@ -221,11 +222,10 @@ void xid_cache_init() ...@@ -221,11 +222,10 @@ void xid_cache_init()
{ {
xid_cache_inited= true; xid_cache_inited= true;
lf_hash_init(&xid_cache, sizeof(XID_cache_element), LF_HASH_UNIQUE, 0, 0, lf_hash_init(&xid_cache, sizeof(XID_cache_element), LF_HASH_UNIQUE, 0, 0,
(my_hash_get_key) XID_cache_element::key, &my_charset_bin); XID_cache_element::key, &my_charset_bin);
xid_cache.alloc.constructor= XID_cache_element::lf_alloc_constructor; xid_cache.alloc.constructor= XID_cache_element::lf_alloc_constructor;
xid_cache.alloc.destructor= XID_cache_element::lf_alloc_destructor; xid_cache.alloc.destructor= XID_cache_element::lf_alloc_destructor;
xid_cache.initializer= xid_cache.initializer= XID_cache_element::lf_hash_initializer;
(lf_hash_initializer) XID_cache_element::lf_hash_initializer;
} }
...@@ -331,9 +331,10 @@ struct xid_cache_iterate_arg ...@@ -331,9 +331,10 @@ struct xid_cache_iterate_arg
void *argument; void *argument;
}; };
static my_bool xid_cache_iterate_callback(XID_cache_element *element, static my_bool xid_cache_iterate_callback(void *el, void *a)
xid_cache_iterate_arg *arg)
{ {
XID_cache_element *element= static_cast<XID_cache_element*>(el);
xid_cache_iterate_arg *arg= static_cast<xid_cache_iterate_arg*>(a);
my_bool res= FALSE; my_bool res= FALSE;
if (element->lock()) if (element->lock())
{ {
...@@ -348,8 +349,7 @@ static int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) ...@@ -348,8 +349,7 @@ static int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg)
xid_cache_iterate_arg argument= { action, arg }; xid_cache_iterate_arg argument= { action, arg };
return thd->fix_xid_hash_pins() ? -1 : return thd->fix_xid_hash_pins() ? -1 :
lf_hash_iterate(&xid_cache, thd->xid_hash_pins, lf_hash_iterate(&xid_cache, thd->xid_hash_pins,
(my_hash_walk_action) xid_cache_iterate_callback, xid_cache_iterate_callback, &argument);
&argument);
} }
...@@ -1039,17 +1039,19 @@ static my_bool xa_recover_callback(XID_cache_element *xs, Protocol *protocol, ...@@ -1039,17 +1039,19 @@ static my_bool xa_recover_callback(XID_cache_element *xs, Protocol *protocol,
} }
static my_bool xa_recover_callback_short(XID_cache_element *xs, static my_bool xa_recover_callback_short(void *x, void *p)
Protocol *protocol)
{ {
XID_cache_element *xs= static_cast<XID_cache_element*>(x);
Protocol *protocol= static_cast<Protocol*>(p);
return xa_recover_callback(xs, protocol, xs->xid.data, return xa_recover_callback(xs, protocol, xs->xid.data,
xs->xid.gtrid_length + xs->xid.bqual_length, &my_charset_bin); xs->xid.gtrid_length + xs->xid.bqual_length, &my_charset_bin);
} }
static my_bool xa_recover_callback_verbose(XID_cache_element *xs, static my_bool xa_recover_callback_verbose(void *x, void *p)
Protocol *protocol)
{ {
XID_cache_element *xs= static_cast<XID_cache_element*>(x);
Protocol *protocol= static_cast<Protocol*>(p);
char buf[SQL_XIDSIZE]; char buf[SQL_XIDSIZE];
uint len= get_sql_xid(&xs->xid, buf); uint len= get_sql_xid(&xs->xid, buf);
return xa_recover_callback(xs, protocol, buf, len, return xa_recover_callback(xs, protocol, buf, len,
...@@ -1082,13 +1084,13 @@ bool mysql_xa_recover(THD *thd) ...@@ -1082,13 +1084,13 @@ bool mysql_xa_recover(THD *thd)
{ {
len= SQL_XIDSIZE; len= SQL_XIDSIZE;
cs= &my_charset_utf8mb3_general_ci; cs= &my_charset_utf8mb3_general_ci;
action= (my_hash_walk_action) xa_recover_callback_verbose; action= xa_recover_callback_verbose;
} }
else else
{ {
len= XIDDATASIZE; len= XIDDATASIZE;
cs= &my_charset_bin; cs= &my_charset_bin;
action= (my_hash_walk_action) xa_recover_callback_short; action= xa_recover_callback_short;
} }
field_list.push_back(new (mem_root) field_list.push_back(new (mem_root)
......
...@@ -453,10 +453,10 @@ class rw_trx_hash_t ...@@ -453,10 +453,10 @@ class rw_trx_hash_t
not accessible by concurrent threads. not accessible by concurrent threads.
*/ */
static void rw_trx_hash_initializer(LF_HASH *, static void rw_trx_hash_initializer(LF_HASH *, void *el, const void *t)
rw_trx_hash_element_t *element,
trx_t *trx)
{ {
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
trx_t *trx= static_cast<trx_t*>(const_cast<void*>(t));
ut_ad(element->trx == 0); ut_ad(element->trx == 0);
element->trx= trx; element->trx= trx;
element->id= trx->id; element->id= trx->id;
...@@ -470,7 +470,7 @@ class rw_trx_hash_t ...@@ -470,7 +470,7 @@ class rw_trx_hash_t
Pins are used to protect object from being destroyed or reused. They are Pins are used to protect object from being destroyed or reused. They are
normally stored in trx object for quick access. If caller doesn't have trx normally stored in trx object for quick access. If caller doesn't have trx
available, we try to get it using currnet_trx(). If caller doesn't have trx available, we try to get it using current_trx(). If caller doesn't have trx
at all, temporary pins are allocated. at all, temporary pins are allocated.
*/ */
...@@ -496,9 +496,10 @@ class rw_trx_hash_t ...@@ -496,9 +496,10 @@ class rw_trx_hash_t
template <typename T> template <typename T>
static my_bool eliminate_duplicates(rw_trx_hash_element_t *element, static my_bool eliminate_duplicates(void *el, void *a)
eliminate_duplicates_arg<T> *arg)
{ {
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
auto arg= static_cast<eliminate_duplicates_arg<T>*>(a);
for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++) for (trx_ids_t::iterator it= arg->ids.begin(); it != arg->ids.end(); it++)
{ {
if (*it == element->id) if (*it == element->id)
...@@ -524,17 +525,17 @@ class rw_trx_hash_t ...@@ -524,17 +525,17 @@ class rw_trx_hash_t
} }
template <typename T> struct debug_iterator_arg struct debug_iterator_arg
{ {
walk_action<T> *action; my_hash_walk_action action;
T *argument; void *argument;
}; };
template <typename T> static my_bool debug_iterator(void *el, void *a)
static my_bool debug_iterator(rw_trx_hash_element_t *element,
debug_iterator_arg<T> *arg)
{ {
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
debug_iterator_arg *arg= static_cast<debug_iterator_arg*>(a);
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
if (element->trx) if (element->trx)
validate_element(element->trx); validate_element(element->trx);
...@@ -744,7 +745,7 @@ class rw_trx_hash_t ...@@ -744,7 +745,7 @@ class rw_trx_hash_t
@param caller_trx used to get/set pins @param caller_trx used to get/set pins
@param action called for every element in hash @param action called for every element in hash
@param argument opque argument passed to action @param argument opaque argument passed to action
May return the same element multiple times if hash is under contention. May return the same element multiple times if hash is under contention.
If caller doesn't like to see the same transaction multiple times, it has If caller doesn't like to see the same transaction multiple times, it has
...@@ -767,28 +768,24 @@ class rw_trx_hash_t ...@@ -767,28 +768,24 @@ class rw_trx_hash_t
@retval 1 iteration was interrupted (action returned 1) @retval 1 iteration was interrupted (action returned 1)
*/ */
template <typename T> int iterate(trx_t *caller_trx, my_hash_walk_action action,
int iterate(trx_t *caller_trx, walk_action<T> *action, T *argument= nullptr) void *argument= nullptr)
{ {
LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash); LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash);
ut_a(pins); ut_a(pins);
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
debug_iterator_arg<T> debug_arg= { action, argument }; debug_iterator_arg debug_arg= { action, argument };
action= reinterpret_cast<decltype(action)>(debug_iterator<T>); action= debug_iterator;
argument= reinterpret_cast<T*>(&debug_arg); argument= reinterpret_cast<void*>(&debug_arg);
#endif #endif
int res= lf_hash_iterate(&hash, pins, int res= lf_hash_iterate(&hash, pins, action, argument);
reinterpret_cast<my_hash_walk_action>(action),
const_cast<void*>(static_cast<const void*>
(argument)));
if (!caller_trx) if (!caller_trx)
lf_hash_put_pins(pins); lf_hash_put_pins(pins);
return res; return res;
} }
template <typename T> int iterate(my_hash_walk_action action, void *argument= nullptr)
int iterate(walk_action<T> *action, T *argument= nullptr)
{ {
return iterate(current_trx(), action, argument); return iterate(current_trx(), action, argument);
} }
...@@ -1176,9 +1173,10 @@ class trx_sys_t ...@@ -1176,9 +1173,10 @@ class trx_sys_t
} }
private: private:
static my_bool get_min_trx_id_callback(rw_trx_hash_element_t *element, static my_bool get_min_trx_id_callback(void *el, void *i)
trx_id_t *id)
{ {
auto element= static_cast<rw_trx_hash_element_t *>(el);
auto id= static_cast<trx_id_t*>(i);
if (element->id < *id) if (element->id < *id)
{ {
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
...@@ -1200,9 +1198,10 @@ class trx_sys_t ...@@ -1200,9 +1198,10 @@ class trx_sys_t
}; };
static my_bool copy_one_id(rw_trx_hash_element_t *element, static my_bool copy_one_id(void* el, void *a)
snapshot_ids_arg *arg)
{ {
auto element= static_cast<const rw_trx_hash_element_t *>(el);
auto arg= static_cast<snapshot_ids_arg*>(a);
if (element->id < arg->m_id) if (element->id < arg->m_id)
{ {
trx_id_t no= element->no; trx_id_t no= element->no;
......
...@@ -5234,8 +5234,9 @@ static void lock_rec_block_validate(const page_id_t page_id) ...@@ -5234,8 +5234,9 @@ static void lock_rec_block_validate(const page_id_t page_id)
} }
static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element, void*) static my_bool lock_validate_table_locks(void *el, void*)
{ {
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
if (element->trx) if (element->trx)
...@@ -5499,10 +5500,10 @@ struct lock_rec_other_trx_holds_expl_arg ...@@ -5499,10 +5500,10 @@ struct lock_rec_other_trx_holds_expl_arg
}; };
static my_bool lock_rec_other_trx_holds_expl_callback( static my_bool lock_rec_other_trx_holds_expl_callback(void *el, void *a)
rw_trx_hash_element_t *element,
lock_rec_other_trx_holds_expl_arg *arg)
{ {
auto element= static_cast<rw_trx_hash_element_t*>(el);
auto arg= static_cast<lock_rec_other_trx_holds_expl_arg*>(a);
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
if (element->trx) if (element->trx)
{ {
...@@ -6325,13 +6326,14 @@ lock_table_get_n_locks( ...@@ -6325,13 +6326,14 @@ lock_table_get_n_locks(
/** /**
Do an exhaustive check for any locks (table or rec) against the table. Do an exhaustive check for any locks (table or rec) against the table.
@param[in] table check if there are any locks held on records in this table @param t check if there are any locks held on records in this table
or on the table itself or on the table itself
*/ */
static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element, static my_bool lock_table_locks_lookup(void *el, void *t)
const dict_table_t *table)
{ {
auto element= static_cast<rw_trx_hash_element_t*>(el);
const dict_table_t *table= static_cast<const dict_table_t*>(t);
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
if (element->trx) if (element->trx)
...@@ -6381,7 +6383,9 @@ lock_table_has_locks( ...@@ -6381,7 +6383,9 @@ lock_table_has_locks(
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (!has_locks) { if (!has_locks) {
trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup, table); trx_sys.rw_trx_hash.iterate(lock_table_locks_lookup,
const_cast<void*>
(static_cast<const void*>(table)));
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
......
...@@ -2053,9 +2053,9 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, ...@@ -2053,9 +2053,9 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element,
} }
static my_bool trx_recover_reset_callback(rw_trx_hash_element_t *element, static my_bool trx_recover_reset_callback(void *el, void*)
void*)
{ {
rw_trx_hash_element_t *element= static_cast<rw_trx_hash_element_t*>(el);
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
if (trx_t *trx= element->trx) if (trx_t *trx= element->trx)
{ {
...@@ -2107,9 +2107,10 @@ struct trx_get_trx_by_xid_callback_arg ...@@ -2107,9 +2107,10 @@ struct trx_get_trx_by_xid_callback_arg
}; };
static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, static my_bool trx_get_trx_by_xid_callback(void *el, void *a)
trx_get_trx_by_xid_callback_arg *arg)
{ {
auto element= static_cast<rw_trx_hash_element_t*>(el);
auto arg= static_cast<trx_get_trx_by_xid_callback_arg*>(a);
my_bool found= 0; my_bool found= 0;
mutex_enter(&element->mutex); mutex_enter(&element->mutex);
if (trx_t *trx= element->trx) if (trx_t *trx= element->trx)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment