Commit c20bf8fd authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-21551 Fix calculation of current concurrency level in

maybe_wake_or_create_thread()

A task that is executed,could be counted as waiting (after wait_begin()
before wait_end()) or as long-running (callback runs for a long time).

If task is both marked waiting and long running, then calculation of
current concurrency (# of executing tasks - # of long tasks - #of waiting tasks)
is wrong, as task is counted twice.

Thus current concurrency could go negative, but with unsigned arithmetic
it will become a huge number.

As a result, maybe_wake_or_create_thread() would neither wake or create
a thread, when it should. Which may result in a deadlock.
parent 92d6c132
...@@ -559,6 +559,7 @@ void thread_pool_generic::maintainence() ...@@ -559,6 +559,7 @@ void thread_pool_generic::maintainence()
thread_data = thread_data->m_next) thread_data = thread_data->m_next)
{ {
if (thread_data->is_executing_task() && if (thread_data->is_executing_task() &&
!thread_data->is_waiting() &&
(thread_data->is_long_task() (thread_data->is_long_task()
|| (m_timestamp - thread_data->m_task_start_time > LONG_TASK_DURATION))) || (m_timestamp - thread_data->m_task_start_time > LONG_TASK_DURATION)))
{ {
...@@ -708,6 +709,7 @@ void thread_pool_generic::maybe_wake_or_create_thread() ...@@ -708,6 +709,7 @@ void thread_pool_generic::maybe_wake_or_create_thread()
{ {
if (m_task_queue.empty()) if (m_task_queue.empty())
return; return;
DBUG_ASSERT(m_active_threads.size() >= m_long_tasks_count + m_waiting_task_count);
if (m_active_threads.size() - m_long_tasks_count - m_waiting_task_count > m_concurrency) if (m_active_threads.size() - m_long_tasks_count - m_waiting_task_count > m_concurrency)
return; return;
if (!m_standby_threads.empty()) if (!m_standby_threads.empty())
......
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