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