| 1 | /* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. |
| 2 | |
| 3 | This program is free software; you can redistribute it and/or modify |
| 4 | it under the terms of the GNU General Public License as published by |
| 5 | the Free Software Foundation; version 2 of the License. |
| 6 | |
| 7 | This program is distributed in the hope that it will be useful, |
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 | GNU General Public License for more details. |
| 11 | |
| 12 | You should have received a copy of the GNU General Public License |
| 13 | along with this program; if not, write to the Free Software |
| 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
| 15 | |
| 16 | #ifndef _waiting_threads_h |
| 17 | #define _waiting_threads_h |
| 18 | |
| 19 | #include <my_sys.h> |
| 20 | |
| 21 | #include <lf.h> |
| 22 | |
| 23 | C_MODE_START |
| 24 | |
| 25 | typedef struct st_wt_resource_id WT_RESOURCE_ID; |
| 26 | typedef struct st_wt_resource WT_RESOURCE; |
| 27 | |
| 28 | typedef struct st_wt_resource_type { |
| 29 | my_bool (*compare)(const void *a, const void *b); |
| 30 | const void *(*make_key)(const WT_RESOURCE_ID *id, uint *len); /* not used */ |
| 31 | } WT_RESOURCE_TYPE; |
| 32 | |
| 33 | struct st_wt_resource_id { |
| 34 | ulonglong value; |
| 35 | const WT_RESOURCE_TYPE *type; |
| 36 | }; |
| 37 | /* the below differs from sizeof(WT_RESOURCE_ID) by the amount of padding */ |
| 38 | #define sizeof_WT_RESOURCE_ID (sizeof(ulonglong)+sizeof(void*)) |
| 39 | |
| 40 | #define WT_WAIT_STATS 24 |
| 41 | #define WT_CYCLE_STATS 32 |
| 42 | extern ulonglong wt_wait_table[WT_WAIT_STATS]; |
| 43 | extern uint32 wt_wait_stats[WT_WAIT_STATS+1]; |
| 44 | extern uint32 wt_cycle_stats[2][WT_CYCLE_STATS+1]; |
| 45 | extern uint32 wt_success_stats; |
| 46 | |
| 47 | typedef struct st_wt_thd { |
| 48 | /* |
| 49 | XXX |
| 50 | there's no protection (mutex) against concurrent access of the |
| 51 | dynarray below. it is assumed that a caller will have it anyway |
| 52 | (not to protect this array but to protect its own - caller's - |
| 53 | data structures), and we'll get it for free. A caller needs to |
| 54 | ensure that a blocker won't release a resource before a blocked |
| 55 | thread starts waiting, which is usually done with a mutex. |
| 56 | |
| 57 | If the above assumption is wrong, we'll need to add a mutex here. |
| 58 | */ |
| 59 | DYNAMIC_ARRAY my_resources; |
| 60 | /* |
| 61 | 'waiting_for' is modified under waiting_for->lock, and only by thd itself |
| 62 | 'waiting_for' is read lock-free (using pinning protocol), but a thd object |
| 63 | can read its own 'waiting_for' without any locks or tricks. |
| 64 | */ |
| 65 | WT_RESOURCE *waiting_for; |
| 66 | LF_PINS *pins; |
| 67 | |
| 68 | /* pointers to values */ |
| 69 | const ulong *timeout_short; |
| 70 | const ulong *deadlock_search_depth_short; |
| 71 | const ulong *timeout_long; |
| 72 | const ulong *deadlock_search_depth_long; |
| 73 | |
| 74 | /* |
| 75 | weight relates to the desirability of a transaction being killed if it's |
| 76 | part of a deadlock. In a deadlock situation transactions with lower weights |
| 77 | are killed first. |
| 78 | |
| 79 | Examples of using the weight to implement different selection strategies: |
| 80 | |
| 81 | 1. Latest |
| 82 | Keep all weights equal. |
| 83 | 2. Random |
| 84 | Assight weights at random. |
| 85 | (variant: modify a weight randomly before every lock request) |
| 86 | 3. Youngest |
| 87 | Set weight to -NOW() |
| 88 | 4. Minimum locks |
| 89 | count locks granted in your lock manager, store the value as a weight |
| 90 | 5. Minimum work |
| 91 | depends on the definition of "work". For example, store the number |
| 92 | of rows modifies in this transaction (or a length of REDO log for a |
| 93 | transaction) as a weight. |
| 94 | |
| 95 | It is only statistically relevant and is not protected by any locks. |
| 96 | */ |
| 97 | ulong volatile weight; |
| 98 | /* |
| 99 | 'killed' is indirectly protected by waiting_for->lock because |
| 100 | a killed thread needs to clear its 'waiting_for' and thus needs a lock. |
| 101 | That is a thread needs an exclusive lock to read 'killed' reliably. |
| 102 | But other threads may change 'killed' from 0 to 1, a shared |
| 103 | lock is enough for that. |
| 104 | */ |
| 105 | my_bool killed; |
| 106 | #ifndef DBUG_OFF |
| 107 | const char *name; |
| 108 | #endif |
| 109 | } WT_THD; |
| 110 | |
| 111 | #define WT_TIMEOUT ETIMEDOUT |
| 112 | #define WT_OK 0 |
| 113 | #define WT_DEADLOCK -1 |
| 114 | #define WT_DEPTH_EXCEEDED -2 |
| 115 | #define WT_FREE_TO_GO -3 |
| 116 | |
| 117 | void wt_init(void); |
| 118 | void wt_end(void); |
| 119 | void wt_thd_lazy_init(WT_THD *, const ulong *, const ulong *, const ulong *, const ulong *); |
| 120 | void wt_thd_destroy(WT_THD *); |
| 121 | int wt_thd_will_wait_for(WT_THD *, WT_THD *, const WT_RESOURCE_ID *); |
| 122 | int wt_thd_cond_timedwait(WT_THD *, mysql_mutex_t *); |
| 123 | void wt_thd_release(WT_THD *, const WT_RESOURCE_ID *); |
| 124 | #define wt_thd_release_all(THD) wt_thd_release((THD), 0) |
| 125 | my_bool wt_resource_id_memcmp(const void *, const void *); |
| 126 | |
| 127 | C_MODE_END |
| 128 | |
| 129 | #endif |
| 130 | |