Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/agent/src/os/linux/hsearch/hsearch_r.c
38841 views
/*-1* Copyright (c) 2015 Nuxi, https://nuxi.nl/2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6* 1. Redistributions of source code must retain the above copyright7* notice, this list of conditions and the following disclaimer.8* 2. Redistributions in binary form must reproduce the above copyright9* notice, this list of conditions and the following disclaimer in the10* documentation and/or other materials provided with the distribution.11*12* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND13* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE14* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE15* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE16* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL17* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS18* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)19* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT20* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY21* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF22* SUCH DAMAGE.23*/2425#include <sys/cdefs.h>26__FBSDID("$FreeBSD: head/lib/libc/stdlib/hsearch_r.c 292767 2015-12-27 07:50:11Z ed $");2728#include <errno.h>29#include <limits.h>30#include "search.h"31#include <stdint.h>32#include <stdlib.h>33#include <string.h>3435#include "hsearch.h"3637/*38* Look up an unused entry in the hash table for a given hash. For this39* implementation we use quadratic probing. Quadratic probing has the40* advantage of preventing primary clustering.41*/42static ENTRY *43hsearch_lookup_free(struct __hsearch *hsearch, size_t hash)44{45size_t index, i;4647for (index = hash, i = 0;; index += ++i) {48ENTRY *entry = &hsearch->entries[index & hsearch->index_mask];49if (entry->key == NULL)50return (entry);51}52}5354/*55* Computes an FNV-1a hash of the key. Depending on the pointer size, this56* either uses the 32- or 64-bit FNV prime.57*/58static size_t59hsearch_hash(size_t offset_basis, const char *str)60{61size_t hash;6263hash = offset_basis;64while (*str != '\0') {65hash ^= (uint8_t)*str++;66if (sizeof(size_t) * CHAR_BIT <= 32)67hash *= UINT32_C(16777619);68else69hash *= UINT64_C(1099511628211);70}71return (hash);72}7374int75hsearch_r(ENTRY item, ACTION action, ENTRY **retval, struct hsearch_data *htab)76{77struct __hsearch *hsearch;78ENTRY *entry, *old_entries, *new_entries;79size_t hash, index, i, old_hash, old_count, new_count;8081hsearch = htab->__hsearch;82hash = hsearch_hash(hsearch->offset_basis, item.key);8384/*85* Search the hash table for an existing entry for this key.86* Stop searching if we run into an unused hash table entry.87*/88for (index = hash, i = 0;; index += ++i) {89entry = &hsearch->entries[index & hsearch->index_mask];90if (entry->key == NULL)91break;92if (strcmp(entry->key, item.key) == 0) {93*retval = entry;94return (1);95}96}9798/* Only perform the insertion if action is set to ENTER. */99if (action == FIND) {100errno = ESRCH;101return (0);102}103104if (hsearch->entries_used * 2 >= hsearch->index_mask) {105/* Preserve the old hash table entries. */106old_count = hsearch->index_mask + 1;107old_entries = hsearch->entries;108109/*110* Allocate and install a new table if insertion would111* yield a hash table that is more than 50% used. By112* using 50% as a threshold, a lookup will only take up113* to two steps on average.114*/115new_count = (hsearch->index_mask + 1) * 2;116new_entries = calloc(new_count, sizeof(ENTRY));117if (new_entries == NULL)118return (0);119hsearch->entries = new_entries;120hsearch->index_mask = new_count - 1;121122/* Copy over the entries from the old table to the new table. */123for (i = 0; i < old_count; ++i) {124entry = &old_entries[i];125if (entry->key != NULL) {126old_hash = hsearch_hash(hsearch->offset_basis,127entry->key);128*hsearch_lookup_free(hsearch, old_hash) =129*entry;130}131}132133/* Destroy the old hash table entries. */134free(old_entries);135136/*137* Perform a new lookup for a free table entry, so that138* we insert the entry into the new hash table.139*/140hsearch = htab->__hsearch;141entry = hsearch_lookup_free(hsearch, hash);142}143144/* Insert the new entry into the hash table. */145*entry = item;146++hsearch->entries_used;147*retval = entry;148return (1);149}150151152