/* * Extraction d'une page du cache * Cache page extraction */ Page* getNextPage() { CacheEntry *entry = NULL; unsigned long nr=0; bool notUnregister = false; Page *page; // Get the next page number switch (_policy) { case EveryPagesIncreasing: nr = _lastPageRequested + 1; break; case EvenDecreasing: if (_lastPageRequested > 2) nr = _lastPageRequested - 2; else { nr = 1; setCachePolicy(OddIncreasing); } break; case OddIncreasing: if (!_lastPageRequested) nr = 1; else nr = _lastPageRequested + 2; break; } DEBUGMSG(_("Next requested page : %lu (# pages into memory=%lu/%u)"), nr, _pagesInMemory, CACHESIZE); // Wait for the page while (nr && (!_numberOfPages || _numberOfPages >= nr)) { { _pageTableLock.lock(); if (_maxPagesInTable >= nr && _pages[nr - 1] && !_pages[nr - 1]->isSwapped()) { entry = _pages[nr - 1]; _pages[nr - 1] = NULL; if (!entry->previous() && !entry->next() && entry != _inMemory) notUnregister = true; if (entry->previous()) entry->previous()->setNext(entry->next()); if (entry->next()) entry->next()->setPrevious(entry->previous()); if (entry == _inMemory) _inMemory = entry->next(); if (entry == _inMemoryLast) _inMemoryLast = NULL; _pageTableLock.unlock(); break; } else if (_maxPagesInTable >= nr && _pages[nr - 1] && _pages[nr - 1]->isSwapped()) _work++; _pageRequested = nr; _pageTableLock.unlock(); } _pageAvailable--; }; // Extract the page instance if (!entry) return NULL; _pagesInTable--; _lastPageRequested = nr; page = entry->page(); delete entry; // Preload a new page if (!notUnregister) _pagesInMemory--; _work++; return page; }
static void* _cacheControllerThread(void *_exitVar) { bool *needToExit = (bool *)_exitVar; bool whatToDo = true; DEBUGMSG(_("Cache controller thread loaded and is waiting for a job")); while (!(*needToExit)) { bool preloadPage = false; // Waiting for a job _work--; #ifdef DUMP_CACHE if (_pagesInMemory) { CacheEntry *tmp = _inMemory; fprintf(stderr, _("DEBUG: [34mCache dump: ")); for (unsigned int i=0; i < _pagesInMemory && tmp; i++) { fprintf(stderr, "%lu ", tmp->page()->pageNr()); tmp = tmp->next(); } fprintf(stderr, "[0m\n"); } else fprintf(stderr, _("DEBUG: [34mCache empty[0m\n")); #endif /* DUMP_CACHE */ // Does the thread needs to exit? if (*needToExit) break; /* * Check what action to do */ // Nothing? if (!_waitingList && (_pagesInMemory == CACHESIZE || _pagesInMemory == _pagesInTable)) continue; // new page to append and pages to preload? // Choose one action of them to do (and inverse the action to do at // each loop) if (_waitingList && !(_pagesInMemory == CACHESIZE || _pagesInMemory == _pagesInTable)) { preloadPage = whatToDo; whatToDo = ~whatToDo; // One of the two thing to do } else preloadPage = (_waitingList == NULL); /* * Preload a page */ if (preloadPage) { __manageMemoryCache(NULL); /* * Store a page */ } else { CacheEntry *entry; // Get the cache entry to store { _waitingListLock.lock(); entry = _waitingList; _waitingList = entry->next(); if (_lastWaitingList == entry) _lastWaitingList = NULL; _waitingListLock.unlock(); } // Store the entry in the page table { _pageTableLock.lock(); // Resize the page table if needed while (entry->page()->pageNr() > _maxPagesInTable) { if (!_maxPagesInTable) { _maxPagesInTable = CACHESIZE; _pages = new CacheEntry*[_maxPagesInTable]; memset(_pages, 0, _maxPagesInTable * sizeof(CacheEntry*)); } else { CacheEntry** tmp = new CacheEntry*[_maxPagesInTable*10]; memcpy(tmp, _pages, _maxPagesInTable * sizeof(CacheEntry*)); memset(tmp + _maxPagesInTable, 0, _maxPagesInTable * 9 * sizeof(CacheEntry*)); delete[] _pages; _pages = tmp; _maxPagesInTable *= 10; } } // Store the page in the table _pages[entry->page()->pageNr() - 1] = entry; _pageTableLock.unlock(); } _pagesInTable++; // Does the main thread needs this page? if (_pageRequested == entry->page()->pageNr()) { _pageTableLock.lock(); entry->setNext(NULL); entry->setPrevious(NULL); _pageAvailable++; _pageTableLock.unlock(); // So check whether the page can be kept in memory or have to // be swapped on the disk } else __manageMemoryCache(entry); } } DEBUGMSG(_("Cache controller unloaded. See ya")); return NULL; }