mariadb/sql/scheduler.cc
Mats Kindahl b1dcf448ea WL#5363: Thread Pool Service Interface
In order to allow thread schedulers to be dynamically loaded,
it is necessary to make the following changes to the server:

- Two new service interfaces

- Modifications to InnoDB to inform the thread scheduler of state changes.

- Changes to the VIO subsystem for checking if data is available on a socket.

- Elimination of remains of the old thread pool implementation.

The two new service interfaces introduces are:

my_thread_scheduler
  A service interface to register a thread
  scheduler.

thd_wait
  A service interface to inform thread scheduler
  that the thread is about to start waiting.

In addition, the patch adds code that:

- Add a call to thd_wait for table locks in mysys
  thd_lock.c by introducing a set function that
  can be used to set a callback to be used when
  waiting on a lock and resuming from waiting.

- Calling the mysys set function from the server
  to set the callbacks correctly.
2010-06-07 16:01:39 +02:00

181 lines
4.8 KiB
C++

/* Copyright (C) 2007 MySQL AB, 2008-2010 Sun Microsystems, Inc.
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 Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Implementation for the thread scheduler
*/
#ifdef USE_PRAGMA_INTERFACE
#pragma implementation
#endif
#include <sql_priv.h>
#include "unireg.h" // REQUIRED: for other includes
#include "scheduler.h"
#include "sql_connect.h" // init_new_connection_handler_thread
#include "scheduler.h"
#include "sql_callback.h"
/*
End connection, in case when we are using 'no-threads'
*/
static bool no_threads_end(THD *thd, bool put_in_cache)
{
unlink_thd(thd);
mysql_mutex_unlock(&LOCK_thread_count);
return 1; // Abort handle_one_connection
}
static scheduler_functions one_thread_scheduler_functions=
{
1, // max_threads
NULL, // init
init_new_connection_handler_thread, // init_new_connection_thread
handle_connection_in_main_thread, // add_connection
NULL, // thd_wait_begin
NULL, // thd_wait_end
NULL, // post_kill_notification
no_threads_end, // end_thread
NULL, // end
};
static scheduler_functions one_thread_per_connection_scheduler_functions=
{
0, // max_threads
NULL, // init
init_new_connection_handler_thread, // init_new_connection_thread
create_thread_to_handle_connection, // add_connection
NULL, // thd_wait_begin
NULL, // thd_wait_end
NULL, // post_kill_notification
one_thread_per_connection_end, // end_thread
NULL, // end
};
scheduler_functions *thread_scheduler=
&one_thread_per_connection_scheduler_functions;
/** @internal
Helper functions to allow mysys to call the thread scheduler when
waiting for locks.
*/
/**@{*/
static void scheduler_wait_begin(void) {
MYSQL_CALLBACK(thread_scheduler,
thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK));
}
static void scheduler_wait_end(void) {
MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd));
}
/**@}*/
/**
Common scheduler init function.
The scheduler is either initialized by calling
one_thread_scheduler() or one_thread_per_connection_scheduler() in
mysqld.cc, so this init function will always be called.
*/
static void scheduler_init() {
thr_set_lock_wait_callback(scheduler_wait_begin, scheduler_wait_end);
}
/*
Initialize scheduler for --thread-handling=one-thread-per-connection
*/
#ifndef EMBEDDED_LIBRARY
void one_thread_per_connection_scheduler()
{
scheduler_init();
one_thread_per_connection_scheduler_functions.max_threads= max_connections;
thread_scheduler= &one_thread_per_connection_scheduler_functions;
}
#endif
/*
Initailize scheduler for --thread-handling=no-threads
*/
void one_thread_scheduler()
{
scheduler_init();
thread_scheduler= &one_thread_scheduler_functions;
}
/*
Initialize scheduler for --thread-handling=one-thread-per-connection
*/
/*
thd_scheduler keeps the link between THD and events.
It's embedded in the THD class.
*/
thd_scheduler::thd_scheduler()
: m_psi(NULL), data(NULL)
{
#ifndef DBUG_OFF
dbug_explain[0]= '\0';
set_explain= FALSE;
#endif
}
thd_scheduler::~thd_scheduler()
{
}
static scheduler_functions *saved_thread_scheduler;
static uint saved_thread_handling;
extern "C"
int my_thread_scheduler_set(scheduler_functions *scheduler)
{
DBUG_ASSERT(scheduler != 0);
if (scheduler == NULL)
return 1;
saved_thread_scheduler= thread_scheduler;
saved_thread_handling= thread_handling;
thread_scheduler= scheduler;
// Scheduler loaded dynamically
thread_handling= SCHEDULER_TYPES_COUNT;
return 0;
}
extern "C"
int my_thread_scheduler_reset()
{
DBUG_ASSERT(saved_thread_scheduler != NULL);
if (saved_thread_scheduler == NULL)
return 1;
thread_scheduler= saved_thread_scheduler;
thread_handling= saved_thread_handling;
saved_thread_scheduler= 0;
return 0;
}