summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vppinfra/vppinfra/bihash_8_8.h20
-rw-r--r--vppinfra/vppinfra/bihash_doc.h140
-rw-r--r--vppinfra/vppinfra/bihash_template.c4
-rw-r--r--vppinfra/vppinfra/bihash_template.h4
4 files changed, 166 insertions, 2 deletions
diff --git a/vppinfra/vppinfra/bihash_8_8.h b/vppinfra/vppinfra/bihash_8_8.h
index 21cb59ad67c..221e1f25534 100644
--- a/vppinfra/vppinfra/bihash_8_8.h
+++ b/vppinfra/vppinfra/bihash_8_8.h
@@ -25,11 +25,15 @@
#include <vppinfra/pool.h>
#include <vppinfra/xxhash.h>
+/** 8 octet key, 8 octet key value pair */
typedef struct {
- u64 key;
- u64 value;
+ u64 key; /**< the key */
+ u64 value; /**< the value */
} clib_bihash_kv_8_8_t;
+/** Decide if a clib_bihash_kv_8_8_t instance is free
+ @param v- pointer to the (key,value) pair
+*/
static inline int clib_bihash_is_free_8_8 (clib_bihash_kv_8_8_t *v)
{
if (v->key == ~0ULL && v->value == ~0ULL)
@@ -37,11 +41,19 @@ static inline int clib_bihash_is_free_8_8 (clib_bihash_kv_8_8_t *v)
return 0;
}
+/** Hash a clib_bihash_kv_8_8_t instance
+ @param v - pointer to the (key,value) pair, hash the key (only)
+*/
static inline u64 clib_bihash_hash_8_8 (clib_bihash_kv_8_8_t *v)
{
return clib_xxhash (v->key);
}
+/** Format a clib_bihash_kv_8_8_t instance
+ @param s - u8 * vector under construction
+ @param v (vararg) - the (key,value) pair to format
+ @return s - the u8 * vector under construction
+*/
static inline u8 * format_bihash_kvp_8_8 (u8 * s, va_list * args)
{
clib_bihash_kv_8_8_t * v = va_arg (*args, clib_bihash_kv_8_8_t *);
@@ -50,6 +62,10 @@ static inline u8 * format_bihash_kvp_8_8 (u8 * s, va_list * args)
return s;
}
+/** Compare two clib_bihash_kv_8_8_t instances
+ @param a - first key
+ @param b - second key
+*/
static inline int clib_bihash_key_compare_8_8 (u64 a, u64 b)
{
return a == b;
diff --git a/vppinfra/vppinfra/bihash_doc.h b/vppinfra/vppinfra/bihash_doc.h
new file mode 100644
index 00000000000..037e7cc90e6
--- /dev/null
+++ b/vppinfra/vppinfra/bihash_doc.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014 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.
+*/
+
+#error do not #include this file!
+
+/** \file
+
+ Bounded-index extensible hashing. The basic algorithm performs
+ thread-safe constant-time lookups in the face of a rational number
+ of hash collisions. The computed hash code h(k) must have
+ reasonable statistics with respect to the key space. It won't do
+ to have h(k) = 0 or 1, for all values of k.
+
+ Each bucket in the power-of-two bucket array contains the index
+ (in a private vppinfra memory heap) of the "backing store" for the
+ bucket, as well as a size field. The size field (log2_pages)
+ corresponds to 1, 2, 4, ... contiguous "pages" containing the
+ (key,value) pairs in the bucket.
+
+ When a single page fills, we allocate two contiguous pages. We
+ recompute h(k) for each (key,value) pair, using an additional bit
+ to deal the (key, value) pairs into the "top" and "bottom" pages.
+
+ At lookup time, we compute h(k), using lg(bucket-array-size) to
+ pick the bucket. We read the bucket to find the base of the
+ backing pages. We use an additional log2_pages' worth of bits
+ from h(k) to compute the offset of the page which will contain the
+ (key,value) pair we're trying to find.
+*/
+
+/** template key/value backing page structure */
+typedef struct clib_bihash_value {
+ union {
+
+ clib_bihash_kv kvp[BIHASH_KVP_PER_PAGE]; /**< the actual key/value pairs */
+ clib_bihash_value * next_free; /**< used when a KVP page (or block thereof) is on a freelist */
+ };
+} clib_bihash_value_t
+
+/** bihash bucket structure */
+typedef struct {
+ union {
+ struct {
+ u32 offset; /**< backing page offset in the clib memory heap */
+ u8 pad[3]; /**< log2 (size of the packing page block) */
+ u8 log2_pages;
+ };
+ u64 as_u64;
+ };
+} clib_bihash_bucket_t;
+#endif /* __defined_clib_bihash_bucket_t__ */
+
+/** A bounded index extensible hash table */
+typedef struct {
+ clib_bihash_bucket_t * buckets; /**< Hash bucket vector, power-of-two in size */
+ volatile u32 * writer_lock; /**< Writer lock, in its own cache line */
+ BVT(clib_bihash_value) ** working_copies; /**< Working copies (various sizes), to avoid locking against readers */
+ clib_bihash_bucket_t saved_bucket; /**< Saved bucket pointer */
+ u32 nbuckets; /**< Number of hash buckets */
+ u32 log2_nbuckets; /**< lg(nbuckets) */
+ u8 * name; /**< hash table name */
+ BVT(clib_bihash_value) **freelists; /**< power of two freelist vector */
+ void * mheap; /**< clib memory heap */
+} clib_bihash_t;
+
+/** Get pointer to value page given its clib mheap offset */
+static inline void *
+clib_bihash_get_value (clib_bihash * h, uword offset);
+
+/** Get clib mheap offset given a pointer */
+static inline uword clib_bihash_get_offset (clib_bihash * h, void * v);
+
+/** initialize a bounded index extensible hash table
+
+ @param h - the bi-hash table to initialize
+ @param name - name of the hash table
+ @param nbuckets - the number of buckets, will be rounded up to
+a power of two
+ @param memory_size - clib mheap size, in bytes
+*/
+
+void clib_bihash_init
+(clib_bihash * h, char * name, u32 nbuckets, uword memory_size);
+
+/** Destroy a bounded index extensible hash table
+ @param h - the bi-hash table to free
+*/
+
+void clib_bihash_free (clib_bihash * h);
+
+/** Add or delete a (key,value) pair from a bi-hash table
+
+ @param h - the bi-hash table to search
+ @param add_kv - the (key,value) pair to add
+ @param is_add - add=1, delete=0
+ @returns 0 on success, < 0 on error
+ @note This function will replace an existing (key,value) pair if the
+ new key matches an existing key
+*/
+int clib_bihash_add_del (clib_bihash * h,
+ clib_bihash_kv * add_v,
+ int is_add);
+
+
+/** Search a bi-hash table
+
+ @param h - the bi-hash table to search
+ @param search_v - (key,value) pair containing the search key
+ @param return_v - (key,value) pair which matches search_v.key
+ @returns 0 on success (with return_v set), < 0 on error
+*/
+int clib_bihash_search (clib_bihash * h,
+ clib_bihash_kv * search_v,
+ clib_bihash_kv * return_v);
+
+
+/** Visit active (key,value) pairs in a bi-hash table
+
+ @param h - the bi-hash table to search
+ @param callback - function to call with each active (key,value) pair
+ @param arg - arbitrary second argument passed to the callback function
+ First argument is the (key,value) pair to visit
+ @note Trying to supply a proper function prototype for the
+ callback function appears to be a fool's errand.
+*/
+void clib_bihash_foreach_key_value_pair (clib_bihash) * h,
+ void *callback,
+ void *arg);
diff --git a/vppinfra/vppinfra/bihash_template.c b/vppinfra/vppinfra/bihash_template.c
index 35384a38067..0ee92c07570 100644
--- a/vppinfra/vppinfra/bihash_template.c
+++ b/vppinfra/vppinfra/bihash_template.c
@@ -13,6 +13,8 @@
* limitations under the License.
*/
+/** @if DOCUMENTATION_IS_IN_BIHASH_DOC_H */
+
void BV(clib_bihash_init)
(BVT(clib_bihash) * h, char * name, u32 nbuckets,
uword memory_size)
@@ -452,3 +454,5 @@ void BV(clib_bihash_foreach_key_value_pair)
}
}
}
+
+/** @endif */
diff --git a/vppinfra/vppinfra/bihash_template.h b/vppinfra/vppinfra/bihash_template.h
index b7968e75453..5f80e7af044 100644
--- a/vppinfra/vppinfra/bihash_template.h
+++ b/vppinfra/vppinfra/bihash_template.h
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+/** @if DOCUMENTATION_IS_IN_BIHASH_DOC_H */
+
/*
* Note: to instantiate the template multiple times in a single file,
* #undef __included_bihash_template_h__...
@@ -197,3 +199,5 @@ static inline int BV(clib_bihash_search_inline_2)
#endif /* __included_bihash_template_h__ */
+
+/** @endif */