Blame source/uds/searchList.c

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.c#2 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#include "searchList.h"
Packit Service 310c69
Packit Service 310c69
#include "errors.h"
Packit Service 310c69
#include "logger.h"
Packit Service 310c69
#include "memoryAlloc.h"
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
int makeSearchList(unsigned int   capacity,
Packit Service 310c69
                   SearchList   **listPtr)
Packit Service 310c69
{
Packit Service 310c69
  if (capacity == 0) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                   "search list must have entries");
Packit Service 310c69
  }
Packit Service 310c69
  if (capacity > UINT8_MAX) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                  "search list capacity must fit in 8 bits");
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // We need three temporary entry arrays for purgeSearchList(). Allocate them
Packit Service 310c69
  // contiguously with the main array.
Packit Service 310c69
  unsigned int bytes = (sizeof(SearchList) + (4 * capacity * sizeof(uint8_t)));
Packit Service 310c69
  SearchList *list;
Packit Service 310c69
  int result = allocateCacheAligned(bytes, "search list", &list);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  list->capacity       = capacity;
Packit Service 310c69
  list->firstDeadEntry = 0;
Packit Service 310c69
Packit Service 310c69
  // Fill in the indexes of the chapter index cache entries. These will be
Packit Service 310c69
  // only ever be permuted as the search list is used.
Packit Service 310c69
  uint8_t i;
Packit Service 310c69
  for (i = 0; i < capacity; i++) {
Packit Service 310c69
    list->entries[i] = i;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  *listPtr = list;
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**********************************************************************/
Packit Service 310c69
void freeSearchList(SearchList **listPtr)
Packit Service 310c69
{
Packit Service 310c69
  FREE(*listPtr);
Packit Service 310c69
  *listPtr = NULL;
Packit Service 310c69
}
Packit Service 310c69
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
  if (searchList->firstDeadEntry == 0) {
Packit Service 310c69
    // There are no live entries in the list to purge.
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  /*
Packit Service 310c69
   * Partition the previously-alive entries in the list into three temporary
Packit Service 310c69
   * lists, keeping the current LRU search order within each list. The element
Packit Service 310c69
   * array was allocated with enough space for all four lists.
Packit Service 310c69
   */
Packit Service 310c69
  uint8_t *entries = &searchList->entries[0];
Packit Service 310c69
  uint8_t *alive   = &entries[searchList->capacity];
Packit Service 310c69
  uint8_t *skipped = &alive[searchList->capacity];
Packit Service 310c69
  uint8_t *dead    = &skipped[searchList->capacity];
Packit Service 310c69
  unsigned int nextAlive   = 0;
Packit Service 310c69
  unsigned int nextSkipped = 0;
Packit Service 310c69
  unsigned int nextDead    = 0;
Packit Service 310c69
Packit Service 310c69
  int i;
Packit Service 310c69
  for (i = 0; i < searchList->firstDeadEntry; i++) {
Packit Service 310c69
    uint8_t entry = entries[i];
Packit Service 310c69
    const CachedChapterIndex *chapter = &chapters[entry];
Packit Service 310c69
    if ((chapter->virtualChapter < oldestVirtualChapter)
Packit Service 310c69
        || (chapter->virtualChapter == UINT64_MAX)) {
Packit Service 310c69
      dead[nextDead++] = entry;
Packit Service 310c69
    } else if (chapter->skipSearch) {
Packit Service 310c69
      skipped[nextSkipped++] = entry;
Packit Service 310c69
    } else {
Packit Service 310c69
      alive[nextAlive++] = entry;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // Copy the temporary lists back to the search list so we wind up with
Packit Service 310c69
  // [ alive, alive, skippable, new-dead, new-dead, old-dead, old-dead ]
Packit Service 310c69
  memcpy(entries, alive, nextAlive);
Packit Service 310c69
  entries += nextAlive;
Packit Service 310c69
Packit Service 310c69
  memcpy(entries, skipped, nextSkipped);
Packit Service 310c69
  entries += nextSkipped;
Packit Service 310c69
Packit Service 310c69
  memcpy(entries, dead, nextDead);
Packit Service 310c69
  // The first dead entry is now the start of the copied dead list.
Packit Service 310c69
  searchList->firstDeadEntry = (nextAlive + nextSkipped);
Packit Service 310c69
}