Exemple #1
0
/*
 * 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;
}
Exemple #2
0
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: Cache dump: "));
            for (unsigned int i=0; i < _pagesInMemory && tmp; i++) {
                fprintf(stderr, "%lu ", tmp->page()->pageNr());
                tmp = tmp->next();
            }
            fprintf(stderr, "\n");
        } else
            fprintf(stderr, _("DEBUG: Cache empty\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;
}