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