MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbdSuperPool.cpp
1 /*
2  Copyright (C) 2006, 2008 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include <ndb_global.h>
20 #include "SuperPool.hpp"
21 #include "ndbd_malloc_impl.hpp"
22 #include "NdbdSuperPool.hpp"
23 
24 #define PSI (1 << (BMW_2LOG + 2))
25 
26 struct AllocArea
27 {
28  AllocArea(AllocArea* next);
29 
30  Uint16 m_currPage; // 2
31  Uint16 m_numPages; // number of pages // 2
32  SuperPool::PtrI m_firstPageI; // 4
33  void* m_memory; // page-aligned pages // 4/8
34  struct AllocArea* m_nextArea; // 4/8
35  // tot 16/24
36 };
37 
38 AllocArea::AllocArea(AllocArea* next)
39 {
40  m_nextArea = next;
41  m_firstPageI = RNIL;
42  m_currPage = m_numPages = 0;
43  m_memory = 0;
44 }
45 
46 NdbdSuperPool::NdbdSuperPool(class Ndbd_mem_manager & mm,
47  Uint32 pageSize, Uint32 pageBits) :
48  SuperPool(pageSize, pageBits),
49  m_mm(mm),
50  m_currArea(0), m_firstArea(0)
51 {
52  m_memRoot = m_mm.get_memroot();
53 
54  m_shift = Ndbd_mem_manager::ndb_log2((1 << (BMW_2LOG + 2)) / pageSize) - 1;
55  m_add = (1 << m_shift) - 1;
56 }
57 
58 NdbdSuperPool::~NdbdSuperPool()
59 {
60  Uint32 cnt = PSI / sizeof(AllocArea);
61  AllocArea* ap = m_firstArea;
62  while(ap != 0)
63  {
64  AllocArea * first = ap;
65  for(Uint32 i = 0; i<cnt; i++)
66  {
67  if (ap->m_numPages)
68  {
69  m_mm.release(ap->m_memory, ap->m_numPages >> m_shift);
70  }
71  ap = ap->m_nextArea;
72  }
73  m_mm.release((void*)first, 1);
74  }
75 }
76 
77 bool
78 NdbdSuperPool::init_1()
79 {
80  Uint32 pageCount = (1 << m_pageBits);
81  if (m_pageEnt == 0) {
82  // allocate page entry array
83  Uint32 bytes = pageCount * sizeof(PageEnt);
84  m_pageEnt = static_cast<PageEnt*>(malloc(bytes));
85  if (m_pageEnt == 0)
86  return false;
87  for (Uint32 i = 0; i < pageCount; i++)
88  new (&m_pageEnt[i]) PageEnt();
89  }
90  if (m_pageType == 0) {
91  // allocate type check array
92  Uint32 bytes = pageCount;
93  m_pageType = static_cast<Uint8*>(malloc(bytes));
94  if (m_pageType == 0)
95  return false;
96  memset(m_pageType, 0, bytes);
97  }
98 
99  return true;
100 }
101 
102 static
103 void
104 initAllocAreaPage(AllocArea * p1)
105 {
106  AllocArea * ap = p1;
107  Uint32 cnt = PSI / sizeof(AllocArea);
108  for(Uint32 i = 0; i<cnt; i++, ap++)
109  {
110  new (ap) AllocArea(ap + 1);
111  }
112 
113  (p1 + cnt - 1)->m_nextArea = 0;
114 }
115 
116 bool
117 NdbdSuperPool::init_2()
118 {
119  m_memRoot = m_mm.get_memroot();
120 
121  Uint32 cnt = 1;
122  AllocArea* p1 = (AllocArea*)m_mm.alloc(&cnt, 1);
123  if (p1 == 0)
124  return false;
125 
126  initAllocAreaPage(p1);
127  m_currArea = p1;
128  m_firstArea = p1;
129  return true;
130 }
131 
132 SuperPool::PtrI
133 NdbdSuperPool::getNewPage()
134 {
135  AllocArea* ap = m_currArea;
136  Uint32 curr = ap->m_currPage;
137  Uint32 cnt = ap->m_numPages;
138  if (curr == cnt)
139  {
140  // area is used up
141  if (! (ap = allocMem()))
142  {
143  abort();
144  return RNIL;
145  }
146  curr = ap->m_currPage;
147  cnt = ap->m_numPages;
148  }
149 
150  assert(curr < cnt);
151  PtrI pageI = ap->m_firstPageI;
152  Uint32 recBits = m_recBits;
153  Int32 ip = ((Int32)pageI >> recBits) + curr;
154  pageI = ip << recBits;
155  ap->m_currPage = curr + 1;
156  return pageI;
157 }
158 
159 Uint32
160 NdbdSuperPool::allocAreaMemory(AllocArea* ap, Uint32 tryPages)
161 {
162  Uint32 cnt = (tryPages + m_add) >> m_shift;
163  void* p1 = m_mm.alloc(&cnt, 1);
164  if (p1 == 0)
165  {
166  abort();
167  return 0;
168  }
169  Uint32 pageI = getPageI(p1);
170  ap->m_firstPageI = pageI;
171  ap->m_currPage = 0;
172  ap->m_memory = p1;
173  ap->m_numPages = cnt << m_shift;
174  return cnt;
175 }
176 
177 AllocArea*
178 NdbdSuperPool::allocArea()
179 {
180  AllocArea * curr = m_currArea;
181  AllocArea * next = curr->m_nextArea;
182  if (next == 0)
183  {
184  Uint32 cnt = 1;
185  AllocArea* p1 = (AllocArea*)m_mm.alloc(&cnt, 1);
186  if (p1 == 0)
187  return 0;
188 
189  initAllocAreaPage(p1);
190 
191  m_currArea->m_nextArea = p1;
192  return m_currArea = p1;
193  }
194  else
195  {
196  m_currArea = m_currArea->m_nextArea;
197  return m_currArea;
198  }
199 }
200 
201 AllocArea*
202 NdbdSuperPool::allocMem()
203 {
204  // compute number of additional pages needed
205  if (m_totPages >= m_maxPages)
206  {
207  abort();
208  return 0;
209  }
210  Uint32 needPages = (m_totPages == 0 ? m_initPages : m_incrPages);
211 
212  // add new area
213  AllocArea* ap = allocArea();
214  if (ap == 0)
215  {
216  abort();
217  return 0;
218  }
219 
220  Uint32 numPages;
221  if (!(numPages = allocAreaMemory(ap, needPages)))
222  {
223  abort();
224  return 0;
225  }
226 
227  // update counts
228  m_totPages += numPages;
229  return ap;
230 }