};
u64 as_u64;
};
+#if BIHASH_KVP_CACHE_SIZE > 0
BVT (clib_bihash_kv) cache[BIHASH_KVP_CACHE_SIZE];
+#endif
} BVT (clib_bihash_bucket);
typedef struct
static inline u8 BV (clib_bihash_get_lru) (BVT (clib_bihash_bucket) * b)
{
+#if BIHASH_KVP_CACHE_SIZE > 0
return (b->cache_lru >> (3 * (BIHASH_KVP_CACHE_SIZE - 1))) & 7;
+#else
+ return 0;
+#endif
}
static inline void BV (clib_bihash_reset_cache) (BVT (clib_bihash_bucket) * b)
{
+#if BIHASH_KVP_CACHE_SIZE > 0
u16 initial_lru_value;
memset (b->cache, 0xff, sizeof (b->cache));
initial_lru_value = (0 << 12) | (1 << 9) | (2 << 6) | (3 << 3) | (4 << 0);
b->cache_lru = initial_lru_value;
+#endif
}
-static inline void BV (clib_bihash_cache_enable_disable)
- (BVT (clib_bihash_bucket) * b, u8 enable)
+static inline int BV (clib_bihash_lock_bucket) (BVT (clib_bihash_bucket) * b)
{
BVT (clib_bihash_bucket) tmp_b;
+ u64 rv;
+
+ tmp_b.as_u64 = 0;
+ tmp_b.cache_lru = 1 << 15;
+
+ rv = __sync_fetch_and_or (&b->as_u64, tmp_b.as_u64);
+ tmp_b.as_u64 = rv;
+ /* Was already locked? */
+ if (tmp_b.cache_lru & (1 << 15))
+ return 0;
+ return 1;
+}
+
+static inline void BV (clib_bihash_unlock_bucket)
+ (BVT (clib_bihash_bucket) * b)
+{
+ BVT (clib_bihash_bucket) tmp_b;
+
tmp_b.as_u64 = b->as_u64;
- tmp_b.cache_lru &= 0x7FFF;
- tmp_b.cache_lru |= enable << 15;
+ tmp_b.cache_lru &= ~(1 << 15);
b->as_u64 = tmp_b.as_u64;
}
u32 bucket_index;
BVT (clib_bihash_value) * v;
BVT (clib_bihash_bucket) * b;
+#if BIHASH_KVP_CACHE_SIZE > 0
BVT (clib_bihash_kv) * kvp;
+#endif
int i, limit;
hash = BV (clib_bihash_hash) (key_result);
if (b->offset == 0)
return -1;
- /* Check the cache, if currently enabled */
- if (PREDICT_TRUE (b->cache_lru & (1 << 15)))
+#if BIHASH_KVP_CACHE_SIZE > 0
+ /* Check the cache, if not currently locked */
+ if (PREDICT_TRUE ((b->cache_lru & (1 << 15)) == 0))
{
limit = BIHASH_KVP_CACHE_SIZE;
kvp = b->cache;
}
}
}
+#endif
hash >>= h->log2_nbuckets;
{
if (BV (clib_bihash_key_compare) (v->kvp[i].key, key_result->key))
{
- u8 cache_slot;
*key_result = v->kvp[i];
- /* Shut off the cache */
- BV (clib_bihash_cache_enable_disable) (b, 0);
- CLIB_MEMORY_BARRIER ();
-
- cache_slot = BV (clib_bihash_get_lru) (b);
- b->cache[cache_slot] = v->kvp[i];
- BV (clib_bihash_update_lru) (b, cache_slot);
+#if BIHASH_KVP_CACHE_SIZE > 0
+ u8 cache_slot;
+ /* Try to lock the bucket */
+ if (BV (clib_bihash_lock_bucket) (b))
+ {
+ cache_slot = BV (clib_bihash_get_lru) (b);
+ b->cache[cache_slot] = v->kvp[i];
+ BV (clib_bihash_update_lru) (b, cache_slot);
- /* Reenable the cache */
- BV (clib_bihash_cache_enable_disable) (b, 1);
- h->cache_misses++;
+ /* Unlock the bucket */
+ BV (clib_bihash_unlock_bucket) (b);
+ h->cache_misses++;
+ }
+#endif
return 0;
}
}
u32 bucket_index;
BVT (clib_bihash_value) * v;
BVT (clib_bihash_bucket) * b;
+#if BIHASH_KVP_CACHE_SIZE > 0
BVT (clib_bihash_kv) * kvp;
+#endif
int i, limit;
ASSERT (valuep);
if (b->offset == 0)
return -1;
- /* Check the cache, if currently enabled */
- if (PREDICT_TRUE (b->cache_lru & (1 << 15)))
+ /* Check the cache, if currently unlocked */
+#if BIHASH_KVP_CACHE_SIZE > 0
+ if (PREDICT_TRUE ((b->cache_lru & (1 << 15)) == 0))
{
limit = BIHASH_KVP_CACHE_SIZE;
kvp = b->cache;
}
}
}
+#endif
hash >>= h->log2_nbuckets;
v = BV (clib_bihash_get_value) (h, b->offset);
{
if (BV (clib_bihash_key_compare) (v->kvp[i].key, search_key->key))
{
- u8 cache_slot;
*valuep = v->kvp[i];
- /* Shut off the cache */
- BV (clib_bihash_cache_enable_disable) (b, 0);
- CLIB_MEMORY_BARRIER ();
+#if BIHASH_KVP_CACHE_SIZE > 0
+ u8 cache_slot;
- cache_slot = BV (clib_bihash_get_lru) (b);
- b->cache[cache_slot] = v->kvp[i];
- BV (clib_bihash_update_lru) (b, cache_slot);
+ /* Try to lock the bucket */
+ if (BV (clib_bihash_lock_bucket) (b))
+ {
+ cache_slot = BV (clib_bihash_get_lru) (b);
+ b->cache[cache_slot] = v->kvp[i];
+ BV (clib_bihash_update_lru) (b, cache_slot);
- /* Reenable the cache */
- BV (clib_bihash_cache_enable_disable) (b, 1);
- h->cache_misses++;
+ /* Reenable the cache */
+ BV (clib_bihash_unlock_bucket) (b);
+ h->cache_misses++;
+ }
+#endif
return 0;
}
}