diff options
Diffstat (limited to 'src/vppinfra/qhash.c')
-rw-r--r-- | src/vppinfra/qhash.c | 859 |
1 files changed, 0 insertions, 859 deletions
diff --git a/src/vppinfra/qhash.c b/src/vppinfra/qhash.c deleted file mode 100644 index 3b5a175065d..00000000000 --- a/src/vppinfra/qhash.c +++ /dev/null @@ -1,859 +0,0 @@ -/* - * Copyright (c) 2015 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/* - Copyright (c) 2006 Eliot Dresselhaus - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include <vppinfra/qhash.h> - -#define QHASH_ALL_VALID ((1 << QHASH_KEYS_PER_BUCKET) - 1) - -void * -_qhash_resize (void *v, uword length, uword elt_bytes) -{ - qhash_t *h; - uword l; - - l = clib_max (max_log2 (length), 2 + QHASH_LOG2_KEYS_PER_BUCKET); - - /* Round up if less than 1/2 full. */ - l += ((f64) length / (f64) (1 << l)) < .5; - - v = _vec_resize (0, 1 << l, elt_bytes << l, sizeof (h[0]), - /* align */ sizeof (uword)); - - h = qhash_header (v); - h->n_elts = 0; - h->log2_hash_size = l; - h->hash_keys = - clib_mem_alloc_aligned_no_fail (sizeof (h->hash_keys[0]) << l, - CLIB_CACHE_LINE_BYTES); - vec_resize (h->hash_key_valid_bitmap, - 1 << (l - QHASH_LOG2_KEYS_PER_BUCKET)); - clib_memset (v, ~0, elt_bytes << l); - - return v; -} - -static u8 min_log2_table[256]; - -static inline uword -qhash_min_log2 (uword x) -{ - ASSERT (is_pow2 (x)); - ASSERT (x < 256); - return min_log2_table[x]; -} - -static void -qhash_min_log2_init () -{ - int i; - for (i = 0; i < 256; i++) - min_log2_table[i] = min_log2 (i); -} - -always_inline uword -qhash_get_valid_elt_mask (qhash_t * h, uword i) -{ - return h->hash_key_valid_bitmap[i / QHASH_KEYS_PER_BUCKET]; -} - -always_inline void -qhash_set_valid_elt_mask (qhash_t * h, uword i, uword mask) -{ - h->hash_key_valid_bitmap[i / QHASH_KEYS_PER_BUCKET] = mask; -} - -always_inline uword -qhash_search_bucket (uword * hash_keys, uword search_key, uword m) -{ - uword t; -#define _(i) ((hash_keys[i] == search_key) << i) - t = (_(0) | _(1) | _(2) | _(3)); - if (QHASH_KEYS_PER_BUCKET > 4) - t |= (_(4) | _(5) | _(6) | _(7)); - if (QHASH_KEYS_PER_BUCKET > 8) - t |= (_(8) | _(9) | _(10) | _(11) | _(12) | _(13) | _(14) | _(15)); -#undef _ - return m & t; -} - -/* Lookup multiple keys in the same hash table. */ -void -qhash_get_multiple (void *v, - uword * search_keys, - uword n_search_keys, u32 * result_indices) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, bucket_mask; - u32 *r; - - if (!v) - { - clib_memset (result_indices, ~0, - sizeof (result_indices[0]) * n_search_keys); - return; - } - - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - k = search_keys; - n_left = n_search_keys; - hash_keys = h->hash_keys; - r = result_indices; - - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, valid0, match0; - u32 a1, b1, c1, bi1, valid1, match1; - uword k0, k1, *h0, *h1; - - k0 = k[0]; - k1 = k[1]; - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - - match0 = qhash_search_bucket (h0, k0, valid0); - match1 = qhash_search_bucket (h1, k1, valid1); - - bi0 += qhash_min_log2 (match0); - bi1 += qhash_min_log2 (match1); - - r[0] = match0 ? bi0 : ~0; - r[1] = match1 ? bi1 : ~0; - r += 2; - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (!match0 && valid0 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k0); - r[-2] = p ? p[0] : ~0; - } - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (!match1 && valid1 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k1); - r[-1] = p ? p[0] : ~0; - } - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, valid0, match0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - /* Search one bucket. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - match0 = qhash_search_bucket (h0, k0, valid0); - - bi0 += qhash_min_log2 (match0); - - r[0] = match0 ? bi0 : ~0; - r += 1; - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (!match0 && valid0 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k0); - r[-1] = p ? p[0] : ~0; - } - } -} - -/* Lookup multiple keys in the same hash table. - Returns index of first matching key. */ -u32 -qhash_get_first_match (void *v, - uword * search_keys, - uword n_search_keys, uword * matching_key) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, match_mask, bucket_mask; - - if (!v) - return ~0; - - match_mask = 0; - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - k = search_keys; - n_left = n_search_keys; - hash_keys = h->hash_keys; - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, valid0; - u32 a1, b1, c1, bi1, valid1; - uword k0, k1, *h0, *h1; - - k0 = k[0]; - k1 = k[1]; - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - match_mask = qhash_search_bucket (h0, k0, valid0); - match_mask |= (qhash_search_bucket (h1, k1, valid1) - << QHASH_KEYS_PER_BUCKET); - if (match_mask) - { - uword bi, is_match1; - - bi = qhash_min_log2 (match_mask); - is_match1 = bi >= QHASH_KEYS_PER_BUCKET; - - bi += ((is_match1 ? bi1 : bi0) - - (is_match1 << QHASH_LOG2_KEYS_PER_BUCKET)); - *matching_key = (k - 2 - search_keys) + is_match1; - return bi; - } - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID - || valid1 == QHASH_ALL_VALID)) - { - uword *p = 0; - uword ki = k - 2 - search_keys; - - if (valid0 == QHASH_ALL_VALID) - p = hash_get (h->overflow_hash, k0); - - if (!p && valid1 == QHASH_ALL_VALID) - { - p = hash_get (h->overflow_hash, k1); - ki++; - } - - if (p) - { - *matching_key = ki; - return p[0]; - } - } - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, valid0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - /* Search one bucket. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - match_mask = qhash_search_bucket (h0, k0, valid0); - if (match_mask) - { - uword bi; - bi = bi0 + qhash_min_log2 (match_mask); - *matching_key = (k - 1 - search_keys); - return bi; - } - - /* Full buckets trigger search of overflow hash. */ - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID)) - { - uword *p = hash_get (h->overflow_hash, k0); - if (p) - { - *matching_key = (k - 1 - search_keys); - return p[0]; - } - } - } - - return ~0; -} - -static void * -qhash_set_overflow (void *v, uword elt_bytes, - uword key, uword bi, uword * n_elts, u32 * result) -{ - qhash_t *h = qhash_header (v); - uword *p = hash_get (h->overflow_hash, key); - uword i; - - bi /= QHASH_KEYS_PER_BUCKET; - - if (p) - i = p[0]; - else - { - uword l = vec_len (h->overflow_free_indices); - if (l > 0) - { - i = h->overflow_free_indices[l - 1]; - _vec_len (h->overflow_free_indices) = l - 1; - } - else - i = (1 << h->log2_hash_size) + hash_elts (h->overflow_hash); - hash_set (h->overflow_hash, key, i); - vec_validate (h->overflow_counts, bi); - h->overflow_counts[bi] += 1; - *n_elts += 1; - - l = vec_len (v); - if (i >= l) - { - uword dl = round_pow2 (1 + i - l, 8); - v = _vec_resize (v, dl, (l + dl) * elt_bytes, sizeof (h[0]), - /* align */ sizeof (uword)); - clib_memset (v + l * elt_bytes, ~0, dl * elt_bytes); - } - } - - *result = i; - - return v; -} - -static uword -qhash_unset_overflow (void *v, uword key, uword bi, uword * n_elts) -{ - qhash_t *h = qhash_header (v); - uword *p = hash_get (h->overflow_hash, key); - uword result; - - bi /= QHASH_KEYS_PER_BUCKET; - - if (p) - { - result = p[0]; - hash_unset (h->overflow_hash, key); - ASSERT (bi < vec_len (h->overflow_counts)); - ASSERT (h->overflow_counts[bi] > 0); - ASSERT (*n_elts > 0); - vec_add1 (h->overflow_free_indices, result); - h->overflow_counts[bi] -= 1; - *n_elts -= 1; - } - else - result = ~0; - - return result; -} - -always_inline uword -qhash_find_free (uword i, uword valid_mask) -{ - return first_set (~valid_mask & pow2_mask (QHASH_KEYS_PER_BUCKET)); -} - -void * -_qhash_set_multiple (void *v, - uword elt_bytes, - uword * search_keys, - uword n_search_keys, u32 * result_indices) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, n_elts, bucket_mask; - u32 *r; - - if (vec_len (v) < n_search_keys) - v = _qhash_resize (v, n_search_keys, elt_bytes); - - if (qhash_min_log2 (2) != 1) - { - qhash_min_log2_init (); - ASSERT (qhash_min_log2 (2) == 1); - } - - ASSERT (v != 0); - - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - hash_keys = h->hash_keys; - k = search_keys; - r = result_indices; - n_left = n_search_keys; - n_elts = h->n_elts; - - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, match0, valid0, free0; - u32 a1, b1, c1, bi1, match1, valid1, free1; - uword k0, *h0; - uword k1, *h1; - - k0 = k[0]; - k1 = k[1]; - - /* Keys must be unique. */ - ASSERT (k0 != k1); - - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - - match0 = qhash_search_bucket (h0, k0, valid0); - match1 = qhash_search_bucket (h1, k1, valid1); - - /* Find first free element starting at hash offset into bucket. */ - free0 = qhash_find_free (c0 & (QHASH_KEYS_PER_BUCKET - 1), valid0); - - valid1 = valid1 | (bi0 == bi1 ? free0 : 0); - free1 = qhash_find_free (c1 & (QHASH_KEYS_PER_BUCKET - 1), valid1); - - n_elts += (match0 == 0) + (match1 == 0); - - match0 = match0 ? match0 : free0; - match1 = match1 ? match1 : free1; - - valid0 |= match0; - valid1 |= match1; - - h0 += qhash_min_log2 (match0); - h1 += qhash_min_log2 (match1); - - if (PREDICT_FALSE (!match0 || !match1)) - goto slow_path2; - - h0[0] = k0; - h1[0] = k1; - r[0] = h0 - hash_keys; - r[1] = h1 - hash_keys; - r += 2; - qhash_set_valid_elt_mask (h, bi0, valid0); - qhash_set_valid_elt_mask (h, bi1, valid1); - continue; - - slow_path2: - if (!match0) - { - n_elts -= 1; - v = qhash_set_overflow (v, elt_bytes, k0, bi0, &n_elts, &r[0]); - } - else - { - h0[0] = k0; - r[0] = h0 - hash_keys; - qhash_set_valid_elt_mask (h, bi0, valid0); - } - if (!match1) - { - n_elts -= 1; - v = qhash_set_overflow (v, elt_bytes, k1, bi1, &n_elts, &r[1]); - } - else - { - h1[0] = k1; - r[1] = h1 - hash_keys; - qhash_set_valid_elt_mask (h, bi1, valid1); - } - r += 2; - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, match0, valid0, free0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - valid0 = qhash_get_valid_elt_mask (h, bi0); - - /* Find first free element starting at hash offset into bucket. */ - free0 = qhash_find_free (c0 & (QHASH_KEYS_PER_BUCKET - 1), valid0); - - match0 = qhash_search_bucket (h0, k0, valid0); - - n_elts += (match0 == 0); - - match0 = match0 ? match0 : free0; - - valid0 |= match0; - - h0 += qhash_min_log2 (match0); - - if (PREDICT_FALSE (!match0)) - goto slow_path1; - - h0[0] = k0; - r[0] = h0 - hash_keys; - r += 1; - qhash_set_valid_elt_mask (h, bi0, valid0); - continue; - - slow_path1: - n_elts -= 1; - v = qhash_set_overflow (v, elt_bytes, k0, bi0, &n_elts, &r[0]); - r += 1; - } - - h = qhash_header (v); - h->n_elts = n_elts; - - return v; -} - -static uword -unset_slow_path (void *v, uword elt_bytes, - uword k0, uword bi0, uword valid0, uword match0, - uword * n_elts) -{ - qhash_t *h = qhash_header (v); - uword i, j = 0, k, l, t = ~0; - hash_pair_t *p, *found; - - if (!match0) - { - if (valid0 == QHASH_ALL_VALID) - t = qhash_unset_overflow (v, k0, bi0, n_elts); - return t; - } - - i = bi0 / QHASH_KEYS_PER_BUCKET; - t = bi0 + qhash_min_log2 (match0); - - if (valid0 == QHASH_ALL_VALID - && i < vec_len (h->overflow_counts) && h->overflow_counts[i] > 0) - { - found = 0; - /* *INDENT-OFF* */ - hash_foreach_pair (p, h->overflow_hash, ({ - j = qhash_hash_mix (h, p->key) / QHASH_KEYS_PER_BUCKET; - if (j == i) - { - found = p; - break; - } - })); - /* *INDENT-ON* */ - ASSERT (found != 0); - ASSERT (j == i); - - l = found->value[0]; - k = found->key; - hash_unset3 (h->overflow_hash, k, &j); - vec_add1 (h->overflow_free_indices, j); - h->overflow_counts[i] -= 1; - - qhash_set_valid_elt_mask (h, bi0, valid0); - - h->hash_keys[t] = k; - clib_memswap (v + t * elt_bytes, v + l * elt_bytes, elt_bytes); - t = l; - } - else - qhash_set_valid_elt_mask (h, bi0, valid0 ^ match0); - - return t; -} - -void -_qhash_unset_multiple (void *v, - uword elt_bytes, - uword * search_keys, - uword n_search_keys, u32 * result_indices) -{ - qhash_t *h = qhash_header (v); - uword *k, *hash_keys; - uword n_left, n_elts, bucket_mask; - u32 *r; - - if (!v) - { - uword i; - for (i = 0; i < n_search_keys; i++) - result_indices[i] = ~0; - } - - bucket_mask = pow2_mask (h->log2_hash_size) & ~(QHASH_KEYS_PER_BUCKET - 1); - - hash_keys = h->hash_keys; - k = search_keys; - r = result_indices; - n_left = n_search_keys; - n_elts = h->n_elts; - - while (n_left >= 2) - { - u32 a0, b0, c0, bi0, match0, valid0; - u32 a1, b1, c1, bi1, match1, valid1; - uword k0, *h0; - uword k1, *h1; - - k0 = k[0]; - k1 = k[1]; - - /* Keys must be unique. */ - ASSERT (k0 != k1); - - n_left -= 2; - k += 2; - - a0 = a1 = h->hash_seeds[0]; - b0 = b1 = h->hash_seeds[1]; - c0 = c1 = h->hash_seeds[2]; - a0 ^= k0; - a1 ^= k1; -#if uword_bits == 64 - b0 ^= k0 >> 32; - b1 ^= k1 >> 32; -#endif - - hash_mix32_step_1 (a0, b0, c0); - hash_mix32_step_1 (a1, b1, c1); - hash_mix32_step_2 (a0, b0, c0); - hash_mix32_step_2 (a1, b1, c1); - hash_mix32_step_3 (a0, b0, c0); - hash_mix32_step_3 (a1, b1, c1); - - bi0 = c0 & bucket_mask; - bi1 = c1 & bucket_mask; - - h0 = hash_keys + bi0; - h1 = hash_keys + bi1; - - /* Search two buckets. */ - valid0 = qhash_get_valid_elt_mask (h, bi0); - valid1 = qhash_get_valid_elt_mask (h, bi1); - - match0 = qhash_search_bucket (h0, k0, valid0); - match1 = qhash_search_bucket (h1, k1, valid1); - - n_elts -= (match0 != 0) + (match1 != 0); - - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID - || valid1 == QHASH_ALL_VALID)) - goto slow_path2; - - valid0 ^= match0; - qhash_set_valid_elt_mask (h, bi0, valid0); - - valid1 = bi0 == bi1 ? valid0 : valid1; - valid1 ^= match1; - - qhash_set_valid_elt_mask (h, bi1, valid1); - - r[0] = match0 ? bi0 + qhash_min_log2 (match0) : ~0; - r[1] = match1 ? bi1 + qhash_min_log2 (match1) : ~0; - r += 2; - continue; - - slow_path2: - r[0] = unset_slow_path (v, elt_bytes, k0, bi0, valid0, match0, &n_elts); - if (bi0 == bi1) - { - /* Search again in same bucket to test new overflow element. */ - valid1 = qhash_get_valid_elt_mask (h, bi0); - if (!match1) - { - match1 = qhash_search_bucket (h1, k1, valid1); - n_elts -= (match1 != 0); - } - } - r[1] = unset_slow_path (v, elt_bytes, k1, bi1, valid1, match1, &n_elts); - r += 2; - } - - while (n_left >= 1) - { - u32 a0, b0, c0, bi0, match0, valid0; - uword k0, *h0; - - k0 = k[0]; - n_left -= 1; - k += 1; - - a0 = h->hash_seeds[0]; - b0 = h->hash_seeds[1]; - c0 = h->hash_seeds[2]; - a0 ^= k0; -#if uword_bits == 64 - b0 ^= k0 >> 32; -#endif - - hash_mix32 (a0, b0, c0); - - bi0 = c0 & bucket_mask; - - h0 = hash_keys + bi0; - - valid0 = qhash_get_valid_elt_mask (h, bi0); - - match0 = qhash_search_bucket (h0, k0, valid0); - n_elts -= (match0 != 0); - qhash_set_valid_elt_mask (h, bi0, valid0 ^ match0); - - r[0] = match0 ? bi0 + qhash_min_log2 (match0) : ~0; - r += 1; - - if (PREDICT_FALSE (valid0 == QHASH_ALL_VALID)) - r[-1] = unset_slow_path (v, elt_bytes, k0, bi0, valid0, match0, - &n_elts); - } - - h->n_elts = n_elts; -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ |