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