xref: /freebsd/sys/contrib/ck/include/ck_ht.h (revision 1fb62fb0)
1*1fb62fb0SOlivier Houchard /*
2*1fb62fb0SOlivier Houchard  * Copyright 2012-2015 Samy Al Bahra.
3*1fb62fb0SOlivier Houchard  * All rights reserved.
4*1fb62fb0SOlivier Houchard  *
5*1fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
6*1fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
7*1fb62fb0SOlivier Houchard  * are met:
8*1fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
9*1fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
10*1fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
11*1fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
12*1fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
13*1fb62fb0SOlivier Houchard  *
14*1fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*1fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*1fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*1fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*1fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*1fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*1fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*1fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*1fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*1fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*1fb62fb0SOlivier Houchard  * SUCH DAMAGE.
25*1fb62fb0SOlivier Houchard  */
26*1fb62fb0SOlivier Houchard 
27*1fb62fb0SOlivier Houchard #ifndef CK_HT_H
28*1fb62fb0SOlivier Houchard #define CK_HT_H
29*1fb62fb0SOlivier Houchard 
30*1fb62fb0SOlivier Houchard #include <ck_pr.h>
31*1fb62fb0SOlivier Houchard 
32*1fb62fb0SOlivier Houchard #define CK_F_HT
33*1fb62fb0SOlivier Houchard #if defined(CK_F_PR_LOAD_64) && defined(CK_F_PR_STORE_64)
34*1fb62fb0SOlivier Houchard #define CK_HT_TYPE uint64_t
35*1fb62fb0SOlivier Houchard #define CK_HT_TYPE_LOAD		ck_pr_load_64
36*1fb62fb0SOlivier Houchard #define CK_HT_TYPE_STORE 	ck_pr_store_64
37*1fb62fb0SOlivier Houchard #define CK_HT_TYPE_MAX		UINT64_MAX
38*1fb62fb0SOlivier Houchard #else
39*1fb62fb0SOlivier Houchard #define CK_HT_TYPE uint32_t
40*1fb62fb0SOlivier Houchard #define CK_HT_TYPE_LOAD		ck_pr_load_32
41*1fb62fb0SOlivier Houchard #define CK_HT_TYPE_STORE	ck_pr_store_32
42*1fb62fb0SOlivier Houchard #define CK_HT_TYPE_MAX		UINT32_MAX
43*1fb62fb0SOlivier Houchard #endif
44*1fb62fb0SOlivier Houchard 
45*1fb62fb0SOlivier Houchard 
46*1fb62fb0SOlivier Houchard #include <ck_cc.h>
47*1fb62fb0SOlivier Houchard #include <ck_malloc.h>
48*1fb62fb0SOlivier Houchard #include <ck_md.h>
49*1fb62fb0SOlivier Houchard #include <ck_stdint.h>
50*1fb62fb0SOlivier Houchard #include <ck_stdbool.h>
51*1fb62fb0SOlivier Houchard #include <ck_stddef.h>
52*1fb62fb0SOlivier Houchard 
53*1fb62fb0SOlivier Houchard struct ck_ht_hash {
54*1fb62fb0SOlivier Houchard 	uint64_t value;
55*1fb62fb0SOlivier Houchard };
56*1fb62fb0SOlivier Houchard typedef struct ck_ht_hash ck_ht_hash_t;
57*1fb62fb0SOlivier Houchard 
58*1fb62fb0SOlivier Houchard #define CK_HT_MODE_DIRECT	1U
59*1fb62fb0SOlivier Houchard #define CK_HT_MODE_BYTESTRING	2U
60*1fb62fb0SOlivier Houchard #define CK_HT_WORKLOAD_DELETE	4U
61*1fb62fb0SOlivier Houchard 
62*1fb62fb0SOlivier Houchard #if defined(CK_MD_POINTER_PACK_ENABLE) && defined(CK_MD_VMA_BITS)
63*1fb62fb0SOlivier Houchard #define CK_HT_PP
64*1fb62fb0SOlivier Houchard #define CK_HT_KEY_LENGTH ((sizeof(void *) * 8) - CK_MD_VMA_BITS)
65*1fb62fb0SOlivier Houchard #define CK_HT_KEY_MASK   ((1U << CK_HT_KEY_LENGTH) - 1)
66*1fb62fb0SOlivier Houchard #else
67*1fb62fb0SOlivier Houchard #define CK_HT_KEY_LENGTH 65535U
68*1fb62fb0SOlivier Houchard #endif
69*1fb62fb0SOlivier Houchard 
70*1fb62fb0SOlivier Houchard struct ck_ht_entry {
71*1fb62fb0SOlivier Houchard #ifdef CK_HT_PP
72*1fb62fb0SOlivier Houchard 	uintptr_t key;
73*1fb62fb0SOlivier Houchard 	uintptr_t value CK_CC_PACKED;
74*1fb62fb0SOlivier Houchard } CK_CC_ALIGN(16);
75*1fb62fb0SOlivier Houchard #else
76*1fb62fb0SOlivier Houchard 	uintptr_t key;
77*1fb62fb0SOlivier Houchard 	uintptr_t value;
78*1fb62fb0SOlivier Houchard 	CK_HT_TYPE key_length;
79*1fb62fb0SOlivier Houchard 	CK_HT_TYPE hash;
80*1fb62fb0SOlivier Houchard } CK_CC_ALIGN(32);
81*1fb62fb0SOlivier Houchard #endif
82*1fb62fb0SOlivier Houchard typedef struct ck_ht_entry ck_ht_entry_t;
83*1fb62fb0SOlivier Houchard 
84*1fb62fb0SOlivier Houchard /*
85*1fb62fb0SOlivier Houchard  * The user is free to define their own stub values.
86*1fb62fb0SOlivier Houchard  */
87*1fb62fb0SOlivier Houchard #ifndef CK_HT_KEY_EMPTY
88*1fb62fb0SOlivier Houchard #define CK_HT_KEY_EMPTY		((uintptr_t)0)
89*1fb62fb0SOlivier Houchard #endif
90*1fb62fb0SOlivier Houchard 
91*1fb62fb0SOlivier Houchard #ifndef CK_HT_KEY_TOMBSTONE
92*1fb62fb0SOlivier Houchard #define CK_HT_KEY_TOMBSTONE	(~CK_HT_KEY_EMPTY)
93*1fb62fb0SOlivier Houchard #endif
94*1fb62fb0SOlivier Houchard 
95*1fb62fb0SOlivier Houchard /*
96*1fb62fb0SOlivier Houchard  * Hash callback function. First argument is updated to contain a hash value,
97*1fb62fb0SOlivier Houchard  * second argument is the key, third argument is key length and final argument
98*1fb62fb0SOlivier Houchard  * is the hash table seed value.
99*1fb62fb0SOlivier Houchard  */
100*1fb62fb0SOlivier Houchard typedef void ck_ht_hash_cb_t(ck_ht_hash_t *, const void *, size_t, uint64_t);
101*1fb62fb0SOlivier Houchard 
102*1fb62fb0SOlivier Houchard struct ck_ht_map;
103*1fb62fb0SOlivier Houchard struct ck_ht {
104*1fb62fb0SOlivier Houchard 	struct ck_malloc *m;
105*1fb62fb0SOlivier Houchard 	struct ck_ht_map *map;
106*1fb62fb0SOlivier Houchard 	unsigned int mode;
107*1fb62fb0SOlivier Houchard 	uint64_t seed;
108*1fb62fb0SOlivier Houchard 	ck_ht_hash_cb_t *h;
109*1fb62fb0SOlivier Houchard };
110*1fb62fb0SOlivier Houchard typedef struct ck_ht ck_ht_t;
111*1fb62fb0SOlivier Houchard 
112*1fb62fb0SOlivier Houchard struct ck_ht_stat {
113*1fb62fb0SOlivier Houchard 	uint64_t probe_maximum;
114*1fb62fb0SOlivier Houchard 	uint64_t n_entries;
115*1fb62fb0SOlivier Houchard };
116*1fb62fb0SOlivier Houchard 
117*1fb62fb0SOlivier Houchard struct ck_ht_iterator {
118*1fb62fb0SOlivier Houchard 	struct ck_ht_entry *current;
119*1fb62fb0SOlivier Houchard 	uint64_t offset;
120*1fb62fb0SOlivier Houchard };
121*1fb62fb0SOlivier Houchard typedef struct ck_ht_iterator ck_ht_iterator_t;
122*1fb62fb0SOlivier Houchard 
123*1fb62fb0SOlivier Houchard #define CK_HT_ITERATOR_INITIALIZER { NULL, 0 }
124*1fb62fb0SOlivier Houchard 
125*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_ht_iterator_init(struct ck_ht_iterator * iterator)126*1fb62fb0SOlivier Houchard ck_ht_iterator_init(struct ck_ht_iterator *iterator)
127*1fb62fb0SOlivier Houchard {
128*1fb62fb0SOlivier Houchard 
129*1fb62fb0SOlivier Houchard 	iterator->current = NULL;
130*1fb62fb0SOlivier Houchard 	iterator->offset = 0;
131*1fb62fb0SOlivier Houchard 	return;
132*1fb62fb0SOlivier Houchard }
133*1fb62fb0SOlivier Houchard 
134*1fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_ht_entry_empty(ck_ht_entry_t * entry)135*1fb62fb0SOlivier Houchard ck_ht_entry_empty(ck_ht_entry_t *entry)
136*1fb62fb0SOlivier Houchard {
137*1fb62fb0SOlivier Houchard 
138*1fb62fb0SOlivier Houchard 	return entry->key == CK_HT_KEY_EMPTY;
139*1fb62fb0SOlivier Houchard }
140*1fb62fb0SOlivier Houchard 
141*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_ht_entry_key_set_direct(ck_ht_entry_t * entry,uintptr_t key)142*1fb62fb0SOlivier Houchard ck_ht_entry_key_set_direct(ck_ht_entry_t *entry, uintptr_t key)
143*1fb62fb0SOlivier Houchard {
144*1fb62fb0SOlivier Houchard 
145*1fb62fb0SOlivier Houchard 	entry->key = key;
146*1fb62fb0SOlivier Houchard 	return;
147*1fb62fb0SOlivier Houchard }
148*1fb62fb0SOlivier Houchard 
149*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_ht_entry_key_set(ck_ht_entry_t * entry,const void * key,uint16_t key_length)150*1fb62fb0SOlivier Houchard ck_ht_entry_key_set(ck_ht_entry_t *entry, const void *key, uint16_t key_length)
151*1fb62fb0SOlivier Houchard {
152*1fb62fb0SOlivier Houchard 
153*1fb62fb0SOlivier Houchard #ifdef CK_HT_PP
154*1fb62fb0SOlivier Houchard 	entry->key = (uintptr_t)key | ((uintptr_t)key_length << CK_MD_VMA_BITS);
155*1fb62fb0SOlivier Houchard #else
156*1fb62fb0SOlivier Houchard 	entry->key = (uintptr_t)key;
157*1fb62fb0SOlivier Houchard 	entry->key_length = key_length;
158*1fb62fb0SOlivier Houchard #endif
159*1fb62fb0SOlivier Houchard 
160*1fb62fb0SOlivier Houchard 	return;
161*1fb62fb0SOlivier Houchard }
162*1fb62fb0SOlivier Houchard 
163*1fb62fb0SOlivier Houchard CK_CC_INLINE static void *
ck_ht_entry_key(ck_ht_entry_t * entry)164*1fb62fb0SOlivier Houchard ck_ht_entry_key(ck_ht_entry_t *entry)
165*1fb62fb0SOlivier Houchard {
166*1fb62fb0SOlivier Houchard 
167*1fb62fb0SOlivier Houchard #ifdef CK_HT_PP
168*1fb62fb0SOlivier Houchard 	return (void *)(entry->key & (((uintptr_t)1 << CK_MD_VMA_BITS) - 1));
169*1fb62fb0SOlivier Houchard #else
170*1fb62fb0SOlivier Houchard 	return (void *)entry->key;
171*1fb62fb0SOlivier Houchard #endif
172*1fb62fb0SOlivier Houchard }
173*1fb62fb0SOlivier Houchard 
174*1fb62fb0SOlivier Houchard CK_CC_INLINE static uint16_t
ck_ht_entry_key_length(ck_ht_entry_t * entry)175*1fb62fb0SOlivier Houchard ck_ht_entry_key_length(ck_ht_entry_t *entry)
176*1fb62fb0SOlivier Houchard {
177*1fb62fb0SOlivier Houchard 
178*1fb62fb0SOlivier Houchard #ifdef CK_HT_PP
179*1fb62fb0SOlivier Houchard 	return entry->key >> CK_MD_VMA_BITS;
180*1fb62fb0SOlivier Houchard #else
181*1fb62fb0SOlivier Houchard 	return entry->key_length;
182*1fb62fb0SOlivier Houchard #endif
183*1fb62fb0SOlivier Houchard }
184*1fb62fb0SOlivier Houchard 
185*1fb62fb0SOlivier Houchard CK_CC_INLINE static void *
ck_ht_entry_value(ck_ht_entry_t * entry)186*1fb62fb0SOlivier Houchard ck_ht_entry_value(ck_ht_entry_t *entry)
187*1fb62fb0SOlivier Houchard {
188*1fb62fb0SOlivier Houchard 
189*1fb62fb0SOlivier Houchard #ifdef CK_HT_PP
190*1fb62fb0SOlivier Houchard 	return (void *)(entry->value & (((uintptr_t)1 << CK_MD_VMA_BITS) - 1));
191*1fb62fb0SOlivier Houchard #else
192*1fb62fb0SOlivier Houchard 	return (void *)entry->value;
193*1fb62fb0SOlivier Houchard #endif
194*1fb62fb0SOlivier Houchard }
195*1fb62fb0SOlivier Houchard 
196*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_ht_entry_set(struct ck_ht_entry * entry,ck_ht_hash_t h,const void * key,uint16_t key_length,const void * value)197*1fb62fb0SOlivier Houchard ck_ht_entry_set(struct ck_ht_entry *entry,
198*1fb62fb0SOlivier Houchard 		ck_ht_hash_t h,
199*1fb62fb0SOlivier Houchard 		const void *key,
200*1fb62fb0SOlivier Houchard 		uint16_t key_length,
201*1fb62fb0SOlivier Houchard 		const void *value)
202*1fb62fb0SOlivier Houchard {
203*1fb62fb0SOlivier Houchard 
204*1fb62fb0SOlivier Houchard #ifdef CK_HT_PP
205*1fb62fb0SOlivier Houchard 	entry->key = (uintptr_t)key | ((uintptr_t)key_length << CK_MD_VMA_BITS);
206*1fb62fb0SOlivier Houchard 	entry->value = (uintptr_t)value | ((uintptr_t)(h.value >> 32) << CK_MD_VMA_BITS);
207*1fb62fb0SOlivier Houchard #else
208*1fb62fb0SOlivier Houchard 	entry->key = (uintptr_t)key;
209*1fb62fb0SOlivier Houchard 	entry->value = (uintptr_t)value;
210*1fb62fb0SOlivier Houchard 	entry->key_length = key_length;
211*1fb62fb0SOlivier Houchard 	entry->hash = h.value;
212*1fb62fb0SOlivier Houchard #endif
213*1fb62fb0SOlivier Houchard 
214*1fb62fb0SOlivier Houchard 	return;
215*1fb62fb0SOlivier Houchard }
216*1fb62fb0SOlivier Houchard 
217*1fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_ht_entry_set_direct(struct ck_ht_entry * entry,ck_ht_hash_t h,uintptr_t key,uintptr_t value)218*1fb62fb0SOlivier Houchard ck_ht_entry_set_direct(struct ck_ht_entry *entry,
219*1fb62fb0SOlivier Houchard 		       ck_ht_hash_t h,
220*1fb62fb0SOlivier Houchard 		       uintptr_t key,
221*1fb62fb0SOlivier Houchard 		       uintptr_t value)
222*1fb62fb0SOlivier Houchard {
223*1fb62fb0SOlivier Houchard 
224*1fb62fb0SOlivier Houchard 	entry->key = key;
225*1fb62fb0SOlivier Houchard 	entry->value = value;
226*1fb62fb0SOlivier Houchard 
227*1fb62fb0SOlivier Houchard #ifndef CK_HT_PP
228*1fb62fb0SOlivier Houchard 	entry->hash = h.value;
229*1fb62fb0SOlivier Houchard #else
230*1fb62fb0SOlivier Houchard 	(void)h;
231*1fb62fb0SOlivier Houchard #endif
232*1fb62fb0SOlivier Houchard 	return;
233*1fb62fb0SOlivier Houchard }
234*1fb62fb0SOlivier Houchard 
235*1fb62fb0SOlivier Houchard CK_CC_INLINE static uintptr_t
ck_ht_entry_key_direct(ck_ht_entry_t * entry)236*1fb62fb0SOlivier Houchard ck_ht_entry_key_direct(ck_ht_entry_t *entry)
237*1fb62fb0SOlivier Houchard {
238*1fb62fb0SOlivier Houchard 
239*1fb62fb0SOlivier Houchard 	return entry->key;
240*1fb62fb0SOlivier Houchard }
241*1fb62fb0SOlivier Houchard 
242*1fb62fb0SOlivier Houchard CK_CC_INLINE static uintptr_t
ck_ht_entry_value_direct(ck_ht_entry_t * entry)243*1fb62fb0SOlivier Houchard ck_ht_entry_value_direct(ck_ht_entry_t *entry)
244*1fb62fb0SOlivier Houchard {
245*1fb62fb0SOlivier Houchard 
246*1fb62fb0SOlivier Houchard 	return entry->value;
247*1fb62fb0SOlivier Houchard }
248*1fb62fb0SOlivier Houchard 
249*1fb62fb0SOlivier Houchard /*
250*1fb62fb0SOlivier Houchard  * Iteration must occur without any concurrent mutations on
251*1fb62fb0SOlivier Houchard  * the hash table.
252*1fb62fb0SOlivier Houchard  */
253*1fb62fb0SOlivier Houchard bool ck_ht_next(ck_ht_t *, ck_ht_iterator_t *, ck_ht_entry_t **entry);
254*1fb62fb0SOlivier Houchard 
255*1fb62fb0SOlivier Houchard void ck_ht_stat(ck_ht_t *, struct ck_ht_stat *);
256*1fb62fb0SOlivier Houchard void ck_ht_hash(ck_ht_hash_t *, ck_ht_t *, const void *, uint16_t);
257*1fb62fb0SOlivier Houchard void ck_ht_hash_direct(ck_ht_hash_t *, ck_ht_t *, uintptr_t);
258*1fb62fb0SOlivier Houchard bool ck_ht_init(ck_ht_t *, unsigned int, ck_ht_hash_cb_t *,
259*1fb62fb0SOlivier Houchard     struct ck_malloc *, CK_HT_TYPE, uint64_t);
260*1fb62fb0SOlivier Houchard void ck_ht_destroy(ck_ht_t *);
261*1fb62fb0SOlivier Houchard bool ck_ht_set_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *);
262*1fb62fb0SOlivier Houchard bool ck_ht_put_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *);
263*1fb62fb0SOlivier Houchard bool ck_ht_get_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *);
264*1fb62fb0SOlivier Houchard bool ck_ht_gc(struct ck_ht *, unsigned long, unsigned long);
265*1fb62fb0SOlivier Houchard bool ck_ht_grow_spmc(ck_ht_t *, CK_HT_TYPE);
266*1fb62fb0SOlivier Houchard bool ck_ht_remove_spmc(ck_ht_t *, ck_ht_hash_t, ck_ht_entry_t *);
267*1fb62fb0SOlivier Houchard bool ck_ht_reset_spmc(ck_ht_t *);
268*1fb62fb0SOlivier Houchard bool ck_ht_reset_size_spmc(ck_ht_t *, CK_HT_TYPE);
269*1fb62fb0SOlivier Houchard CK_HT_TYPE ck_ht_count(ck_ht_t *);
270*1fb62fb0SOlivier Houchard 
271*1fb62fb0SOlivier Houchard #endif /* CK_HT_H */
272