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