|
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 |
}
|