2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
4 * SPDX-License-Identifier: GPL-2.0-only
11 #include <urcu/compiler.h>
13 #include <common/common.h>
14 #include <common/defaults.h>
16 #include "hashtable.h"
19 /* seed_lock protects both seed_init and lttng_ht_seed. */
20 static pthread_mutex_t seed_lock
= PTHREAD_MUTEX_INITIALIZER
;
21 static bool seed_init
;
22 unsigned long lttng_ht_seed
;
24 static unsigned long min_hash_alloc_size
= 1;
25 static unsigned long max_hash_buckets_size
= 0;
28 * Getter/lookup functions need to be called with RCU read-side lock
29 * held. However, modification functions (add, add_unique, replace, del)
30 * take the RCU lock internally, so it does not matter whether the
31 * caller hold the RCU lock or not.
35 * Match function for string node.
37 static int match_str(struct cds_lfht_node
*node
, const void *key
)
39 struct lttng_ht_node_str
*match_node
=
40 caa_container_of(node
, struct lttng_ht_node_str
, node
);
42 return hash_match_key_str(match_node
->key
, (void *) key
);
46 * Match function for ulong node.
48 static int match_ulong(struct cds_lfht_node
*node
, const void *key
)
50 struct lttng_ht_node_ulong
*match_node
=
51 caa_container_of(node
, struct lttng_ht_node_ulong
, node
);
53 return hash_match_key_ulong((void *) match_node
->key
, (void *) key
);
57 * Match function for u64 node.
59 static int match_u64(struct cds_lfht_node
*node
, const void *key
)
61 struct lttng_ht_node_u64
*match_node
=
62 caa_container_of(node
, struct lttng_ht_node_u64
, node
);
64 return hash_match_key_u64(&match_node
->key
, (void *) key
);
68 * Match function for two uint64_t node.
70 static int match_two_u64(struct cds_lfht_node
*node
, const void *key
)
72 struct lttng_ht_node_two_u64
*match_node
=
73 caa_container_of(node
, struct lttng_ht_node_two_u64
, node
);
75 return hash_match_key_two_u64((void *) &match_node
->key
, (void *) key
);
79 const char *lttng_ht_type_str(enum lttng_ht_type type
)
82 case LTTNG_HT_TYPE_STRING
:
84 case LTTNG_HT_TYPE_ULONG
:
86 case LTTNG_HT_TYPE_U64
:
88 case LTTNG_HT_TYPE_TWO_U64
:
91 ERR("Unknown lttng hashtable type %d", type
);
97 * Return an allocated lttng hashtable.
99 struct lttng_ht
*lttng_ht_new(unsigned long size
, lttng_ht_type type
)
105 size
= DEFAULT_HT_SIZE
;
107 pthread_mutex_lock(&seed_lock
);
109 lttng_ht_seed
= (unsigned long) time(NULL
);
112 pthread_mutex_unlock(&seed_lock
);
114 ht
= (lttng_ht
*) zmalloc(sizeof(*ht
));
116 PERROR("zmalloc lttng_ht");
120 ht
->ht
= cds_lfht_new(size
, min_hash_alloc_size
, max_hash_buckets_size
,
121 CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, NULL
);
123 * There is already an assert in the RCU hashtable code so if the ht is
124 * NULL here there is a *huge* problem.
126 LTTNG_ASSERT(ht
->ht
);
129 case LTTNG_HT_TYPE_STRING
:
130 ht
->match_fct
= match_str
;
131 ht
->hash_fct
= hash_key_str
;
133 case LTTNG_HT_TYPE_ULONG
:
134 ht
->match_fct
= match_ulong
;
135 ht
->hash_fct
= hash_key_ulong
;
137 case LTTNG_HT_TYPE_U64
:
138 ht
->match_fct
= match_u64
;
139 ht
->hash_fct
= hash_key_u64
;
141 case LTTNG_HT_TYPE_TWO_U64
:
142 ht
->match_fct
= match_two_u64
;
143 ht
->hash_fct
= hash_key_two_u64
;
146 ERR("Unknown lttng hashtable type %d", type
);
147 lttng_ht_destroy(ht
);
151 DBG3("Created hashtable size %lu at %p of type %s", size
, ht
->ht
,
152 lttng_ht_type_str(type
));
161 * Free a lttng hashtable.
163 void lttng_ht_destroy(struct lttng_ht
*ht
)
167 ret
= cds_lfht_destroy(ht
->ht
, NULL
);
173 * Init lttng ht node string.
175 void lttng_ht_node_init_str(struct lttng_ht_node_str
*node
, char *key
)
180 cds_lfht_node_init(&node
->node
);
184 * Init lttng ht node unsigned long.
186 void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong
*node
,
192 cds_lfht_node_init(&node
->node
);
196 * Init lttng ht node uint64_t.
198 void lttng_ht_node_init_u64(struct lttng_ht_node_u64
*node
,
204 cds_lfht_node_init(&node
->node
);
208 * Init lttng ht node with two uint64_t.
210 void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64
*node
,
211 uint64_t key1
, uint64_t key2
)
215 node
->key
.key1
= key1
;
216 node
->key
.key2
= key2
;
217 cds_lfht_node_init(&node
->node
);
221 * Free lttng ht node string.
223 void lttng_ht_node_free_str(struct lttng_ht_node_str
*node
)
230 * Free lttng ht node unsigned long.
232 void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong
*node
)
239 * Free lttng ht node uint64_t.
241 void lttng_ht_node_free_u64(struct lttng_ht_node_u64
*node
)
248 * Free lttng ht node two uint64_t.
250 void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64
*node
)
257 * Lookup function in hashtable.
259 void lttng_ht_lookup(struct lttng_ht
*ht
, const void *key
,
260 struct lttng_ht_iter
*iter
)
263 LTTNG_ASSERT(ht
->ht
);
265 cds_lfht_lookup(ht
->ht
, ht
->hash_fct(key
, lttng_ht_seed
),
266 ht
->match_fct
, key
, &iter
->iter
);
270 * Add unique string node to hashtable.
272 void lttng_ht_add_unique_str(struct lttng_ht
*ht
,
273 struct lttng_ht_node_str
*node
)
275 struct cds_lfht_node
*node_ptr
;
277 LTTNG_ASSERT(ht
->ht
);
280 /* RCU read lock protects from ABA. */
282 node_ptr
= cds_lfht_add_unique(ht
->ht
, ht
->hash_fct(node
->key
, lttng_ht_seed
),
283 ht
->match_fct
, node
->key
, &node
->node
);
285 LTTNG_ASSERT(node_ptr
== &node
->node
);
289 * Add string node to hashtable.
291 void lttng_ht_add_str(struct lttng_ht
*ht
,
292 struct lttng_ht_node_str
*node
)
295 LTTNG_ASSERT(ht
->ht
);
298 /* RCU read lock protects from ABA. */
300 cds_lfht_add(ht
->ht
, ht
->hash_fct(node
->key
, lttng_ht_seed
),
306 * Add unsigned long node to hashtable.
308 void lttng_ht_add_ulong(struct lttng_ht
*ht
, struct lttng_ht_node_ulong
*node
)
311 LTTNG_ASSERT(ht
->ht
);
314 /* RCU read lock protects from ABA. */
316 cds_lfht_add(ht
->ht
, ht
->hash_fct((void *) node
->key
, lttng_ht_seed
),
322 * Add uint64_t node to hashtable.
324 void lttng_ht_add_u64(struct lttng_ht
*ht
, struct lttng_ht_node_u64
*node
)
327 LTTNG_ASSERT(ht
->ht
);
330 /* RCU read lock protects from ABA. */
332 cds_lfht_add(ht
->ht
, ht
->hash_fct(&node
->key
, lttng_ht_seed
),
338 * Add unique unsigned long node to hashtable.
340 void lttng_ht_add_unique_ulong(struct lttng_ht
*ht
,
341 struct lttng_ht_node_ulong
*node
)
343 struct cds_lfht_node
*node_ptr
;
345 LTTNG_ASSERT(ht
->ht
);
348 /* RCU read lock protects from ABA. */
350 node_ptr
= cds_lfht_add_unique(ht
->ht
,
351 ht
->hash_fct((void *) node
->key
, lttng_ht_seed
), ht
->match_fct
,
352 (void *) node
->key
, &node
->node
);
354 LTTNG_ASSERT(node_ptr
== &node
->node
);
358 * Add unique uint64_t node to hashtable.
360 void lttng_ht_add_unique_u64(struct lttng_ht
*ht
,
361 struct lttng_ht_node_u64
*node
)
363 struct cds_lfht_node
*node_ptr
;
365 LTTNG_ASSERT(ht
->ht
);
368 /* RCU read lock protects from ABA. */
370 node_ptr
= cds_lfht_add_unique(ht
->ht
,
371 ht
->hash_fct(&node
->key
, lttng_ht_seed
), ht
->match_fct
,
372 &node
->key
, &node
->node
);
374 LTTNG_ASSERT(node_ptr
== &node
->node
);
378 * Add unique two uint64_t node to hashtable.
380 void lttng_ht_add_unique_two_u64(struct lttng_ht
*ht
,
381 struct lttng_ht_node_two_u64
*node
)
383 struct cds_lfht_node
*node_ptr
;
385 LTTNG_ASSERT(ht
->ht
);
388 /* RCU read lock protects from ABA. */
390 node_ptr
= cds_lfht_add_unique(ht
->ht
,
391 ht
->hash_fct((void *) &node
->key
, lttng_ht_seed
), ht
->match_fct
,
392 (void *) &node
->key
, &node
->node
);
394 LTTNG_ASSERT(node_ptr
== &node
->node
);
398 * Add replace unsigned long node to hashtable.
400 struct lttng_ht_node_ulong
*lttng_ht_add_replace_ulong(struct lttng_ht
*ht
,
401 struct lttng_ht_node_ulong
*node
)
403 struct cds_lfht_node
*node_ptr
;
405 LTTNG_ASSERT(ht
->ht
);
408 /* RCU read lock protects from ABA. */
410 node_ptr
= cds_lfht_add_replace(ht
->ht
,
411 ht
->hash_fct((void *) node
->key
, lttng_ht_seed
), ht
->match_fct
,
412 (void *) node
->key
, &node
->node
);
417 return caa_container_of(node_ptr
, struct lttng_ht_node_ulong
, node
);
419 LTTNG_ASSERT(node_ptr
== &node
->node
);
423 * Add replace unsigned long node to hashtable.
425 struct lttng_ht_node_u64
*lttng_ht_add_replace_u64(struct lttng_ht
*ht
,
426 struct lttng_ht_node_u64
*node
)
428 struct cds_lfht_node
*node_ptr
;
430 LTTNG_ASSERT(ht
->ht
);
433 /* RCU read lock protects from ABA. */
435 node_ptr
= cds_lfht_add_replace(ht
->ht
,
436 ht
->hash_fct(&node
->key
, lttng_ht_seed
), ht
->match_fct
,
437 &node
->key
, &node
->node
);
442 return caa_container_of(node_ptr
, struct lttng_ht_node_u64
, node
);
444 LTTNG_ASSERT(node_ptr
== &node
->node
);
448 * Delete node from hashtable.
450 int lttng_ht_del(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
455 LTTNG_ASSERT(ht
->ht
);
458 /* RCU read lock protects from ABA. */
460 ret
= cds_lfht_del(ht
->ht
, iter
->iter
.node
);
466 * Get first node in the hashtable.
468 void lttng_ht_get_first(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
471 LTTNG_ASSERT(ht
->ht
);
474 cds_lfht_first(ht
->ht
, &iter
->iter
);
478 * Get next node in the hashtable.
480 void lttng_ht_get_next(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
483 LTTNG_ASSERT(ht
->ht
);
486 cds_lfht_next(ht
->ht
, &iter
->iter
);
490 * Return the number of nodes in the hashtable.
492 unsigned long lttng_ht_get_count(struct lttng_ht
*ht
)
498 LTTNG_ASSERT(ht
->ht
);
500 /* RCU read lock protects from ABA and allows RCU traversal. */
502 cds_lfht_count_nodes(ht
->ht
, &scb
, &count
, &sca
);
509 * Return lttng ht string node from iterator.
511 struct lttng_ht_node_str
*lttng_ht_iter_get_node_str(
512 struct lttng_ht_iter
*iter
)
514 struct cds_lfht_node
*node
;
517 node
= cds_lfht_iter_get_node(&iter
->iter
);
521 return caa_container_of(node
, struct lttng_ht_node_str
, node
);
525 * Return lttng ht unsigned long node from iterator.
527 struct lttng_ht_node_ulong
*lttng_ht_iter_get_node_ulong(
528 struct lttng_ht_iter
*iter
)
530 struct cds_lfht_node
*node
;
533 node
= cds_lfht_iter_get_node(&iter
->iter
);
537 return caa_container_of(node
, struct lttng_ht_node_ulong
, node
);
541 * Return lttng ht unsigned long node from iterator.
543 struct lttng_ht_node_u64
*lttng_ht_iter_get_node_u64(
544 struct lttng_ht_iter
*iter
)
546 struct cds_lfht_node
*node
;
549 node
= cds_lfht_iter_get_node(&iter
->iter
);
553 return caa_container_of(node
, struct lttng_ht_node_u64
, node
);
557 * Return lttng ht stream and index id node from iterator.
559 struct lttng_ht_node_two_u64
*lttng_ht_iter_get_node_two_u64(
560 struct lttng_ht_iter
*iter
)
562 struct cds_lfht_node
*node
;
565 node
= cds_lfht_iter_get_node(&iter
->iter
);
569 return caa_container_of(node
, struct lttng_ht_node_two_u64
, node
);