scheduler.cc 4.9 KB
Newer Older
Marc Alff's avatar
Marc Alff committed
1
/* Copyright (C) 2007 MySQL AB, 2008-2010 Sun Microsystems, Inc.
unknown's avatar
unknown committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

   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

24 25 26 27
#include <sql_priv.h>
#include "unireg.h"                    // REQUIRED: for other includes
#include "scheduler.h"
#include "sql_connect.h"         // init_new_connection_handler_thread
28 29
#include "scheduler.h"
#include "sql_callback.h"
unknown's avatar
unknown committed
30 31

/*
32 33
  End connection, in case when we are using 'no-threads'
*/
unknown's avatar
unknown committed
34

35 36 37 38 39 40
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
}
unknown's avatar
unknown committed
41

42 43 44 45 46
static scheduler_functions one_thread_scheduler_functions=
{
  1,                                     // max_threads
  NULL,                                  // init
  init_new_connection_handler_thread,    // init_new_connection_thread
47
#ifndef EMBEDDED_LIBRARY
48
  handle_connection_in_main_thread,      // add_connection
49 50 51
#else
  NULL,                                  // add_connection
#endif // EMBEDDED_LIBRARY
52 53 54 55 56 57 58
  NULL,                                  // thd_wait_begin
  NULL,                                  // thd_wait_end
  NULL,                                  // post_kill_notification
  no_threads_end,                        // end_thread
  NULL,                                  // end
};

59
#ifndef EMBEDDED_LIBRARY
60 61 62 63 64 65 66 67 68 69 70 71
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
};
72
#endif  // EMBEDDED_LIBRARY
73 74


75
scheduler_functions *thread_scheduler= NULL;
76 77 78 79

/** @internal
  Helper functions to allow mysys to call the thread scheduler when
  waiting for locks.
unknown's avatar
unknown committed
80 81
*/

82 83 84 85 86
/**@{*/
static void scheduler_wait_begin(void) {
  MYSQL_CALLBACK(thread_scheduler,
                 thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK));
}
unknown's avatar
unknown committed
87

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
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);
}
unknown's avatar
unknown committed
103 104

/*
105
  Initialize scheduler for --thread-handling=one-thread-per-connection
unknown's avatar
unknown committed
106 107
*/

108 109
#ifndef EMBEDDED_LIBRARY
void one_thread_per_connection_scheduler()
unknown's avatar
unknown committed
110
{
111 112 113
  scheduler_init();
  one_thread_per_connection_scheduler_functions.max_threads= max_connections;
  thread_scheduler= &one_thread_per_connection_scheduler_functions;
unknown's avatar
unknown committed
114
}
115
#endif
unknown's avatar
unknown committed
116 117 118 119 120

/*
  Initailize scheduler for --thread-handling=no-threads
*/

121
void one_thread_scheduler()
unknown's avatar
unknown committed
122
{
123 124
  scheduler_init();
  thread_scheduler= &one_thread_scheduler_functions;
unknown's avatar
unknown committed
125 126 127 128 129 130 131
}


/*
  Initialize scheduler for --thread-handling=one-thread-per-connection
*/

132 133 134 135 136 137 138
/*
  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)
unknown's avatar
unknown committed
139
{
140 141 142 143
#ifndef DBUG_OFF
  dbug_explain[0]= '\0';
  set_explain= FALSE;
#endif
unknown's avatar
unknown committed
144
}
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186


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;
}