1 /* Copyright (c) 2007, 2013, Oracle and/or its affiliates.
2    Copyright (c) 2012, 2014, SkySQL Ab.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 /*
18   Implementation for the thread scheduler
19 */
20 
21 #ifdef USE_PRAGMA_INTERFACE
22 #pragma implementation
23 #endif
24 
25 #include "mariadb.h"
26 #include "mysqld.h"
27 #include "scheduler.h"
28 #include "sql_class.h"
29 #include "sql_callback.h"
30 #include <violite.h>
31 
32 /** @internal
33   Helper functions to allow mysys to call the thread scheduler when
34   waiting for locks.
35 */
36 
37 /**@{*/
38 extern "C"
39 {
scheduler_wait_lock_begin(void)40 static void scheduler_wait_lock_begin(void) {
41   thd_wait_begin(NULL, THD_WAIT_TABLE_LOCK);
42 }
43 
scheduler_wait_lock_end(void)44 static void scheduler_wait_lock_end(void) {
45   thd_wait_end(NULL);
46 }
47 
scheduler_wait_sync_begin(void)48 static void scheduler_wait_sync_begin(void) {
49   thd_wait_begin(NULL, THD_WAIT_SYNC);
50 }
51 
scheduler_wait_sync_end(void)52 static void scheduler_wait_sync_end(void) {
53   thd_wait_end(NULL);
54 }
55 
scheduler_wait_net_begin(void)56 static void scheduler_wait_net_begin(void) {
57    thd_wait_begin(NULL, THD_WAIT_NET);
58 }
59 
scheduler_wait_net_end(void)60 static void scheduler_wait_net_end(void) {
61    thd_wait_end(NULL);
62 }
63 
64 };
65 /**@}*/
66 
67 /**
68   Common scheduler init function.
69 
70   The scheduler is either initialized by calling
71   one_thread_scheduler() or one_thread_per_connection_scheduler() in
72   mysqld.cc, so this init function will always be called.
73  */
74 
scheduler_init()75 void scheduler_init()
76 {
77   thr_set_lock_wait_callback(scheduler_wait_lock_begin,
78                              scheduler_wait_lock_end);
79   thr_set_sync_wait_callback(scheduler_wait_sync_begin,
80                              scheduler_wait_sync_end);
81 
82   vio_set_wait_callback(scheduler_wait_net_begin,
83     scheduler_wait_net_end);
84 }
85 
86 
87 /**
88   Kill notification callback,  used by  one-thread-per-connection
89   and threadpool scheduler.
90 
91   Wakes up a thread that is stuck in read/poll/epoll/event-poll
92   routines used by threadpool, such that subsequent attempt to
93   read from  client connection will result in IO error.
94 */
95 
post_kill_notification(THD * thd)96 void post_kill_notification(THD *thd)
97 {
98   DBUG_ENTER("post_kill_notification");
99   if (current_thd == thd || thd->system_thread)
100     DBUG_VOID_RETURN;
101 
102   if (thd->net.vio)
103     vio_shutdown(thd->net.vio, SHUT_RD);
104   DBUG_VOID_RETURN;
105 }
106 
107 /*
108   Initialize scheduler for --thread-handling=one-thread-per-connection
109 */
110 
111 #ifndef EMBEDDED_LIBRARY
112 
one_thread_per_connection_scheduler(scheduler_functions * func,ulong * arg_max_connections,Atomic_counter<uint> * arg_connection_count)113 void one_thread_per_connection_scheduler(scheduler_functions *func,
114     ulong *arg_max_connections,
115     Atomic_counter<uint> *arg_connection_count)
116 {
117   scheduler_init();
118   func->max_threads= *arg_max_connections + 1;
119   func->max_connections= arg_max_connections;
120   func->connection_count= arg_connection_count;
121   func->add_connection= create_thread_to_handle_connection;
122   func->post_kill_notification= post_kill_notification;
123 }
124 #else
handle_connection_in_main_thread(CONNECT * connect)125 void handle_connection_in_main_thread(CONNECT *connect)
126 {
127 }
128 #endif
129 
130 /*
131   Initialize scheduler for --thread-handling=no-threads
132 */
133 
one_thread_scheduler(scheduler_functions * func)134 void one_thread_scheduler(scheduler_functions *func)
135 {
136   scheduler_init();
137   func->max_threads= 1;
138   func->max_connections= &max_connections;
139   func->connection_count= &connection_count;
140   func->add_connection= handle_connection_in_main_thread;
141 }
142