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