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