1 /*
2 Copyright (c) 2006, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #ifndef NDBD_MALLOC_IMPL_H
26 #define NDBD_MALLOC_IMPL_H
27
28 #include <kernel_types.h>
29 #include <Bitmask.hpp>
30 #include <assert.h>
31 #include "Pool.hpp"
32 #include <Vector.hpp>
33
34 #define JAM_FILE_ID 291
35
36
37 /**
38 * 13 -> 8192 words -> 32768 bytes
39 * 18 -> 262144 words -> 1M
40 */
41 #define BMW_2LOG 13
42 #define BITMAP_WORDS (1 << BMW_2LOG)
43
44 #define BPP_2LOG (BMW_2LOG + 5)
45 #define SPACE_PER_BMP_2LOG ((2 + BMW_2LOG) + BPP_2LOG)
46
47 //#define BITMAP_WORDS GLOBAL_PAGE_SIZE_WORDS
48
49 struct Alloc_page
50 {
51 Uint32 m_data[BITMAP_WORDS];
52 };
53
54 struct InitChunk
55 {
56 Uint32 m_cnt;
57 Uint32 m_start;
58 Alloc_page* m_ptr;
59 };
60
61 struct Free_page_data
62 {
63 Uint32 m_list;
64 Uint32 m_next;
65 Uint32 m_prev;
66 Uint32 m_size;
67 };
68
69 #define FPD_2LOG 2
70
71 class Ndbd_mem_manager
72 {
73 public:
74 Ndbd_mem_manager();
75
76 void set_resource_limit(const Resource_limit& rl);
77 bool get_resource_limit(Uint32 id, Resource_limit& rl) const;
78 bool get_resource_limit_nolock(Uint32 id, Resource_limit& rl) const;
79
80 bool init(Uint32 *watchCounter, bool allow_alloc_less_than_requested = true);
81 void map(Uint32 * watchCounter, bool memlock = false, Uint32 resources[] = 0);
82 void* get_memroot() const;
83
84 void dump() const ;
85
86 enum AllocZone
87 {
88 NDB_ZONE_LO = 0, // Only allocate with page_id < (1 << 13)
89 NDB_ZONE_ANY = 1 // Allocate with any page_id
90 };
91
92 void* alloc_page(Uint32 type, Uint32* i, enum AllocZone);
93 void release_page(Uint32 type, Uint32 i);
94
95 void alloc_pages(Uint32 type, Uint32* i, Uint32 *cnt, Uint32 min = 1);
96 void release_pages(Uint32 type, Uint32 i, Uint32 cnt);
97
98 /**
99 * Compute 2log of size
100 * @note size = 0 -> 0
101 * @note size > 65536 -> 16
102 */
103 static Uint32 ndb_log2(Uint32 size);
104
105 private:
106 void grow(Uint32 start, Uint32 cnt);
107
108 #define XX_RL_COUNT 10
109 /**
110 * Return pointer to free page data on page
111 */
112 static Free_page_data* get_free_page_data(Alloc_page*, Uint32 idx);
113 Vector<Uint32> m_used_bitmap_pages;
114
115 Uint32 m_buddy_lists[2][16];
116 Resource_limit m_resource_limit[XX_RL_COUNT]; // RG_COUNT in record_types.hpp
117 Alloc_page * m_base_page;
118
119 void release_impl(Uint32 zone, Uint32 start, Uint32 cnt);
120 void insert_free_list(Uint32 zone, Uint32 start, Uint32 cnt);
121 Uint32 remove_free_list(Uint32 zone, Uint32 start, Uint32 list);
122
123 void set(Uint32 first, Uint32 last);
124 void clear(Uint32 first, Uint32 last);
125 void clear_and_set(Uint32 first, Uint32 last);
126 Uint32 check(Uint32 first, Uint32 last);
127
128 void alloc(AllocZone, Uint32* ret, Uint32 *pages, Uint32 min_requested);
129 void alloc_impl(Uint32 zone, Uint32* ret, Uint32 *pages, Uint32 min);
130 void release(Uint32 start, Uint32 cnt);
131
132 /**
133 * This is memory that has been allocated
134 * but not yet mapped (i.e it is not possible to get it using alloc_page(s)
135 */
136 Vector<InitChunk> m_unmapped_chunks;
137 };
138
139 inline
140 Free_page_data*
get_free_page_data(Alloc_page * ptr,Uint32 idx)141 Ndbd_mem_manager::get_free_page_data(Alloc_page* ptr, Uint32 idx)
142 {
143 assert(idx & ((1 << BPP_2LOG) - 1));
144 assert((idx & ((1 << BPP_2LOG) - 1)) != ((1 << BPP_2LOG) - 1));
145
146 return (Free_page_data*)
147 (ptr->m_data + ((idx & ((BITMAP_WORDS >> FPD_2LOG) - 1)) << FPD_2LOG));
148 }
149
150 inline
151 void
set(Uint32 first,Uint32 last)152 Ndbd_mem_manager::set(Uint32 first, Uint32 last)
153 {
154 Alloc_page * ptr = m_base_page;
155 #if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
156 Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
157 assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
158 assert(bmp < m_resource_limit[0].m_resource_id);
159
160 first -= bmp;
161 last -= bmp;
162 ptr += bmp;
163 #endif
164 BitmaskImpl::set(BITMAP_WORDS, ptr->m_data, first);
165 BitmaskImpl::set(BITMAP_WORDS, ptr->m_data, last);
166 }
167
168 inline
169 void
clear(Uint32 first,Uint32 last)170 Ndbd_mem_manager::clear(Uint32 first, Uint32 last)
171 {
172 Alloc_page * ptr = m_base_page;
173 #if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
174 Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
175 assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
176 assert(bmp < m_resource_limit[0].m_resource_id);
177
178 first -= bmp;
179 last -= bmp;
180 ptr += bmp;
181 #endif
182 BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, first);
183 BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, last);
184 }
185
186 inline
187 void
clear_and_set(Uint32 first,Uint32 last)188 Ndbd_mem_manager::clear_and_set(Uint32 first, Uint32 last)
189 {
190 Alloc_page * ptr = m_base_page;
191 #if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
192 Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
193 assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
194 assert(bmp < m_resource_limit[0].m_resource_id);
195
196 first -= bmp;
197 last -= bmp;
198 ptr += bmp;
199 #endif
200 BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, first);
201 BitmaskImpl::clear(BITMAP_WORDS, ptr->m_data, last);
202 BitmaskImpl::set(BITMAP_WORDS, ptr->m_data, last+1);
203 }
204
205 inline
206 Uint32
check(Uint32 first,Uint32 last)207 Ndbd_mem_manager::check(Uint32 first, Uint32 last)
208 {
209 Uint32 ret = 0;
210 Alloc_page * ptr = m_base_page;
211 #if ((SPACE_PER_BMP_2LOG < 32) && (SIZEOF_CHARP == 4)) || (SIZEOF_CHARP == 8)
212 Uint32 bmp = first & ~((1 << BPP_2LOG) - 1);
213 assert((first >> BPP_2LOG) == (last >> BPP_2LOG));
214 assert(bmp < m_resource_limit[0].m_resource_id);
215
216 first -= bmp;
217 last -= bmp;
218 ptr += bmp;
219 #endif
220 ret |= BitmaskImpl::get(BITMAP_WORDS, ptr->m_data, first) << 0;
221 ret |= BitmaskImpl::get(BITMAP_WORDS, ptr->m_data, last) << 1;
222 return ret;
223 }
224
225
226
227 #undef JAM_FILE_ID
228
229 #endif
230