|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Copyright (c) 2020 Red Hat, Inc.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is free software; you can redistribute it and/or
|
|
Packit Service |
310c69 |
* modify it under the terms of the GNU General Public License
|
|
Packit Service |
310c69 |
* as published by the Free Software Foundation; either version 2
|
|
Packit Service |
310c69 |
* of the License, or (at your option) any later version.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
310c69 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
310c69 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
310c69 |
* GNU General Public License for more details.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
310c69 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
310c69 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit Service |
310c69 |
* 02110-1301, USA.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* $Id: //eng/uds-releases/jasper/src/uds/pageCache.h#5 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#ifndef PAGE_CACHE_H
|
|
Packit Service |
310c69 |
#define PAGE_CACHE_H
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "atomicDefs.h"
|
|
Packit Service |
310c69 |
#include "cacheCounters.h"
|
|
Packit Service |
310c69 |
#include "chapterIndex.h"
|
|
Packit Service |
310c69 |
#include "common.h"
|
|
Packit Service |
310c69 |
#include "compiler.h"
|
|
Packit Service |
310c69 |
#include "indexConfig.h"
|
|
Packit Service |
310c69 |
#include "opaqueTypes.h"
|
|
Packit Service |
310c69 |
#include "permassert.h"
|
|
Packit Service |
310c69 |
#include "request.h"
|
|
Packit Service |
310c69 |
#include "volumeStore.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct requestList {
|
|
Packit Service |
310c69 |
Request *first;
|
|
Packit Service |
310c69 |
Request *last;
|
|
Packit Service |
310c69 |
} RequestList;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct cachedPage {
|
|
Packit Service |
310c69 |
/* whether this page is currently being read asynchronously */
|
|
Packit Service |
310c69 |
bool cp_readPending;
|
|
Packit Service |
310c69 |
/* if equal to numCacheEntries, the page is invalid */
|
|
Packit Service |
310c69 |
unsigned int cp_physicalPage;
|
|
Packit Service |
310c69 |
/* the value of the volume clock when this page was last used */
|
|
Packit Service |
310c69 |
int64_t cp_lastUsed;
|
|
Packit Service |
310c69 |
/* the cache page data */
|
|
Packit Service |
310c69 |
struct volume_page cp_pageData;
|
|
Packit Service |
310c69 |
/* the chapter index page. This is here, even for record pages */
|
|
Packit Service |
310c69 |
DeltaIndexPage cp_indexPage;
|
|
Packit Service |
310c69 |
} CachedPage;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
enum {
|
|
Packit Service |
310c69 |
VOLUME_CACHE_MAX_ENTRIES = (UINT16_MAX >> 1),
|
|
Packit Service |
310c69 |
VOLUME_CACHE_QUEUED_FLAG = (1 << 15),
|
|
Packit Service |
310c69 |
VOLUME_CACHE_DEFAULT_MAX_QUEUED_READS = 4096
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct queuedRead {
|
|
Packit Service |
310c69 |
/* whether this queue entry is invalid */
|
|
Packit Service |
310c69 |
bool invalid;
|
|
Packit Service |
310c69 |
/* whether this queue entry has a pending read on it */
|
|
Packit Service |
310c69 |
bool reserved;
|
|
Packit Service |
310c69 |
/* physical page to read */
|
|
Packit Service |
310c69 |
unsigned int physicalPage;
|
|
Packit Service |
310c69 |
/* list of requests waiting on a queued read */
|
|
Packit Service |
310c69 |
RequestList requestList;
|
|
Packit Service |
310c69 |
} QueuedRead;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// Reason for invalidating a cache entry, used for gathering statistics
|
|
Packit Service |
310c69 |
typedef enum invalidationReason {
|
|
Packit Service |
310c69 |
INVALIDATION_EVICT, // cache is full, goodbye
|
|
Packit Service |
310c69 |
INVALIDATION_EXPIRE, // your chapter is being overwritten
|
|
Packit Service |
310c69 |
INVALIDATION_ERROR, // error happened; don't try to use data
|
|
Packit Service |
310c69 |
INVALIDATION_INIT_SHUTDOWN
|
|
Packit Service |
310c69 |
} InvalidationReason;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* Value stored atomically in a SearchPendingCounter. The low order 32 bits is
|
|
Packit Service |
310c69 |
* the physical page number of the cached page being read. The high order 32
|
|
Packit Service |
310c69 |
* bits is a sequence number.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* An InvalidateCounter is only written by its zone thread by calling the
|
|
Packit Service |
310c69 |
* beginPendingSearch or endPendingSearch methods.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Any other thread that is accessing an InvalidateCounter is reading the value
|
|
Packit Service |
310c69 |
* in the waitForPendingSearches method.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
typedef int64_t InvalidateCounter;
|
|
Packit Service |
310c69 |
// Fields of InvalidateCounter.
|
|
Packit Service |
310c69 |
// These must be 64 bit, so an enum cannot be not used.
|
|
Packit Service |
310c69 |
#define PAGE_FIELD ((long)UINT_MAX) // The page number field
|
|
Packit Service |
310c69 |
#define COUNTER_LSB (PAGE_FIELD + 1L) // The LSB of the counter field
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct __attribute__((aligned(CACHE_LINE_BYTES))) {
|
|
Packit Service |
310c69 |
atomic64_t atomicValue;
|
|
Packit Service |
310c69 |
} SearchPendingCounter;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
typedef struct pageCache {
|
|
Packit Service |
310c69 |
// Geometry governing the volume
|
|
Packit Service |
310c69 |
const Geometry *geometry;
|
|
Packit Service |
310c69 |
// The number of zones
|
|
Packit Service |
310c69 |
unsigned int zoneCount;
|
|
Packit Service |
310c69 |
// The number of index entries
|
|
Packit Service |
310c69 |
unsigned int numIndexEntries;
|
|
Packit Service |
310c69 |
// The max number of cached entries
|
|
Packit Service |
310c69 |
uint16_t numCacheEntries;
|
|
Packit Service |
310c69 |
// The index used to quickly access page in cache - top bit is a 'queued'
|
|
Packit Service |
310c69 |
// flag
|
|
Packit Service |
310c69 |
uint16_t *index;
|
|
Packit Service |
310c69 |
// The cache
|
|
Packit Service |
310c69 |
CachedPage *cache;
|
|
Packit Service |
310c69 |
// A counter for each zone to keep track of when a search is occurring
|
|
Packit Service |
310c69 |
// within that zone.
|
|
Packit Service |
310c69 |
SearchPendingCounter *searchPendingCounters;
|
|
Packit Service |
310c69 |
// Queued reads, as a circular array, with first and last indexes
|
|
Packit Service |
310c69 |
QueuedRead *readQueue;
|
|
Packit Service |
310c69 |
// Cache counters for stats. This is the first field of a PageCache that is
|
|
Packit Service |
310c69 |
// not constant after the struct is initialized.
|
|
Packit Service |
310c69 |
CacheCounters counters;
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Entries are enqueued at readQueueLast.
|
|
Packit Service |
310c69 |
* To 'reserve' entries, we get the entry pointed to by readQueueLastRead
|
|
Packit Service |
310c69 |
* and increment last read. This is done with a lock so if another reader
|
|
Packit Service |
310c69 |
* thread reserves a read, it will grab the next one. After every read
|
|
Packit Service |
310c69 |
* is completed, the reader thread calls releaseReadQueueEntry which
|
|
Packit Service |
310c69 |
* increments readQueueFirst until it is equal to readQueueLastRead, but only
|
|
Packit Service |
310c69 |
* if the value pointed to by readQueueFirst is no longer pending.
|
|
Packit Service |
310c69 |
* This means that if n reads are outstanding, readQueueFirst may not
|
|
Packit Service |
310c69 |
* be incremented until the last of the reads finishes.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* First Last
|
|
Packit Service |
310c69 |
* || | | | | | ||
|
|
Packit Service |
310c69 |
* LR (1) (2)
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Read thread 1 increments last read (1), then read thread 2 increments it
|
|
Packit Service |
310c69 |
* (2). When each read completes, it checks to see if it can increment first,
|
|
Packit Service |
310c69 |
* when all concurrent reads have completed, readQueueFirst should equal
|
|
Packit Service |
310c69 |
* readQueueLastRead.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
uint16_t readQueueFirst;
|
|
Packit Service |
310c69 |
uint16_t readQueueLastRead;
|
|
Packit Service |
310c69 |
uint16_t readQueueLast;
|
|
Packit Service |
310c69 |
// The size of the read queue
|
|
Packit Service |
310c69 |
unsigned int readQueueMaxSize;
|
|
Packit Service |
310c69 |
// Page access counter
|
|
Packit Service |
310c69 |
atomic64_t clock;
|
|
Packit Service |
310c69 |
} PageCache;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Allocate a cache for a volume.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param geometry The geometry governing the volume
|
|
Packit Service |
310c69 |
* @param chaptersInCache The size (in chapters) of the page cache
|
|
Packit Service |
310c69 |
* @param readQueueMaxSize The maximum size of the read queue
|
|
Packit Service |
310c69 |
* @param zoneCount The number of zones in the index
|
|
Packit Service |
310c69 |
* @param cachePtr A pointer to hold the new page cache
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int makePageCache(const Geometry *geometry,
|
|
Packit Service |
310c69 |
unsigned int chaptersInCache,
|
|
Packit Service |
310c69 |
unsigned int readQueueMaxSize,
|
|
Packit Service |
310c69 |
unsigned int zoneCount,
|
|
Packit Service |
310c69 |
PageCache **cachePtr)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Clean up a volume's cache
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the volumecache
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
void freePageCache(PageCache *cache);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Invalidates a page cache for a particular chapter
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param chapter the chapter
|
|
Packit Service |
310c69 |
* @param pagesPerChapter the number of pages per chapter
|
|
Packit Service |
310c69 |
* @param reason the reason for invalidation
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int invalidatePageCacheForChapter(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int chapter,
|
|
Packit Service |
310c69 |
unsigned int pagesPerChapter,
|
|
Packit Service |
310c69 |
InvalidationReason reason)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Find a page, invalidate it, and make its memory the least recent. This
|
|
Packit Service |
310c69 |
* method is only exposed for the use of unit tests.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache The cache containing the page
|
|
Packit Service |
310c69 |
* @param physicalPage The id of the page to invalidate
|
|
Packit Service |
310c69 |
* @param readQueue The queue of pending reads (may be NULL)
|
|
Packit Service |
310c69 |
* @param reason The reason for the invalidation, for stats
|
|
Packit Service |
310c69 |
* @param mustFind If true , it is an error if the page
|
|
Packit Service |
310c69 |
* can't be found
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int findInvalidateAndMakeLeastRecent(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int physicalPage,
|
|
Packit Service |
310c69 |
QueuedRead *readQueue,
|
|
Packit Service |
310c69 |
InvalidationReason reason,
|
|
Packit Service |
310c69 |
bool mustFind);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Make the page the most recent in the cache
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param pagePtr the page to make most recent
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
void makePageMostRecent(PageCache *cache, CachedPage *pagePtr);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Verifies that a page is in the cache. This method is only exposed for the
|
|
Packit Service |
310c69 |
* use of unit tests.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the cache to verify
|
|
Packit Service |
310c69 |
* @param page the page to find
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int assertPageInCache(PageCache *cache, CachedPage *page)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Gets a page from the cache.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param [in] cache the page cache
|
|
Packit Service |
310c69 |
* @param [in] physicalPage the page number
|
|
Packit Service |
310c69 |
* @param [in] probeType the type of cache access being done (CacheProbeType
|
|
Packit Service |
310c69 |
* optionally OR'ed with CACHE_PROBE_IGNORE_FAILURE)
|
|
Packit Service |
310c69 |
* @param [out] pagePtr the found page
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int getPageFromCache(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int physicalPage,
|
|
Packit Service |
310c69 |
int probeType,
|
|
Packit Service |
310c69 |
CachedPage **pagePtr)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Enqueue a read request
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param request the request that depends on the read
|
|
Packit Service |
310c69 |
* @param physicalPage the physicalPage for the request
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_QUEUED if the page was queued
|
|
Packit Service |
310c69 |
* UDS_SUCCESS if the queue was full
|
|
Packit Service |
310c69 |
* an error code if there was an error
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int enqueueRead(PageCache *cache, Request *request, unsigned int physicalPage)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Reserves a queued read for future dequeuing, but does not remove it from
|
|
Packit Service |
310c69 |
* the queue. Must call releaseReadQueueEntry to complete the process
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param queuePos the position in the read queue for this pending read
|
|
Packit Service |
310c69 |
* @param firstRequests list of requests for the pending read
|
|
Packit Service |
310c69 |
* @param physicalPage the physicalPage for the requests
|
|
Packit Service |
310c69 |
* @param invalid whether or not this entry is invalid
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
bool reserveReadQueueEntry(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int *queuePos,
|
|
Packit Service |
310c69 |
Request **firstRequests,
|
|
Packit Service |
310c69 |
unsigned int *physicalPage,
|
|
Packit Service |
310c69 |
bool *invalid);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Releases a read from the queue, allowing it to be reused by future
|
|
Packit Service |
310c69 |
* enqueues
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param queuePos queue entry position
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
void releaseReadQueueEntry(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int queuePos);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Check for the page cache read queue being empty.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache for which to check the read queue.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if the read queue for cache is empty, false otherwise.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool readQueueIsEmpty(PageCache *cache)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (cache->readQueueFirst == cache->readQueueLast);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Check for the page cache read queue being full.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache for which to check the read queue.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if the read queue for cache is full, false otherwise.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool readQueueIsFull(PageCache *cache)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (cache->readQueueFirst ==
|
|
Packit Service |
310c69 |
(cache->readQueueLast + 1) % cache->readQueueMaxSize);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Selects a page in the cache to be used for a read.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This will clear the pointer in the page map and
|
|
Packit Service |
310c69 |
* set readPending to true on the cache page
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param pagePtr the page to add
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int selectVictimInCache(PageCache *cache,
|
|
Packit Service |
310c69 |
CachedPage **pagePtr)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Completes an async page read in the cache, so that
|
|
Packit Service |
310c69 |
* the page can now be used for incoming requests.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This will invalidate the old cache entry and point
|
|
Packit Service |
310c69 |
* the page map for the new page to this entry
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param physicalPage the page number
|
|
Packit Service |
310c69 |
* @param page the page to complete processing on
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int putPageInCache(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int physicalPage,
|
|
Packit Service |
310c69 |
CachedPage *page)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Cancels an async page read in the cache, so that
|
|
Packit Service |
310c69 |
* the page can now be used for incoming requests.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This will invalidate the old cache entry and clear
|
|
Packit Service |
310c69 |
* the read queued flag on the page map entry, if it
|
|
Packit Service |
310c69 |
* was set.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param physicalPage the page number to clear the queued read flag on
|
|
Packit Service |
310c69 |
* @param page the page to cancel processing on
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return UDS_SUCCESS or an error code
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
void cancelPageInCache(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int physicalPage,
|
|
Packit Service |
310c69 |
CachedPage *page);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Get the page cache size
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the size of the page cache
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
size_t getPageCacheSize(PageCache *cache)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Read the InvalidateCounter for the given zone.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param zoneNumber the zone number
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the InvalidateCounter value
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE InvalidateCounter getInvalidateCounter(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int zoneNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return atomic64_read(&cache->searchPendingCounters[zoneNumber].atomicValue);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Write the InvalidateCounter for the given zone.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param zoneNumber the zone number
|
|
Packit Service |
310c69 |
* @param invalidateCounter the InvalidateCounter value to write
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void setInvalidateCounter(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int zoneNumber,
|
|
Packit Service |
310c69 |
InvalidateCounter invalidateCounter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
atomic64_set(&cache->searchPendingCounters[zoneNumber].atomicValue,
|
|
Packit Service |
310c69 |
invalidateCounter);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Return the physical page number of the page being searched. The return
|
|
Packit Service |
310c69 |
* value is only valid if searchPending indicates that a search is in progress.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param counter the InvalidateCounter value to check
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the page that the zone is searching
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE unsigned int pageBeingSearched(InvalidateCounter counter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return counter & PAGE_FIELD;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Determines whether a given value indicates that a search is occuring.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param invalidateCounter the InvalidateCounter value to check
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if a search is pending, false otherwise
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool searchPending(InvalidateCounter invalidateCounter)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (invalidateCounter & COUNTER_LSB) != 0;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Determines whether there is a search occuring for the given zone.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param zoneNumber the zone number
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if a search is pending, false otherwise
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool isSearchPending(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int zoneNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return searchPending(getInvalidateCounter(cache, zoneNumber));
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Increment the counter for the specified zone to signal that a search has
|
|
Packit Service |
310c69 |
* begun. Also set which page is being searched. The searchPendingCounters
|
|
Packit Service |
310c69 |
* are protecting read access to pages indexed by the cache. This is the
|
|
Packit Service |
310c69 |
* "lock" action.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param physicalPage the page that the zone is searching
|
|
Packit Service |
310c69 |
* @param zoneNumber the zone number
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void beginPendingSearch(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int physicalPage,
|
|
Packit Service |
310c69 |
unsigned int zoneNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
InvalidateCounter invalidateCounter = getInvalidateCounter(cache,
|
|
Packit Service |
310c69 |
zoneNumber);
|
|
Packit Service |
310c69 |
invalidateCounter &= ~PAGE_FIELD;
|
|
Packit Service |
310c69 |
invalidateCounter |= physicalPage;
|
|
Packit Service |
310c69 |
invalidateCounter += COUNTER_LSB;
|
|
Packit Service |
310c69 |
setInvalidateCounter(cache, zoneNumber, invalidateCounter);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(searchPending(invalidateCounter),
|
|
Packit Service |
310c69 |
"Search is pending for zone %u", zoneNumber);
|
|
Packit Service |
310c69 |
/*
|
|
Packit Service |
310c69 |
* This memory barrier ensures that the write to the invalidate counter is
|
|
Packit Service |
310c69 |
* seen by other threads before this threads accesses the cached page. The
|
|
Packit Service |
310c69 |
* corresponding read memory barrier is in waitForPendingSearches.
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Increment the counter for the specified zone to signal that a search has
|
|
Packit Service |
310c69 |
* finished. We do not need to reset the page since we only should ever look
|
|
Packit Service |
310c69 |
* at the page value if the counter indicates a search is ongoing. The
|
|
Packit Service |
310c69 |
* searchPendingCounters are protecting read access to pages indexed by the
|
|
Packit Service |
310c69 |
* cache. This is the "unlock" action.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param cache the page cache
|
|
Packit Service |
310c69 |
* @param zoneNumber the zone number
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void endPendingSearch(PageCache *cache,
|
|
Packit Service |
310c69 |
unsigned int zoneNumber)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// This memory barrier ensures that this thread completes reads of the
|
|
Packit Service |
310c69 |
// cached page before other threads see the write to the invalidate counter.
|
|
Packit Service |
310c69 |
smp_mb();
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
InvalidateCounter invalidateCounter = getInvalidateCounter(cache,
|
|
Packit Service |
310c69 |
zoneNumber);
|
|
Packit Service |
310c69 |
ASSERT_LOG_ONLY(searchPending(invalidateCounter),
|
|
Packit Service |
310c69 |
"Search is pending for zone %u", zoneNumber);
|
|
Packit Service |
310c69 |
invalidateCounter += COUNTER_LSB;
|
|
Packit Service |
310c69 |
setInvalidateCounter(cache, zoneNumber, invalidateCounter);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#endif /* PAGE_CACHE_H */
|