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

Cleanup: Reduce que_thr_t, que_fork_t, trx_lock_t size

que_thr_t::magic_n: Remove. Access to freed data is best caught
by AddressSanitizer.

que_thr_t::start_running(): Replaces que_thr_move_to_run_state_for_mysql()
and que_thr_move_to_run_state(), which were identical non-inline functions.

que_thr_t::stop_no_error(): Replaces que_thr_stop_for_mysql_no_error().

que_fork_t::n_active_thrs, trx_lock_t::n_active_thrs: Make debug-only.

que_fork_t::set_active(bool active): Update n_active_thrs.
parent 77e1b0c3
...@@ -7034,7 +7034,7 @@ prepare_inplace_alter_table_dict( ...@@ -7034,7 +7034,7 @@ prepare_inplace_alter_table_dict(
row_mysql_unlock_data_dictionary(ctx->trx); row_mysql_unlock_data_dictionary(ctx->trx);
dict_locked = false; dict_locked = false;
ut_a(ctx->trx->lock.n_active_thrs == 0); ut_ad(!ctx->trx->lock.n_active_thrs);
if (ctx->old_table->fts) { if (ctx->old_table->fts) {
fts_sync_during_ddl(ctx->old_table); fts_sync_during_ddl(ctx->old_table);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -108,22 +108,7 @@ ibool ...@@ -108,22 +108,7 @@ ibool
que_thr_stop( que_thr_stop(
/*=========*/ /*=========*/
que_thr_t* thr); /*!< in: query thread */ que_thr_t* thr); /*!< in: query thread */
/**********************************************************************//**
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
the n_active_thrs counters of the query graph and transaction. */
void
que_thr_move_to_run_state_for_mysql(
/*================================*/
que_thr_t* thr, /*!< in: an query thread */
trx_t* trx); /*!< in: transaction */
/**********************************************************************//**
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
select, when there is no error or lock wait. */
void
que_thr_stop_for_mysql_no_error(
/*============================*/
que_thr_t* thr, /*!< in: query thread */
trx_t* trx); /*!< in: transaction */
/**********************************************************************//** /**********************************************************************//**
A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
query thread is stopped and made inactive, except in the case where query thread is stopped and made inactive, except in the case where
...@@ -338,16 +323,10 @@ trx_t::mutex with the exceptions named below */ ...@@ -338,16 +323,10 @@ trx_t::mutex with the exceptions named below */
struct que_thr_t{ struct que_thr_t{
que_common_t common; /*!< type: QUE_NODE_THR */ que_common_t common; /*!< type: QUE_NODE_THR */
ulint magic_n; /*!< magic number to catch memory
corruption */
que_node_t* child; /*!< graph child node */ que_node_t* child; /*!< graph child node */
que_t* graph; /*!< graph where this node belongs */ que_t* graph; /*!< graph where this node belongs */
que_thr_state_t state; /*!< state of the query thread */ que_thr_state_t state; /*!< state of the query thread */
ibool is_active; /*!< TRUE if the thread has been set bool is_active; /*!< whether the thread is active */
to the run state in
que_thr_move_to_run_state, but not
deactivated in
que_thr_dec_reference_count */
/*------------------------------*/ /*------------------------------*/
/* The following fields are private to the OS thread executing the /* The following fields are private to the OS thread executing the
query thread, and are not protected by any mutex: */ query thread, and are not protected by any mutex: */
...@@ -378,21 +357,40 @@ struct que_thr_t{ ...@@ -378,21 +357,40 @@ struct que_thr_t{
related delete/updates */ related delete/updates */
row_prebuilt_t* prebuilt; /*!< prebuilt structure processed by row_prebuilt_t* prebuilt; /*!< prebuilt structure processed by
the query thread */ the query thread */
};
#define QUE_THR_MAGIC_N 8476583 #ifdef UNIV_DEBUG
#define QUE_THR_MAGIC_FREED 123461526 /** Change the 'active' status */
inline void set_active(bool active);
#endif
/** Transition to the QUE_THR_RUNNING state. */
inline void start_running()
{
ut_d(if (!is_active) set_active(true));
is_active= true;
state= QUE_THR_RUNNING;
}
/** Stop query execution when there is no error or lock wait. */
void stop_no_error()
{
ut_ad(is_active);
ut_d(set_active(false));
state= QUE_THR_COMPLETED;
is_active= false;
}
};
/* Query graph fork node: its fields are protected by the query thread mutex */ /* Query graph fork node: its fields are protected by the query thread mutex */
struct que_fork_t{ struct que_fork_t{
que_common_t common; /*!< type: QUE_NODE_FORK */ que_common_t common; /*!< type: QUE_NODE_FORK */
que_t* graph; /*!< query graph of this node */ que_t* graph; /*!< query graph of this node */
ulint fork_type; /*!< fork type */ ulint fork_type; /*!< fork type */
ulint n_active_thrs; /*!< if this is the root of a graph, the #ifdef UNIV_DEBUG
number query threads that have been /** For the query graph root, updated in set_active() */
started in que_thr_move_to_run_state ulint n_active_thrs;
but for which que_thr_dec_refer_count /** Change the 'active' status */
has not yet been called */ void set_active(bool active);
#endif
trx_t* trx; /*!< transaction: this is set only in trx_t* trx; /*!< transaction: this is set only in
the root node */ the root node */
ulint state; /*!< state of the fork node */ ulint state; /*!< state of the fork node */
...@@ -418,6 +416,10 @@ struct que_fork_t{ ...@@ -418,6 +416,10 @@ struct que_fork_t{
}; };
#ifdef UNIV_DEBUG
inline void que_thr_t::set_active(bool active) { graph->set_active(active); };
#endif
/* Query fork (or graph) types */ /* Query fork (or graph) types */
#define QUE_FORK_SELECT_NON_SCROLL 1 /* forward-only cursor */ #define QUE_FORK_SELECT_NON_SCROLL 1 /* forward-only cursor */
#define QUE_FORK_SELECT_SCROLL 2 /* scrollable cursor */ #define QUE_FORK_SELECT_SCROLL 2 /* scrollable cursor */
......
...@@ -511,8 +511,11 @@ code and no mutex is required when the query thread is no longer waiting. */ ...@@ -511,8 +511,11 @@ code and no mutex is required when the query thread is no longer waiting. */
/** The locks and state of an active transaction. Protected by /** The locks and state of an active transaction. Protected by
lock_sys.mutex, trx->mutex or both. */ lock_sys.mutex, trx->mutex or both. */
struct trx_lock_t { struct trx_lock_t {
ulint n_active_thrs; /*!< number of active query threads */ #ifdef UNIV_DEBUG
/** number of active query threads; at most 1, except for the
dummy transaction in trx_purge() */
ulint n_active_thrs;
#endif
trx_que_t que_state; /*!< valid when trx->state trx_que_t que_state; /*!< valid when trx->state
== TRX_STATE_ACTIVE: TRX_QUE_RUNNING, == TRX_STATE_ACTIVE: TRX_QUE_RUNNING,
TRX_QUE_LOCK_WAIT, ... */ TRX_QUE_LOCK_WAIT, ... */
......
...@@ -4037,7 +4037,7 @@ lock_table_for_trx( ...@@ -4037,7 +4037,7 @@ lock_table_for_trx(
que_fork_get_first_thr( que_fork_get_first_thr(
static_cast<que_fork_t*>(que_node_get_parent(thr)))); static_cast<que_fork_t*>(que_node_get_parent(thr))));
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
run_again: run_again:
thr->run_node = thr; thr->run_node = thr;
...@@ -4048,7 +4048,7 @@ lock_table_for_trx( ...@@ -4048,7 +4048,7 @@ lock_table_for_trx(
trx->error_state = err; trx->error_state = err;
if (UNIV_LIKELY(err == DB_SUCCESS)) { if (UNIV_LIKELY(err == DB_SUCCESS)) {
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
} else { } else {
que_thr_stop_for_mysql(thr); que_thr_stop_for_mysql(thr);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, 2020 MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -96,17 +96,6 @@ When the execution of the graph completes, it is like returning ...@@ -96,17 +96,6 @@ When the execution of the graph completes, it is like returning
from a subprocedure: the query thread which requested the operation from a subprocedure: the query thread which requested the operation
starts running again. */ starts running again. */
/**********************************************************************//**
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
the n_active_thrs counters of the query graph and transaction.
***NOTE***: This is the only function in which such a transition is allowed
to happen! */
static
void
que_thr_move_to_run_state(
/*======================*/
que_thr_t* thr); /*!< in: an query thread */
/***********************************************************************//** /***********************************************************************//**
Creates a query graph fork node. Creates a query graph fork node.
@return own: fork node */ @return own: fork node */
...@@ -166,8 +155,6 @@ que_thr_create( ...@@ -166,8 +155,6 @@ que_thr_create(
thr->common.parent = parent; thr->common.parent = parent;
thr->magic_n = QUE_THR_MAGIC_N;
thr->common.type = QUE_NODE_THR; thr->common.type = QUE_NODE_THR;
thr->state = QUE_THR_COMMAND_WAIT; thr->state = QUE_THR_COMMAND_WAIT;
...@@ -194,7 +181,6 @@ que_thr_end_lock_wait( ...@@ -194,7 +181,6 @@ que_thr_end_lock_wait(
QUE_THR_LOCK_WAIT */ QUE_THR_LOCK_WAIT */
{ {
que_thr_t* thr; que_thr_t* thr;
ibool was_active;
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(trx)); ut_ad(trx_mutex_own(trx));
...@@ -207,9 +193,9 @@ que_thr_end_lock_wait( ...@@ -207,9 +193,9 @@ que_thr_end_lock_wait(
/* In MySQL this is the only possible state here */ /* In MySQL this is the only possible state here */
ut_a(thr->state == QUE_THR_LOCK_WAIT); ut_a(thr->state == QUE_THR_LOCK_WAIT);
was_active = thr->is_active; bool was_active = thr->is_active;
que_thr_move_to_run_state(thr); thr->start_running();
trx->lock.que_state = TRX_QUE_RUNNING; trx->lock.que_state = TRX_QUE_RUNNING;
...@@ -231,8 +217,7 @@ que_thr_init_command( ...@@ -231,8 +217,7 @@ que_thr_init_command(
{ {
thr->run_node = thr; thr->run_node = thr;
thr->prev_node = thr->common.parent; thr->prev_node = thr->common.parent;
thr->start_running();
que_thr_move_to_run_state(thr);
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -355,12 +340,9 @@ que_fork_start_command( ...@@ -355,12 +340,9 @@ que_fork_start_command(
} }
if (suspended_thr) { if (suspended_thr) {
thr = suspended_thr; thr = suspended_thr;
que_thr_move_to_run_state(thr); thr->start_running();
} else if (completed_thr) { } else if (completed_thr) {
thr = completed_thr; thr = completed_thr;
que_thr_init_command(thr); que_thr_init_command(thr);
} else { } else {
...@@ -429,15 +411,8 @@ que_graph_free_recursive( ...@@ -429,15 +411,8 @@ que_graph_free_recursive(
break; break;
case QUE_NODE_THR: case QUE_NODE_THR:
thr = static_cast<que_thr_t*>(node); thr = static_cast<que_thr_t*>(node);
ut_a(thr->magic_n == QUE_THR_MAGIC_N);
thr->magic_n = QUE_THR_MAGIC_FREED;
que_graph_free_recursive(thr->child); que_graph_free_recursive(thr->child);
break; break;
case QUE_NODE_UNDO: case QUE_NODE_UNDO:
...@@ -633,35 +608,6 @@ que_thr_node_step( ...@@ -633,35 +608,6 @@ que_thr_node_step(
return(NULL); return(NULL);
} }
/**********************************************************************//**
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
the n_active_thrs counters of the query graph and transaction if thr was
not active.
***NOTE***: This and ..._mysql are the only functions in which such a
transition is allowed to happen! */
static
void
que_thr_move_to_run_state(
/*======================*/
que_thr_t* thr) /*!< in: an query thread */
{
ut_ad(thr->state != QUE_THR_RUNNING);
if (!thr->is_active) {
trx_t* trx;
trx = thr_get_trx(thr);
thr->graph->n_active_thrs++;
trx->lock.n_active_thrs++;
thr->is_active = TRUE;
}
thr->state = QUE_THR_RUNNING;
}
/**********************************************************************//** /**********************************************************************//**
Stops a query thread if graph or trx is in a state requiring it. The Stops a query thread if graph or trx is in a state requiring it. The
conditions are tested in the order (1) graph, (2) trx. conditions are tested in the order (1) graph, (2) trx.
...@@ -725,7 +671,6 @@ que_thr_dec_refer_count( ...@@ -725,7 +671,6 @@ que_thr_dec_refer_count(
a new query thread */ a new query thread */
{ {
trx_t* trx; trx_t* trx;
que_fork_t* fork;
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
...@@ -762,13 +707,8 @@ que_thr_dec_refer_count( ...@@ -762,13 +707,8 @@ que_thr_dec_refer_count(
} }
} }
fork = static_cast<que_fork_t*>(thr->common.parent); ut_d(static_cast<que_fork_t*>(thr->common.parent)->set_active(false));
thr->is_active = false;
--trx->lock.n_active_thrs;
--fork->n_active_thrs;
thr->is_active = FALSE;
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -805,64 +745,31 @@ que_thr_stop_for_mysql( ...@@ -805,64 +745,31 @@ que_thr_stop_for_mysql(
} }
} }
ut_ad(thr->is_active == TRUE); ut_ad(thr->is_active);
ut_ad(trx->lock.n_active_thrs == 1); ut_d(thr->set_active(false));
ut_ad(thr->graph->n_active_thrs == 1); thr->is_active= false;
thr->is_active = FALSE;
thr->graph->n_active_thrs--;
trx->lock.n_active_thrs--;
trx_mutex_exit(trx); trx_mutex_exit(trx);
} }
/**********************************************************************//** #ifdef UNIV_DEBUG
Moves a thread from another state to the QUE_THR_RUNNING state. Increments /** Change the 'active' status */
the n_active_thrs counters of the query graph and transaction if thr was void que_fork_t::set_active(bool active)
not active. */
void
que_thr_move_to_run_state_for_mysql(
/*================================*/
que_thr_t* thr, /*!< in: an query thread */
trx_t* trx) /*!< in: transaction */
{ {
ut_a(thr->magic_n == QUE_THR_MAGIC_N); if (active)
{
if (!thr->is_active) { n_active_thrs++;
trx->lock.n_active_thrs++;
thr->graph->n_active_thrs++; }
else
trx->lock.n_active_thrs++; {
ut_ad(n_active_thrs);
thr->is_active = TRUE; ut_ad(trx->lock.n_active_thrs);
} n_active_thrs--;
trx->lock.n_active_thrs--;
thr->state = QUE_THR_RUNNING; }
}
/**********************************************************************//**
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
select, when there is no error or lock wait. */
void
que_thr_stop_for_mysql_no_error(
/*============================*/
que_thr_t* thr, /*!< in: query thread */
trx_t* trx) /*!< in: transaction */
{
ut_ad(thr->state == QUE_THR_RUNNING);
ut_ad(thr->is_active == TRUE);
ut_ad(trx->lock.n_active_thrs == 1);
ut_ad(thr->graph->n_active_thrs == 1);
ut_a(thr->magic_n == QUE_THR_MAGIC_N);
thr->state = QUE_THR_COMPLETED;
thr->is_active = FALSE;
thr->graph->n_active_thrs--;
trx->lock.n_active_thrs--;
} }
#endif
/****************************************************************//** /****************************************************************//**
Get the first containing loop node (e.g. while_node_t or for_node_t) for the Get the first containing loop node (e.g. while_node_t or for_node_t) for the
......
...@@ -1189,7 +1189,7 @@ row_lock_table_autoinc_for_mysql( ...@@ -1189,7 +1189,7 @@ row_lock_table_autoinc_for_mysql(
thr = que_fork_get_first_thr(prebuilt->ins_graph); thr = que_fork_get_first_thr(prebuilt->ins_graph);
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
run_again: run_again:
thr->run_node = node; thr->run_node = node;
...@@ -1218,7 +1218,7 @@ row_lock_table_autoinc_for_mysql( ...@@ -1218,7 +1218,7 @@ row_lock_table_autoinc_for_mysql(
return(err); return(err);
} }
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
trx->op_info = ""; trx->op_info = "";
...@@ -1248,7 +1248,7 @@ row_lock_table(row_prebuilt_t* prebuilt) ...@@ -1248,7 +1248,7 @@ row_lock_table(row_prebuilt_t* prebuilt)
thr = que_fork_get_first_thr(prebuilt->sel_graph); thr = que_fork_get_first_thr(prebuilt->sel_graph);
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
run_again: run_again:
thr->run_node = thr; thr->run_node = thr;
...@@ -1280,7 +1280,7 @@ row_lock_table(row_prebuilt_t* prebuilt) ...@@ -1280,7 +1280,7 @@ row_lock_table(row_prebuilt_t* prebuilt)
return(err); return(err);
} }
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
trx->op_info = ""; trx->op_info = "";
...@@ -1453,7 +1453,7 @@ row_insert_for_mysql( ...@@ -1453,7 +1453,7 @@ row_insert_for_mysql(
node->state = INS_NODE_ALLOC_ROW_ID; node->state = INS_NODE_ALLOC_ROW_ID;
} }
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
run_again: run_again:
thr->run_node = node; thr->run_node = node;
...@@ -1555,7 +1555,7 @@ row_insert_for_mysql( ...@@ -1555,7 +1555,7 @@ row_insert_for_mysql(
} }
} }
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
if (table->is_system_db) { if (table->is_system_db) {
srv_stats.n_system_rows_inserted.inc(size_t(trx->id)); srv_stats.n_system_rows_inserted.inc(size_t(trx->id));
...@@ -1868,7 +1868,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) ...@@ -1868,7 +1868,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
ut_ad(!prebuilt->sql_stat_start); ut_ad(!prebuilt->sql_stat_start);
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
ut_ad(!prebuilt->versioned_write || node->table->versioned()); ut_ad(!prebuilt->versioned_write || node->table->versioned());
...@@ -1913,7 +1913,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) ...@@ -1913,7 +1913,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
} }
} }
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
if (dict_table_has_fts_index(table) if (dict_table_has_fts_index(table)
&& trx->fts_next_doc_id != UINT64_UNDEFINED) { && trx->fts_next_doc_id != UINT64_UNDEFINED) {
...@@ -3188,7 +3188,7 @@ row_mysql_lock_table( ...@@ -3188,7 +3188,7 @@ row_mysql_lock_table(
thr = que_fork_get_first_thr( thr = que_fork_get_first_thr(
static_cast<que_fork_t*>(que_node_get_parent(thr))); static_cast<que_fork_t*>(que_node_get_parent(thr)));
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
run_again: run_again:
thr->run_node = thr; thr->run_node = thr;
...@@ -3199,7 +3199,7 @@ row_mysql_lock_table( ...@@ -3199,7 +3199,7 @@ row_mysql_lock_table(
trx->error_state = err; trx->error_state = err;
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
} else { } else {
que_thr_stop_for_mysql(thr); que_thr_stop_for_mysql(thr);
......
...@@ -4525,7 +4525,7 @@ row_search_mvcc( ...@@ -4525,7 +4525,7 @@ row_search_mvcc(
thr = que_fork_get_first_thr(prebuilt->sel_graph); thr = que_fork_get_first_thr(prebuilt->sel_graph);
que_thr_move_to_run_state_for_mysql(thr, trx); thr->start_running();
clust_index = dict_table_get_first_index(prebuilt->table); clust_index = dict_table_get_first_index(prebuilt->table);
...@@ -5676,10 +5676,10 @@ row_search_mvcc( ...@@ -5676,10 +5676,10 @@ row_search_mvcc(
{ {
/* handler_index_cond_check() may pull TR_table search /* handler_index_cond_check() may pull TR_table search
which initates another row_search_mvcc(). */ which initates another row_search_mvcc(). */
ulint n_active_thrs= trx->lock.n_active_thrs; ut_d(ulint n_active_thrs= trx->lock.n_active_thrs);
trx->lock.n_active_thrs= 1; ut_d(trx->lock.n_active_thrs= 1);
que_thr_stop_for_mysql_no_error(thr, trx); thr->stop_no_error();
trx->lock.n_active_thrs= n_active_thrs - 1; ut_d(trx->lock.n_active_thrs= n_active_thrs - 1);
} }
mtr.commit(); mtr.commit();
......
...@@ -1607,7 +1607,7 @@ trx_commit_or_rollback_prepare( ...@@ -1607,7 +1607,7 @@ trx_commit_or_rollback_prepare(
trx->lock.que_state = TRX_QUE_RUNNING; trx->lock.que_state = TRX_QUE_RUNNING;
} }
ut_a(trx->lock.n_active_thrs == 1); ut_ad(trx->lock.n_active_thrs == 1);
return; return;
case TRX_STATE_COMMITTED_IN_MEMORY: case TRX_STATE_COMMITTED_IN_MEMORY:
......
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