1 | /* Copyright (c) 2008, 2015, 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 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 Foundation, |
14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ |
15 | |
16 | #ifndef PFS_GLOBAL_H |
17 | #define PFS_GLOBAL_H |
18 | |
19 | #include "my_compiler.h" |
20 | |
21 | /** |
22 | @file storage/perfschema/pfs_global.h |
23 | Miscellaneous global dependencies (declarations). |
24 | */ |
25 | |
26 | /** True when the performance schema is initialized. */ |
27 | extern bool pfs_initialized; |
28 | |
29 | /** Total memory allocated by the performance schema, in bytes. */ |
30 | extern size_t pfs_allocated_memory; |
31 | |
32 | #if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) || defined(HAVE_ALIGNED_MALLOC) |
33 | #define PFS_ALIGNEMENT CPU_LEVEL1_DCACHE_LINESIZE |
34 | #define PFS_ALIGNED MY_ALIGNED(PFS_ALIGNEMENT) |
35 | #else |
36 | /* |
37 | Known platforms that do not provide aligned memory: |
38 | - MacOSX Darwin (osx10.5) |
39 | For these platforms, compile without the alignment optimization. |
40 | */ |
41 | #define PFS_ALIGNED |
42 | #endif /* HAVE_POSIX_MEMALIGN || HAVE_MEMALIGN || HAVE_ALIGNED_MALLOC */ |
43 | |
44 | void *pfs_malloc(size_t size, myf flags); |
45 | |
46 | /** Allocate an array of structures with overflow check. */ |
47 | void *pfs_malloc_array(size_t n, size_t size, myf flags); |
48 | |
49 | /** |
50 | Helper, to allocate an array of structures. |
51 | @param n number of elements in the array |
52 | @param s size of array element |
53 | @param T type of an element |
54 | @param f flags to use when allocating memory |
55 | */ |
56 | #define PFS_MALLOC_ARRAY(n, s, T, f) \ |
57 | reinterpret_cast<T*>(pfs_malloc_array((n), (s), (f))) |
58 | |
59 | /** Free memory allocated with @sa pfs_malloc. */ |
60 | void pfs_free(void *ptr); |
61 | |
62 | /** Detect multiplication overflow. */ |
63 | bool is_overflow(size_t product, size_t n1, size_t n2); |
64 | |
65 | uint pfs_get_socket_address(char *host, |
66 | uint host_len, |
67 | uint *port, |
68 | const struct sockaddr_storage *src_addr, |
69 | socklen_t src_len); |
70 | |
71 | /** |
72 | Compute a random index value in an interval. |
73 | @param ptr seed address |
74 | @param max_size maximun size of the interval |
75 | @return a random value in [0, max_size-1] |
76 | */ |
77 | inline uint randomized_index(const void *ptr, uint max_size) |
78 | { |
79 | static uint seed1= 0; |
80 | static uint seed2= 0; |
81 | uint result; |
82 | intptr value; |
83 | |
84 | if (unlikely(max_size == 0)) |
85 | return 0; |
86 | |
87 | /* |
88 | ptr is typically an aligned structure, and can be in an array. |
89 | - The last bits are not random because of alignment, |
90 | so we divide by 8. |
91 | - The high bits are mostly constant, especially with 64 bits architectures, |
92 | but we keep most of them anyway, by doing computation in intptr. |
93 | The high bits are significant depending on where the data is |
94 | stored (the data segment, the stack, the heap, ...). |
95 | - To spread consecutive cells in an array further, we multiply by |
96 | a factor A. This factor should not be too high, which would cause |
97 | an overflow and cause loss of randomness (droping the top high bits). |
98 | The factor is a prime number, to help spread the distribution. |
99 | - To add more noise, and to be more robust if the calling code is |
100 | passing a constant value instead of a random identity, |
101 | we add the previous results, for hysteresys, with a degree 2 polynom, |
102 | X^2 + X + 1. |
103 | - Last, a modulo is applied to be within the [0, max_size - 1] range. |
104 | Note that seed1 and seed2 are static, and are *not* thread safe, |
105 | which is even better. |
106 | Effect with arrays: T array[N] |
107 | - ptr(i) = & array[i] = & array[0] + i * sizeof(T) |
108 | - ptr(i+1) = ptr(i) + sizeof(T). |
109 | What we want here, is to have index(i) and index(i+1) fall into |
110 | very different areas in [0, max_size - 1], to avoid locality. |
111 | */ |
112 | value= (reinterpret_cast<intptr> (ptr)) >> 3; |
113 | value*= 1789; |
114 | value+= seed2 + seed1 + 1; |
115 | |
116 | result= (static_cast<uint> (value)) % max_size; |
117 | |
118 | seed2= seed1*seed1; |
119 | seed1= result; |
120 | |
121 | DBUG_ASSERT(result < max_size); |
122 | return result; |
123 | } |
124 | |
125 | void pfs_print_error(const char *format, ...); |
126 | |
127 | /** |
128 | Given an array defined as T ARRAY[MAX], |
129 | check that an UNSAFE pointer actually points to an element |
130 | within the array. |
131 | */ |
132 | #define SANITIZE_ARRAY_BODY(T, ARRAY, MAX, UNSAFE) \ |
133 | intptr offset; \ |
134 | if ((&ARRAY[0] <= UNSAFE) && \ |
135 | (UNSAFE < &ARRAY[MAX])) \ |
136 | { \ |
137 | offset= ((intptr) UNSAFE - (intptr) ARRAY) % sizeof(T); \ |
138 | if (offset == 0) \ |
139 | return UNSAFE; \ |
140 | } \ |
141 | return NULL |
142 | |
143 | #endif |
144 | |
145 | |