1 | /* |
2 | Copyright (c) 2009, 2011, Monty Program 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 Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
16 | |
17 | #include "maria_def.h" |
18 | #include "ma_servicethread.h" |
19 | |
20 | /** |
21 | Initializes the service thread |
22 | |
23 | @param control control block |
24 | |
25 | @return Operation status |
26 | @retval 0 OK |
27 | @retval 1 error |
28 | */ |
29 | |
30 | int ma_service_thread_control_init(MA_SERVICE_THREAD_CONTROL *control) |
31 | { |
32 | int res= 0; |
33 | DBUG_ENTER("ma_service_thread_control_init" ); |
34 | DBUG_PRINT("init" , ("control %p" , control)); |
35 | control->inited= TRUE; |
36 | control->killed= FALSE; |
37 | res= (mysql_mutex_init(key_SERVICE_THREAD_CONTROL_lock, |
38 | control->LOCK_control, MY_MUTEX_INIT_SLOW) || |
39 | mysql_cond_init(key_SERVICE_THREAD_CONTROL_cond, |
40 | control->COND_control, 0)); |
41 | DBUG_PRINT("info" , ("init: %s" , (res ? "Error" : "OK" ))); |
42 | DBUG_RETURN(res); |
43 | } |
44 | |
45 | |
46 | /** |
47 | Kill the service thread |
48 | |
49 | @param control control block |
50 | |
51 | @note The service thread should react on condition and status equal |
52 | THREAD_DYING, by setting status THREAD_DEAD, and issuing message to |
53 | control thread via condition and exiting. The base way to do so is using |
54 | my_service_thread_sleep() and my_service_thread_signal_end() |
55 | */ |
56 | |
57 | void ma_service_thread_control_end(MA_SERVICE_THREAD_CONTROL *control) |
58 | { |
59 | DBUG_ENTER("ma_service_thread_control_end" ); |
60 | DBUG_PRINT("init" , ("control %p" , control)); |
61 | DBUG_ASSERT(control->inited); |
62 | mysql_mutex_lock(control->LOCK_control); |
63 | if (!control->killed) |
64 | { |
65 | DBUG_PRINT("info" ,("killing Maria background thread" )); |
66 | control->killed= TRUE; /* kill it */ |
67 | mysql_cond_broadcast(control->COND_control); |
68 | mysql_mutex_unlock(control->LOCK_control); |
69 | DBUG_PRINT("info" , ("waiting for Maria background thread to die" )); |
70 | pthread_join(control->thread, NULL); |
71 | } |
72 | else |
73 | mysql_mutex_unlock(control->LOCK_control); |
74 | mysql_mutex_destroy(control->LOCK_control); |
75 | mysql_cond_destroy(control->COND_control); |
76 | control->inited= FALSE; |
77 | DBUG_VOID_RETURN; |
78 | } |
79 | |
80 | |
81 | /** |
82 | Sleep for given number of nanoseconds with reaction on thread kill |
83 | |
84 | @param control control block |
85 | @param sleep_time time of sleeping |
86 | |
87 | @return Operation status |
88 | @retval FALSE Time out |
89 | @retval TRUE Thread should be killed |
90 | */ |
91 | |
92 | my_bool my_service_thread_sleep(MA_SERVICE_THREAD_CONTROL *control, |
93 | ulonglong sleep_time) |
94 | { |
95 | struct timespec abstime; |
96 | my_bool res= FALSE; |
97 | DBUG_ENTER("my_service_thread_sleep" ); |
98 | DBUG_PRINT("init" , ("control %p" , control)); |
99 | mysql_mutex_lock(control->LOCK_control); |
100 | if (control->killed) |
101 | { |
102 | mysql_mutex_unlock(control->LOCK_control); |
103 | DBUG_RETURN(TRUE); |
104 | } |
105 | #if 0 /* good for testing, to do a lot of checkpoints, finds a lot of bugs */ |
106 | mysql_mutex_unlock(&control->LOCK_control); |
107 | my_sleep(100000); /* a tenth of a second */ |
108 | mysql_mutex_lock(&control->LOCK_control); |
109 | #else |
110 | /* To have a killable sleep, we use timedwait like our SQL GET_LOCK() */ |
111 | DBUG_PRINT("info" , ("sleeping %llu nano seconds" , sleep_time)); |
112 | if (sleep_time) |
113 | { |
114 | set_timespec_nsec(abstime, sleep_time); |
115 | mysql_cond_timedwait(control->COND_control, |
116 | control->LOCK_control, &abstime); |
117 | } |
118 | #endif |
119 | if (control->killed) |
120 | res= TRUE; |
121 | mysql_mutex_unlock(control->LOCK_control); |
122 | DBUG_RETURN(res); |
123 | } |
124 | |