Heap::Page *Heap::WorkPage(int k) // get a new empty workpage { LLOG("AllocK - next work not available " << k << " empty: " << (void *)empty[k]); Page *page = empty[k]; // hot empty page of the same klass empty[k] = NULL; if(!page) { // try to reacquire pages freed remotely LLOG("AllocK - trying FreeRemote"); FreeRemote(); if(work[k]->freelist) { // partially free page found LLOG("AllocK - work available after FreeRemote " << k); return work[k]; } page = empty[k]; // hot empty page empty[k] = NULL; } if(!page) for(int i = 0; i < NKLASS; i++) // Try hot local page of different klass if(empty[i]) { LLOG("AllocK - free page available for reformatting " << k); page = empty[i]; empty[i] = NULL; page->Format(k); break; } if(!page) { // Attempt to find page in global storage of free pages Mutex::Lock __(mutex); aux.FreeRemoteRaw(); if(aux.work[k]->next != aux.work[k]) { // Try page of the same klass first page = aux.work[k]->next; page->Unlink(); page->heap = this; LLOG("AllocK - adopting aux page " << k << " page: " << (void *)page << ", free " << (void *)page->freelist); } if(!page && aux.empty[k]) { // Try hot empty page of the same klass page = aux.empty[k]; aux.empty[k] = page->next; LLOG("AllocK - empty aux page available of the same format " << k << " page: " << (void *)page << ", free " << (void *)page->freelist); } if(!page) for(int i = 0; i < NKLASS; i++) // Finally try to to find hot page of different klass if(aux.empty[i]) { page = aux.empty[i]; aux.empty[i] = page->next; page->Format(k); LLOG("AllocK - empty aux page available for reformatting " << k << " page: " << (void *)page << ", free " << (void *)page->freelist); break; } if(!page) { // Not free memory was found, ask system for the new page page = (Page *)AllocRaw4KB(Ksz(k)); LLOG("AllocK - allocated new system page " << (void *)page << " " << k); page->Format(k); } page->heap = this; } page->Link(work[k]); ASSERT(page->klass == k); return page; }
inline void *MSmall::AllocK(int k) { LOG("AllocK " << (int)k); Page *page = work[k]->next; for(;;) { ASSERT(page->klass == k); FreeLink *p = page->freelist; if(p) { page->freelist = p->next; ++page->active; return p; } if(page->free > page->Begin()) { // Try swapping with freelist void *p = page->free; page->free -= page->sz; ++page->active; return p; } if(page->next != page) { page->active = 255; page->Unlink(); page->Link(full[k]); page = work[k]->next; } else { page = empty[k]->next; if(page->next == page) { if(emptypages) { emptypages--; for(int i = 0; i < 16; i++) { // try inverse direction page = empty[i]->next; if(page->next != page) { page->Unlink(); break; } } ASSERT(page->next != page); } else // remote delete should be here! page = (Page *)AllocRaw4KB(); page->Format(k); ASSERT(page->klass == k); } else { ASSERT(emptypages > 0); page->Unlink(); emptypages--; ASSERT(page->klass == k); } page->Link(work[k]); ASSERT(page->klass == k); } } }