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(
row_mysql_unlock_data_dictionary(ctx->trx);
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) {
fts_sync_during_ddl(ctx->old_table);
......
/*****************************************************************************
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
the terms of the GNU General Public License as published by the Free Software
......@@ -108,22 +108,7 @@ ibool
que_thr_stop(
/*=========*/
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
query thread is stopped and made inactive, except in the case where
......@@ -338,16 +323,10 @@ trx_t::mutex with the exceptions named below */
struct que_thr_t{
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_t* graph; /*!< graph where this node belongs */
que_thr_state_t state; /*!< state of the query thread */
ibool is_active; /*!< TRUE if the thread has been set
to the run state in
que_thr_move_to_run_state, but not
deactivated in
que_thr_dec_reference_count */
bool is_active; /*!< whether the thread is active */
/*------------------------------*/
/* The following fields are private to the OS thread executing the
query thread, and are not protected by any mutex: */
......@@ -378,21 +357,40 @@ struct que_thr_t{
related delete/updates */
row_prebuilt_t* prebuilt; /*!< prebuilt structure processed by
the query thread */
};
#define QUE_THR_MAGIC_N 8476583
#define QUE_THR_MAGIC_FREED 123461526
#ifdef UNIV_DEBUG
/** 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 */
struct que_fork_t{
que_common_t common; /*!< type: QUE_NODE_FORK */
que_t* graph; /*!< query graph of this node */
ulint fork_type; /*!< fork type */
ulint n_active_thrs; /*!< if this is the root of a graph, the
number query threads that have been
started in que_thr_move_to_run_state
but for which que_thr_dec_refer_count
has not yet been called */
#ifdef UNIV_DEBUG
/** For the query graph root, updated in set_active() */
ulint n_active_thrs;
/** Change the 'active' status */
void set_active(bool active);
#endif
trx_t* trx; /*!< transaction: this is set only in
the root node */
ulint state; /*!< state of the fork node */
......@@ -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 */
#define QUE_FORK_SELECT_NON_SCROLL 1 /* forward-only 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. */
/** The locks and state of an active transaction. Protected by
lock_sys.mutex, trx->mutex or both. */
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_STATE_ACTIVE: TRX_QUE_RUNNING,
TRX_QUE_LOCK_WAIT, ... */
......
......@@ -4037,7 +4037,7 @@ lock_table_for_trx(
que_fork_get_first_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:
thr->run_node = thr;
......@@ -4048,7 +4048,7 @@ lock_table_for_trx(
trx->error_state = err;
if (UNIV_LIKELY(err == DB_SUCCESS)) {
que_thr_stop_for_mysql_no_error(thr, trx);
thr->stop_no_error();
} else {
que_thr_stop_for_mysql(thr);
......
/*****************************************************************************
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
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
from a subprocedure: the query thread which requested the operation
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.
@return own: fork node */
......@@ -166,8 +155,6 @@ que_thr_create(
thr->common.parent = parent;
thr->magic_n = QUE_THR_MAGIC_N;
thr->common.type = QUE_NODE_THR;
thr->state = QUE_THR_COMMAND_WAIT;
......@@ -194,7 +181,6 @@ que_thr_end_lock_wait(
QUE_THR_LOCK_WAIT */
{
que_thr_t* thr;
ibool was_active;
ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(trx));
......@@ -207,9 +193,9 @@ que_thr_end_lock_wait(
/* In MySQL this is the only possible state here */
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;
......@@ -231,8 +217,7 @@ que_thr_init_command(
{
thr->run_node = thr;
thr->prev_node = thr->common.parent;
que_thr_move_to_run_state(thr);
thr->start_running();
}
/**********************************************************************//**
......@@ -355,12 +340,9 @@ que_fork_start_command(
}
if (suspended_thr) {
thr = suspended_thr;
que_thr_move_to_run_state(thr);
thr->start_running();
} else if (completed_thr) {
thr = completed_thr;
que_thr_init_command(thr);
} else {
......@@ -429,15 +411,8 @@ que_graph_free_recursive(
break;
case QUE_NODE_THR:
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);
break;
case QUE_NODE_UNDO:
......@@ -633,35 +608,6 @@ que_thr_node_step(
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
conditions are tested in the order (1) graph, (2) trx.
......@@ -725,7 +671,6 @@ que_thr_dec_refer_count(
a new query thread */
{
trx_t* trx;
que_fork_t* fork;
trx = thr_get_trx(thr);
......@@ -762,13 +707,8 @@ que_thr_dec_refer_count(
}
}
fork = static_cast<que_fork_t*>(thr->common.parent);
--trx->lock.n_active_thrs;
--fork->n_active_thrs;
thr->is_active = FALSE;
ut_d(static_cast<que_fork_t*>(thr->common.parent)->set_active(false));
thr->is_active = false;
}
/**********************************************************************//**
......@@ -805,64 +745,31 @@ que_thr_stop_for_mysql(
}
}
ut_ad(thr->is_active == TRUE);
ut_ad(trx->lock.n_active_thrs == 1);
ut_ad(thr->graph->n_active_thrs == 1);
thr->is_active = FALSE;
thr->graph->n_active_thrs--;
trx->lock.n_active_thrs--;
ut_ad(thr->is_active);
ut_d(thr->set_active(false));
thr->is_active= false;
trx_mutex_exit(trx);
}
/**********************************************************************//**
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. */
void
que_thr_move_to_run_state_for_mysql(
/*================================*/
que_thr_t* thr, /*!< in: an query thread */
trx_t* trx) /*!< in: transaction */
#ifdef UNIV_DEBUG
/** Change the 'active' status */
void que_fork_t::set_active(bool active)
{
ut_a(thr->magic_n == QUE_THR_MAGIC_N);
if (!thr->is_active) {
thr->graph->n_active_thrs++;
trx->lock.n_active_thrs++;
thr->is_active = TRUE;
}
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--;
if (active)
{
n_active_thrs++;
trx->lock.n_active_thrs++;
}
else
{
ut_ad(n_active_thrs);
ut_ad(trx->lock.n_active_thrs);
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
......
......@@ -1189,7 +1189,7 @@ row_lock_table_autoinc_for_mysql(
thr = que_fork_get_first_thr(prebuilt->ins_graph);
que_thr_move_to_run_state_for_mysql(thr, trx);
thr->start_running();
run_again:
thr->run_node = node;
......@@ -1218,7 +1218,7 @@ row_lock_table_autoinc_for_mysql(
return(err);
}
que_thr_stop_for_mysql_no_error(thr, trx);
thr->stop_no_error();
trx->op_info = "";
......@@ -1248,7 +1248,7 @@ row_lock_table(row_prebuilt_t* prebuilt)
thr = que_fork_get_first_thr(prebuilt->sel_graph);
que_thr_move_to_run_state_for_mysql(thr, trx);
thr->start_running();
run_again:
thr->run_node = thr;
......@@ -1280,7 +1280,7 @@ row_lock_table(row_prebuilt_t* prebuilt)
return(err);
}
que_thr_stop_for_mysql_no_error(thr, trx);
thr->stop_no_error();
trx->op_info = "";
......@@ -1453,7 +1453,7 @@ row_insert_for_mysql(
node->state = INS_NODE_ALLOC_ROW_ID;
}
que_thr_move_to_run_state_for_mysql(thr, trx);
thr->start_running();
run_again:
thr->run_node = node;
......@@ -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) {
srv_stats.n_system_rows_inserted.inc(size_t(trx->id));
......@@ -1868,7 +1868,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
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());
......@@ -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)
&& trx->fts_next_doc_id != UINT64_UNDEFINED) {
......@@ -3188,7 +3188,7 @@ row_mysql_lock_table(
thr = que_fork_get_first_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:
thr->run_node = thr;
......@@ -3199,7 +3199,7 @@ row_mysql_lock_table(
trx->error_state = err;
if (err == DB_SUCCESS) {
que_thr_stop_for_mysql_no_error(thr, trx);
thr->stop_no_error();
} else {
que_thr_stop_for_mysql(thr);
......
......@@ -4525,7 +4525,7 @@ row_search_mvcc(
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);
......@@ -5676,10 +5676,10 @@ row_search_mvcc(
{
/* handler_index_cond_check() may pull TR_table search
which initates another row_search_mvcc(). */
ulint n_active_thrs= trx->lock.n_active_thrs;
trx->lock.n_active_thrs= 1;
que_thr_stop_for_mysql_no_error(thr, trx);
trx->lock.n_active_thrs= n_active_thrs - 1;
ut_d(ulint n_active_thrs= trx->lock.n_active_thrs);
ut_d(trx->lock.n_active_thrs= 1);
thr->stop_no_error();
ut_d(trx->lock.n_active_thrs= n_active_thrs - 1);
}
mtr.commit();
......
......@@ -1607,7 +1607,7 @@ trx_commit_or_rollback_prepare(
trx->lock.que_state = TRX_QUE_RUNNING;
}
ut_a(trx->lock.n_active_thrs == 1);
ut_ad(trx->lock.n_active_thrs == 1);
return;
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