Blame source/uds/searchList.h

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 */