19 #include <ndb_global.h>
20 #include "SuperPool.hpp"
22 #define SP_ALIGN(sz, al) (((sz) + (al) - 1) & ~((al) - 1))
25 #define NNIL 0xffffffff
29 SuperPool::SuperPool(Uint32 pageSize, Uint32 pageBits) :
32 m_recBits(32 - m_pageBits),
33 m_recMask((1 << m_recBits) - 1),
47 assert(m_pageSize != 0 && (m_pageSize & (m_pageSize - 1)) == 0);
48 assert(m_pageBits <= 30);
51 SuperPool::~SuperPool()
55 SuperPool::PageEnt::PageEnt() :
66 SuperPool::PageList::PageList() :
73 SuperPool::PageList::PageList(PtrI pageI) :
78 assert(pageI != RNIL);
82 SuperPool::movePages(PageList& pl1, PageList& pl2)
84 PtrI pageI1 = pl1.m_tailPageI;
85 PtrI pageI2 = pl2.m_headPageI;
86 if (pl1.m_pageCount != 0) {
87 assert(pageI1 != RNIL);
88 if (pl2.m_pageCount != 0) {
89 assert(pageI2 != RNIL);
90 PageEnt& pe1 = getPageEnt(pageI1);
91 PageEnt& pe2 = getPageEnt(pageI2);
92 pe1.m_nextPageI = pageI2;
93 pe2.m_prevPageI = pageI1;
94 pl1.m_tailPageI = pl2.m_tailPageI;
95 pl1.m_pageCount += pl2.m_pageCount;
97 assert(pageI2 == RNIL);
100 assert(pageI1 == RNIL);
103 pl2.m_headPageI = pl2.m_tailPageI = RNIL;
108 SuperPool::addHeadPage(PageList& pl, PtrI pageI)
110 assert(pageI != RNIL);
111 PageEnt& pe = getPageEnt(pageI);
112 assert(pe.m_nextPageI == RNIL & pe.m_prevPageI == RNIL);
119 SuperPool::addTailPage(PageList& pl, PtrI pageI)
121 assert(pageI != RNIL);
122 PageEnt& pe = getPageEnt(pageI);
123 assert(pe.m_nextPageI == RNIL & pe.m_prevPageI == RNIL);
129 SuperPool::removePage(PageList& pl, PtrI pageI)
131 assert(pageI != RNIL);
132 PageEnt& pe = getPageEnt(pageI);
133 if (pe.m_nextPageI != RNIL) {
134 assert(pl.m_tailPageI != pageI);
135 PageEnt& nextPe = getPageEnt(pe.m_nextPageI);
136 nextPe.m_prevPageI = pe.m_prevPageI;
138 assert(pl.m_tailPageI == pageI);
139 pl.m_tailPageI = pe.m_prevPageI;
141 if (pe.m_prevPageI != RNIL) {
142 assert(pl.m_headPageI != pageI);
143 PageEnt& prevPe = getPageEnt(pe.m_prevPageI);
144 prevPe.m_nextPageI = pe.m_nextPageI;
146 assert(pl.m_headPageI == pageI);
147 pl.m_headPageI = pe.m_nextPageI;
149 pe.m_nextPageI = RNIL;
150 pe.m_prevPageI = RNIL;
151 assert(pl.m_pageCount != 0);
158 SuperPool::getPageI(
void* pageP)
160 Uint32 pageSize = m_pageSize;
161 Uint32 pageBits = m_pageBits;
162 Uint32 recBits = m_recBits;
163 void* memRoot = m_memRoot;
164 my_ptrdiff_t ipL = (Uint8*)pageP - (Uint8*)memRoot;
165 assert(ipL % pageSize == 0);
166 ipL /= (Int32)pageSize;
167 Int32 ip = (Int32)ipL;
168 Int32 lim = 1 << (pageBits - 1);
169 if (! (ip == ipL && -lim <= ip && ip < lim && ip != -1)) {
173 PtrI pageI = ip << recBits;
174 assert(pageP == getPageP(pageI));
180 SuperPool::RecInfo::RecInfo(
GroupPool& gp, Uint32 recSize) :
192 m_recType = (sp.m_typeCount++ << 1) | 1;
193 assert(m_recSize == SP_ALIGN(m_recSize,
sizeof(Uint32)));
195 Uint32 n1 = sp.m_pageSize / m_recSize;
196 Uint32 b2 = (sp.m_recBits < 16 ? sp.m_recBits : 16);
197 Uint32 n2 = (1 << b2) - 1;
198 m_maxPerPage = (n1 < n2 ? n1 : n2);
199 assert(m_maxPerPage != 0);
204 SuperPool::getFreeCount(RecInfo& ri, PtrI recI)
207 Uint32 recMask = m_recMask;
208 Uint32 loopRecI = recI;
209 while ((loopRecI & recMask) != recMask) {
211 void* loopRecP = getRecP(loopRecI, ri);
212 loopRecI = *(Uint32*)loopRecP;
214 assert(n == (Uint16)n);
219 SuperPool::getRecPageCount(RecInfo& ri)
222 for (Uint32 k = 0; k <= 2; k++)
223 n += ri.m_pageList[k].m_pageCount;
224 if (ri.m_freeRecI != NNIL)
230 SuperPool::getRecTotCount(RecInfo& ri)
232 return ri.m_maxPerPage * getRecPageCount(ri);
236 SuperPool::getRecUseCount(RecInfo& ri)
238 Uint32 n = ri.m_useCount;
240 if (ri.m_freeRecI != NNIL) {
241 Uint32 maxPerPage = ri.m_maxPerPage;
242 Uint32 freeCount = getFreeCount(ri, ri.m_freeRecI);
243 assert(maxPerPage >= freeCount);
244 n += maxPerPage - freeCount;
252 SuperPool::getRecPageList(RecInfo& ri, PageEnt& pe)
254 if (pe.m_useCount == 0)
256 if (pe.m_useCount < ri.m_maxPerPage)
258 if (pe.m_useCount == ri.m_maxPerPage)
265 SuperPool::addCurrPage(RecInfo& ri, PtrI pageI)
267 PageEnt& pe = getPageEnt(pageI);
268 ri.m_freeRecI = pe.m_freeRecI;
270 Uint32 k = getRecPageList(ri, pe);
272 removePage(ri.m_pageList[k], pageI);
273 assert(ri.m_useCount >= pe.m_useCount);
274 ri.m_useCount -= pe.m_useCount;
278 SuperPool::removeCurrPage(RecInfo& ri)
280 Uint32 recMask = m_recMask;
281 PtrI pageI = ri.m_freeRecI & ~ m_recMask;
283 PageEnt& pe = getPageEnt(pageI);
284 pe.m_freeRecI = ri.m_freeRecI;
285 Uint32 maxPerPage = ri.m_maxPerPage;
286 Uint32 freeCount = getFreeCount(ri, pe.m_freeRecI);
287 assert(maxPerPage >= freeCount);
288 pe.m_useCount = maxPerPage - freeCount;
290 Uint32 k = getRecPageList(ri, pe);
291 addHeadPage(ri.m_pageList[k], pageI);
292 ri.m_useCount += pe.m_useCount;
293 ri.m_freeRecI = NNIL;
302 SuperPool::getAvailPage(RecInfo& ri)
305 if ((pageI = ri.m_pageList[1].m_headPageI) != RNIL ||
306 (pageI = ri.m_pageList[0].m_headPageI) != RNIL ||
307 (pageI = getFreePage(ri)) != RNIL) {
309 if (ri.m_freeRecI != NNIL)
311 addCurrPage(ri, pageI);
318 SuperPool::getFreePage(RecInfo& ri)
322 if ((pageI = getFreePage(gp)) != RNIL) {
323 initFreePage(ri, pageI);
324 addHeadPage(ri.m_pageList[0], pageI);
334 if ((pageI = gp.m_freeList.m_headPageI) != RNIL) {
335 removePage(gp.m_freeList, pageI);
338 if (gp.m_totPages < getMaxPages(gp) &&
339 (pageI = getFreePage()) != RNIL) {
347 SuperPool::getFreePage()
350 if ((pageI = m_freeList.m_headPageI) != RNIL) {
351 removePage(m_freeList, pageI);
354 if ((pageI = getNewPage()) != RNIL) {
361 SuperPool::initFreePage(RecInfo& ri, PtrI pageI)
363 void* pageP = getPageP(pageI);
365 Uint32 num = ri.m_maxPerPage;
366 Uint32 recSize = ri.m_recSize;
367 void* recP = (Uint8*)pageP;
369 while (irNext < num) {
370 *(Uint32*)recP = pageI | irNext;
371 recP = (Uint8*)recP + recSize;
375 *(Uint32*)recP = pageI | m_recMask;
377 PageEnt& pe = getPageEnt(pageI);
379 pe.m_pageType = ri.m_recType;
380 pe.m_freeRecI = pageI | 0;
383 Uint32 ip = pageI >> m_recBits;
384 m_pageType[ip] = (ri.m_recType & 0xFF);
390 SuperPool::releaseNotCurrent(RecInfo& ri, PtrI recI)
392 PageEnt& pe = getPageEnt(recI);
393 void* recP = getRecP(recI, ri);
394 *(Uint32*)recP = pe.m_freeRecI;
395 pe.m_freeRecI = recI;
396 PtrI pageI = recI & ~ m_recMask;
397 Uint32 maxPerPage = ri.m_maxPerPage;
399 Uint32 k1 = getRecPageList(ri, pe);
400 assert(pe.m_useCount != 0);
402 Uint32 k2 = getRecPageList(ri, pe);
404 removePage(ri.m_pageList[k1], pageI);
405 addHeadPage(ri.m_pageList[k2], pageI);
410 assert(ri.m_useCount != 0);
415 SuperPool::freeRecPages(RecInfo& ri)
418 Uint32 useCount = ri.m_useCount;
420 for (uint32 k = 0; k <= 2; k++)
421 totCount += ri.m_pageList[k].m_pageCount;
422 totCount *= ri.m_maxPerPage;
423 assert(totCount >= useCount);
424 if ((totCount - useCount) * ri.m_hyY < useCount * ri.m_hyX)
428 Uint32 minPages = getMinPages(gp);
429 PageList& pl = ri.m_pageList[0];
430 while (pl.m_pageCount != 0) {
431 PtrI pageI = pl.m_headPageI;
432 removePage(pl, pageI);
433 PageEnt& pe = getPageEnt(pageI);
435 pe.m_freeRecI = NNIL;
436 Uint32 ip = pageI >> m_recBits;
438 if (gp.m_totPages <= minPages) {
439 addHeadPage(gp.m_freeList, pageI);
442 addHeadPage(m_freeList, pageI);
443 assert(gp.m_totPages != 0);
450 SuperPool::freeAllRecPages(RecInfo& ri,
bool force)
453 if (ri.m_freeRecI != NNIL)
455 assert(force || ri.m_useCount == 0);
456 for (Uint32 k = 0; k <= 2; k++)
457 movePages(gp.m_freeList, ri.m_pageList[k]);
463 SuperPool::setInitPages(Uint32 initPages)
465 m_initPages = initPages;
469 SuperPool::setIncrPages(Uint32 incrPages)
471 m_incrPages = incrPages;
475 SuperPool::setMaxPages(Uint32 maxPages)
477 m_maxPages = maxPages;
481 SuperPool::getGpMinPages()
483 Uint32 minPages = (m_groupMinPct * m_totPages) / 100;
484 if (minPages < m_groupMinPages)
485 minPages = m_groupMinPages;
492 Uint32 minPages = (gp.m_minPct * m_totPages) / 100;
493 if (minPages < gp.m_minPages)
494 minPages = gp.m_minPages;
501 Uint32 n1 = getGpMinPages();
502 Uint32 n2 = getMinPages(gp);
507 Uint32 n4 = (m_totPages >= n3 ? m_totPages - n3 : 0);
514 SuperPool::verify(RecInfo& ri)
517 verifyPageList(m_freeList);
518 verifyPageList(gp.m_freeList);
519 for (Uint32 k = 0; k <= 2; k++) {
520 PageList& pl = ri.m_pageList[k];
522 PtrI pageI = pl.m_headPageI;
523 while (pageI != RNIL) {
524 PageEnt& pe = getPageEnt(pageI);
525 assert(pe.m_pageType == ri.m_recType);
526 Uint32 maxPerPage = ri.m_maxPerPage;
527 Uint32 freeCount = getFreeCount(ri, pe.m_freeRecI);
528 assert(maxPerPage >= freeCount);
529 Uint32 useCount = maxPerPage - freeCount;
530 assert(pe.m_useCount == useCount);
531 assert(k != 0 || useCount == 0);
532 assert(k != 1 || (useCount != 0 && freeCount != 0));
533 assert(k != 2 || freeCount == 0);
534 pageI = pe.m_nextPageI;
540 SuperPool::verifyPageList(PageList& pl)
543 PtrI pageI = pl.m_headPageI;
544 while (pageI != RNIL) {
545 PageEnt& pe = getPageEnt(pageI);
546 if (pe.m_prevPageI == RNIL) {
549 PageEnt& prevPe = getPageEnt(pe.m_prevPageI);
550 assert(prevPe.m_nextPageI == pageI);
552 if (pe.m_nextPageI == RNIL) {
553 assert(pl.m_tailPageI == pageI);
555 PageEnt& nextPe = getPageEnt(pe.m_nextPageI);
556 assert(nextPe.m_prevPageI == pageI);
558 if (pe.m_pageType != 0) {
559 assert(pe.m_freeRecI != NNIL);
560 PageEnt& pe2 = getPageEnt(pe.m_freeRecI);
563 assert(pe.m_freeRecI == NNIL);
565 pageI = pe.m_nextPageI;
568 assert(pl.m_pageCount == count);
582 GroupPool::~GroupPool()
587 GroupPool::setMinPct(Uint32 minPct)
591 assert(sp.m_groupMinPct >= m_minPct);
592 sp.m_groupMinPct -= m_minPct;
594 sp.m_groupMinPct += minPct;
599 GroupPool::setMinPages(Uint32 minPages)
603 assert(sp.m_groupMinPages >= m_minPages);
604 sp.m_groupMinPages -= m_minPages;
606 sp.m_groupMinPages += minPages;
607 m_minPages = minPages;
612 HeapPool::HeapPool(Uint32 pageSize, Uint32 pageBits) :
615 m_currArea(&m_areaHead),
616 m_lastArea(&m_areaHead)
620 HeapPool::~HeapPool()
625 while ((ap = m_areaHead.m_nextArea) != 0) {
626 m_areaHead.m_nextArea = ap->m_nextArea;
632 HeapPool::Area::Area() :
643 HeapPool::getNewPage()
645 Area* ap = m_currArea;
646 if (ap->m_currPage == ap->m_numPages) {
648 if (ap->m_nextArea == 0) {
649 if (! allocMemoryImpl())
652 ap = m_currArea = ap->m_nextArea;
655 assert(ap->m_currPage < ap->m_numPages);
656 PtrI pageI = ap->m_firstPageI;
657 Uint32 recBits = m_recBits;
658 Int32 ip = (Int32)pageI >> recBits;
659 ip += ap->m_currPage;
660 pageI = ip << recBits;
666 HeapPool::allocInit()
668 Uint32 pageCount = (1 << m_pageBits);
669 if (m_pageEnt == 0) {
671 Uint32 bytes = pageCount *
sizeof(PageEnt);
672 m_pageEnt =
static_cast<PageEnt*
>(malloc(bytes));
675 for (Uint32
i = 0;
i < pageCount;
i++)
676 new (&m_pageEnt[
i]) PageEnt();
678 if (m_pageType == 0) {
680 Uint32 bytes = pageCount;
681 m_pageType =
static_cast<Uint8*
>(malloc(bytes));
684 memset(m_pageType, 0, bytes);
690 HeapPool::allocArea(Area* ap, Uint32 tryPages)
692 Uint32 pageSize = m_pageSize;
694 Uint8* p1 = (Uint8*)malloc(pageSize * (tryPages + 1));
698 UintPtr n1 = (UintPtr)p1;
699 UintPtr n2 = SP_ALIGN(n1, (UintPtr)pageSize);
700 Uint8* p2 = p1 + (n2 - n1);
701 assert(p2 >= p1 && p2 - p1 < pageSize && (UintPtr)p2 % pageSize == 0);
706 Uint32 pageI = getPageI(p2);
707 ap->m_firstPageI = pageI;
711 ap->m_numPages = tryPages + (p1 == p2);
716 HeapPool::allocMemoryImpl()
721 if (m_maxPages <= m_totPages)
723 Uint32 needPages = (m_totPages == 0 ? m_initPages : m_incrPages);
724 if (needPages > m_maxPages - m_totPages)
725 needPages = m_maxPages - m_totPages;
726 while (needPages != 0) {
728 Area* ap =
static_cast<Area*
>(malloc(
sizeof(Area)));
732 m_lastArea->m_nextArea = ap;
735 Uint32 wantPages = needPages;
736 if (m_incrPages != 0 && wantPages > m_incrPages)
737 wantPages = m_incrPages;
738 Uint32 tryPages = wantPages;
739 while (tryPages != 0) {
740 if (allocArea(ap, tryPages))
747 Uint32 numPages = ap->m_numPages;
748 m_totPages += numPages;
749 needPages = (needPages > numPages ? needPages - numPages : 0);