|
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/searchList.h#1 $
|
|
Packit Service |
310c69 |
*/
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#ifndef SEARCH_LIST_H
|
|
Packit Service |
310c69 |
#define SEARCH_LIST_H
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#include "cachedChapterIndex.h"
|
|
Packit Service |
310c69 |
#include "compiler.h"
|
|
Packit Service |
310c69 |
#include "stringUtils.h"
|
|
Packit Service |
310c69 |
#include "typeDefs.h"
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* A SearchList represents the permutations of the sparse chapter index cache
|
|
Packit Service |
310c69 |
* entry array. Those permutations express an ordering on the chapter indexes,
|
|
Packit Service |
310c69 |
* from most recently accessed to least recently accessed, which is the order
|
|
Packit Service |
310c69 |
* in which the indexes should be searched and the reverse order in which they
|
|
Packit Service |
310c69 |
* should be evicted from the cache (LRU cache replacement policy).
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* Cache entries that are dead (virtualChapter == UINT64_MAX) are kept as a
|
|
Packit Service |
310c69 |
* suffix of the list, avoiding the need to even iterate over them to search,
|
|
Packit Service |
310c69 |
* and ensuring that dead entries are replaced before any live entries are
|
|
Packit Service |
310c69 |
* evicted.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* The search list is intended to be instantated for each zone thread,
|
|
Packit Service |
310c69 |
* avoiding any need for synchronization. The structure is allocated on a
|
|
Packit Service |
310c69 |
* cache boundary to avoid false sharing of memory cache lines between zone
|
|
Packit Service |
310c69 |
* threads.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
typedef struct searchList {
|
|
Packit Service |
310c69 |
/** The number of cached chapter indexes and search list entries */
|
|
Packit Service |
310c69 |
uint8_t capacity;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** The index in the entries array of the first dead cache entry */
|
|
Packit Service |
310c69 |
uint8_t firstDeadEntry;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** The chapter array indexes representing the chapter search order */
|
|
Packit Service |
310c69 |
uint8_t entries[];
|
|
Packit Service |
310c69 |
} SearchList;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* SearchListIterator captures the fields needed to iterate over the live
|
|
Packit Service |
310c69 |
* entries in a search list and return the CachedChapterIndex pointers that
|
|
Packit Service |
310c69 |
* the search code actually wants to deal with.
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
typedef struct {
|
|
Packit Service |
310c69 |
/** The search list defining the chapter search iteration order */
|
|
Packit Service |
310c69 |
SearchList *list;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** The index of the next entry to return from the search list */
|
|
Packit Service |
310c69 |
unsigned int nextEntry;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/** The cached chapters that are referenced by the search list */
|
|
Packit Service |
310c69 |
CachedChapterIndex *chapters;
|
|
Packit Service |
310c69 |
} SearchListIterator;
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Allocate and initialize a new chapter cache search list with the same
|
|
Packit Service |
310c69 |
* capacity as the cache. The index of each entry in the cache will appear
|
|
Packit Service |
310c69 |
* exactly once in the array. All the chapters in the cache are assumed to be
|
|
Packit Service |
310c69 |
* initially dead, so firstDeadEntry will be zero and no chapters will be
|
|
Packit Service |
310c69 |
* returned when the search list is iterated.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param [in] capacity the number of entries in the search list
|
|
Packit Service |
310c69 |
* @param [out] listPtr a pointer in which to return the new search list
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
int makeSearchList(unsigned int capacity,
|
|
Packit Service |
310c69 |
SearchList **listPtr)
|
|
Packit Service |
310c69 |
__attribute__((warn_unused_result));
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Free a search list and null out the reference to it.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param listPtr the reference to the search list to free
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
void freeSearchList(SearchList **listPtr);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Copy the contents of one search list to another.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param source the list to copy
|
|
Packit Service |
310c69 |
* @param target the list to replace
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE void copySearchList(const SearchList *source,
|
|
Packit Service |
310c69 |
SearchList *target)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
*target = *source;
|
|
Packit Service |
310c69 |
memcpy(target->entries, source->entries, source->capacity);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Prepare to iterate over the live cache entries a search list.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param list the list defining the live chapters and the search order
|
|
Packit Service |
310c69 |
* @param chapters the chapter index entries to return from getNextChapter()
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return an iterator positioned at the start of the search list
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE SearchListIterator
|
|
Packit Service |
310c69 |
iterateSearchList(SearchList *list, CachedChapterIndex chapters[])
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
SearchListIterator iterator = {
|
|
Packit Service |
310c69 |
.list = list,
|
|
Packit Service |
310c69 |
.nextEntry = 0,
|
|
Packit Service |
310c69 |
.chapters = chapters,
|
|
Packit Service |
310c69 |
};
|
|
Packit Service |
310c69 |
return iterator;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Check if the search list iterator has another entry to return.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param iterator the search list iterator
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return true if getNextChapter() may be called
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE bool hasNextChapter(const SearchListIterator *iterator)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return (iterator->nextEntry < iterator->list->firstDeadEntry);
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Return a pointer to the next live chapter in the search list iteration and
|
|
Packit Service |
310c69 |
* advance the iterator. This must only be called when hasNextChapter()
|
|
Packit Service |
310c69 |
* returns true .
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param iterator the search list iterator
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return a pointer to the next live chapter index in the search list order
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE CachedChapterIndex *getNextChapter(SearchListIterator *iterator)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
return &iterator->chapters[iterator->list->entries[iterator->nextEntry++]];
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Rotate the pointers in a prefix of a search list downwards by one item,
|
|
Packit Service |
310c69 |
* pushing elements deeper into the list and moving a new chapter to the start
|
|
Packit Service |
310c69 |
* of the search list. This is the "make most recent" operation on the search
|
|
Packit Service |
310c69 |
* list.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* If the search list provided is [ 0 1 2 3 4 ] and the prefix
|
|
Packit Service |
310c69 |
* length is 4 , then 3 is being moved to the front.
|
|
Packit Service |
310c69 |
* The search list after the call will be [ 3 0 1 2 4 ] and the
|
|
Packit Service |
310c69 |
* function will return 3 .
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param searchList the chapter index search list to rotate
|
|
Packit Service |
310c69 |
* @param prefixLength the length of the prefix of the list to rotate
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @return the array index of the chapter cache entry that is now at the front
|
|
Packit Service |
310c69 |
* of the search list
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
static INLINE uint8_t rotateSearchList(SearchList *searchList,
|
|
Packit Service |
310c69 |
uint8_t prefixLength)
|
|
Packit Service |
310c69 |
{
|
|
Packit Service |
310c69 |
// Grab the value of the last entry in the list prefix.
|
|
Packit Service |
310c69 |
uint8_t mostRecent = searchList->entries[prefixLength - 1];
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
if (prefixLength > 1) {
|
|
Packit Service |
310c69 |
// Push the first N-1 entries down by one entry, overwriting the entry
|
|
Packit Service |
310c69 |
// we just grabbed.
|
|
Packit Service |
310c69 |
memmove(&searchList->entries[1],
|
|
Packit Service |
310c69 |
&searchList->entries[0],
|
|
Packit Service |
310c69 |
prefixLength - 1);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// We now have a hole at the front of the list in which we can place the
|
|
Packit Service |
310c69 |
// rotated entry.
|
|
Packit Service |
310c69 |
searchList->entries[0] = mostRecent;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
// This function is also used to move a dead chapter to the front of the
|
|
Packit Service |
310c69 |
// list, in which case the suffix of dead chapters was pushed down too.
|
|
Packit Service |
310c69 |
if (searchList->firstDeadEntry < prefixLength) {
|
|
Packit Service |
310c69 |
searchList->firstDeadEntry += 1;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
return mostRecent;
|
|
Packit Service |
310c69 |
}
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
/**
|
|
Packit Service |
310c69 |
* Purge invalid cache entries, marking them as dead and moving them to the
|
|
Packit Service |
310c69 |
* end of the search list, then push any chapters that have skipSearch set
|
|
Packit Service |
310c69 |
* down so they follow all the remaining live, valid chapters in the search
|
|
Packit Service |
310c69 |
* list. This effectively sorts the search list into three regions--active,
|
|
Packit Service |
310c69 |
* skippable, and dead--while maintaining the LRU ordering that already
|
|
Packit Service |
310c69 |
* existed (a stable sort).
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* This operation must only be called during the critical section in
|
|
Packit Service |
310c69 |
* updateSparseCache() since it effectively changes cache membership.
|
|
Packit Service |
310c69 |
*
|
|
Packit Service |
310c69 |
* @param searchList the chapter index search list to purge
|
|
Packit Service |
310c69 |
* @param chapters the chapter index cache entries
|
|
Packit Service |
310c69 |
* @param oldestVirtualChapter the oldest virtual chapter
|
|
Packit Service |
310c69 |
**/
|
|
Packit Service |
310c69 |
void purgeSearchList(SearchList *searchList,
|
|
Packit Service |
310c69 |
const CachedChapterIndex chapters[],
|
|
Packit Service |
310c69 |
uint64_t oldestVirtualChapter);
|
|
Packit Service |
310c69 |
|
|
Packit Service |
310c69 |
#endif /* SEARCH_LIST_H */
|