2 * Copyright (C) 2011 EfficiOS Inc.
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
;
23 static unsigned long min_hash_alloc_size
= 1;
24 static unsigned long max_hash_buckets_size
= 0;
27 * Getter/lookup functions need to be called with RCU read-side lock
28 * held. However, modification functions (add, add_unique, replace, del)
29 * take the RCU lock internally, so it does not matter whether the
30 * caller hold the RCU lock or not.
34 * Match function for string node.
36 static int match_str(struct cds_lfht_node
*node
, const void *key
)
38 struct lttng_ht_node_str
*match_node
=
39 caa_container_of(node
, struct lttng_ht_node_str
, node
);
41 return hash_match_key_str(match_node
->key
, (void *) key
);
45 * Match function for ulong node.
47 static int match_ulong(struct cds_lfht_node
*node
, const void *key
)
49 struct lttng_ht_node_ulong
*match_node
=
50 caa_container_of(node
, struct lttng_ht_node_ulong
, node
);
52 return hash_match_key_ulong((void *) match_node
->key
, (void *) key
);
56 * Match function for u64 node.
58 static int match_u64(struct cds_lfht_node
*node
, const void *key
)
60 struct lttng_ht_node_u64
*match_node
=
61 caa_container_of(node
, struct lttng_ht_node_u64
, node
);
63 return hash_match_key_u64(&match_node
->key
, (void *) key
);
67 * Match function for two uint64_t node.
69 static int match_two_u64(struct cds_lfht_node
*node
, const void *key
)
71 struct lttng_ht_node_two_u64
*match_node
=
72 caa_container_of(node
, struct lttng_ht_node_two_u64
, node
);
74 return hash_match_key_two_u64((void *) &match_node
->key
, (void *) key
);
78 const char *lttng_ht_type_str(enum lttng_ht_type type
)
81 case LTTNG_HT_TYPE_STRING
:
83 case LTTNG_HT_TYPE_ULONG
:
85 case LTTNG_HT_TYPE_U64
:
87 case LTTNG_HT_TYPE_TWO_U64
:
90 ERR("Unknown lttng hashtable type %d", type
);
96 * Return an allocated lttng hashtable.
98 struct lttng_ht
*lttng_ht_new(unsigned long size
, lttng_ht_type type
)
104 size
= DEFAULT_HT_SIZE
;
106 pthread_mutex_lock(&seed_lock
);
108 lttng_ht_seed
= (unsigned long) time(NULL
);
111 pthread_mutex_unlock(&seed_lock
);
113 ht
= (lttng_ht
*) zmalloc(sizeof(*ht
));
115 PERROR("zmalloc lttng_ht");
119 ht
->ht
= cds_lfht_new(size
, min_hash_alloc_size
, max_hash_buckets_size
,
120 CDS_LFHT_AUTO_RESIZE
| CDS_LFHT_ACCOUNTING
, NULL
);
122 * There is already an assert in the RCU hashtable code so if the ht is
123 * NULL here there is a *huge* problem.
125 LTTNG_ASSERT(ht
->ht
);
128 case LTTNG_HT_TYPE_STRING
:
129 ht
->match_fct
= match_str
;
130 ht
->hash_fct
= hash_key_str
;
132 case LTTNG_HT_TYPE_ULONG
:
133 ht
->match_fct
= match_ulong
;
134 ht
->hash_fct
= hash_key_ulong
;
136 case LTTNG_HT_TYPE_U64
:
137 ht
->match_fct
= match_u64
;
138 ht
->hash_fct
= hash_key_u64
;
140 case LTTNG_HT_TYPE_TWO_U64
:
141 ht
->match_fct
= match_two_u64
;
142 ht
->hash_fct
= hash_key_two_u64
;
145 ERR("Unknown lttng hashtable type %d", type
);
146 lttng_ht_destroy(ht
);
150 DBG3("Created hashtable size %lu at %p of type %s", size
, ht
->ht
,
151 lttng_ht_type_str(type
));
160 * Free a lttng hashtable.
162 void lttng_ht_destroy(struct lttng_ht
*ht
)
166 ret
= cds_lfht_destroy(ht
->ht
, NULL
);
172 * Init lttng ht node string.
174 void lttng_ht_node_init_str(struct lttng_ht_node_str
*node
, char *key
)
179 cds_lfht_node_init(&node
->node
);
183 * Init lttng ht node unsigned long.
185 void lttng_ht_node_init_ulong(struct lttng_ht_node_ulong
*node
,
191 cds_lfht_node_init(&node
->node
);
195 * Init lttng ht node uint64_t.
197 void lttng_ht_node_init_u64(struct lttng_ht_node_u64
*node
,
203 cds_lfht_node_init(&node
->node
);
207 * Init lttng ht node with two uint64_t.
209 void lttng_ht_node_init_two_u64(struct lttng_ht_node_two_u64
*node
,
210 uint64_t key1
, uint64_t key2
)
214 node
->key
.key1
= key1
;
215 node
->key
.key2
= key2
;
216 cds_lfht_node_init(&node
->node
);
220 * Free lttng ht node string.
222 void lttng_ht_node_free_str(struct lttng_ht_node_str
*node
)
229 * Free lttng ht node unsigned long.
231 void lttng_ht_node_free_ulong(struct lttng_ht_node_ulong
*node
)
238 * Free lttng ht node uint64_t.
240 void lttng_ht_node_free_u64(struct lttng_ht_node_u64
*node
)
247 * Free lttng ht node two uint64_t.
249 void lttng_ht_node_free_two_u64(struct lttng_ht_node_two_u64
*node
)
256 * Lookup function in hashtable.
258 void lttng_ht_lookup(struct lttng_ht
*ht
, const void *key
,
259 struct lttng_ht_iter
*iter
)
262 LTTNG_ASSERT(ht
->ht
);
264 cds_lfht_lookup(ht
->ht
, ht
->hash_fct(key
, lttng_ht_seed
),
265 ht
->match_fct
, key
, &iter
->iter
);
269 * Add unique string node to hashtable.
271 void lttng_ht_add_unique_str(struct lttng_ht
*ht
,
272 struct lttng_ht_node_str
*node
)
274 struct cds_lfht_node
*node_ptr
;
276 LTTNG_ASSERT(ht
->ht
);
279 /* RCU read lock protects from ABA. */
281 node_ptr
= cds_lfht_add_unique(ht
->ht
, ht
->hash_fct(node
->key
, lttng_ht_seed
),
282 ht
->match_fct
, node
->key
, &node
->node
);
284 LTTNG_ASSERT(node_ptr
== &node
->node
);
288 * Add string node to hashtable.
290 void lttng_ht_add_str(struct lttng_ht
*ht
,
291 struct lttng_ht_node_str
*node
)
294 LTTNG_ASSERT(ht
->ht
);
297 /* RCU read lock protects from ABA. */
299 cds_lfht_add(ht
->ht
, ht
->hash_fct(node
->key
, lttng_ht_seed
),
305 * Add unsigned long node to hashtable.
307 void lttng_ht_add_ulong(struct lttng_ht
*ht
, struct lttng_ht_node_ulong
*node
)
310 LTTNG_ASSERT(ht
->ht
);
313 /* RCU read lock protects from ABA. */
315 cds_lfht_add(ht
->ht
, ht
->hash_fct((void *) node
->key
, lttng_ht_seed
),
321 * Add uint64_t node to hashtable.
323 void lttng_ht_add_u64(struct lttng_ht
*ht
, struct lttng_ht_node_u64
*node
)
326 LTTNG_ASSERT(ht
->ht
);
329 /* RCU read lock protects from ABA. */
331 cds_lfht_add(ht
->ht
, ht
->hash_fct(&node
->key
, lttng_ht_seed
),
337 * Add unique unsigned long node to hashtable.
339 void lttng_ht_add_unique_ulong(struct lttng_ht
*ht
,
340 struct lttng_ht_node_ulong
*node
)
342 struct cds_lfht_node
*node_ptr
;
344 LTTNG_ASSERT(ht
->ht
);
347 /* RCU read lock protects from ABA. */
349 node_ptr
= cds_lfht_add_unique(ht
->ht
,
350 ht
->hash_fct((void *) node
->key
, lttng_ht_seed
), ht
->match_fct
,
351 (void *) node
->key
, &node
->node
);
353 LTTNG_ASSERT(node_ptr
== &node
->node
);
357 * Add unique uint64_t node to hashtable.
359 void lttng_ht_add_unique_u64(struct lttng_ht
*ht
,
360 struct lttng_ht_node_u64
*node
)
362 struct cds_lfht_node
*node_ptr
;
364 LTTNG_ASSERT(ht
->ht
);
367 /* RCU read lock protects from ABA. */
369 node_ptr
= cds_lfht_add_unique(ht
->ht
,
370 ht
->hash_fct(&node
->key
, lttng_ht_seed
), ht
->match_fct
,
371 &node
->key
, &node
->node
);
373 LTTNG_ASSERT(node_ptr
== &node
->node
);
377 * Add unique two uint64_t node to hashtable.
379 void lttng_ht_add_unique_two_u64(struct lttng_ht
*ht
,
380 struct lttng_ht_node_two_u64
*node
)
382 struct cds_lfht_node
*node_ptr
;
384 LTTNG_ASSERT(ht
->ht
);
387 /* RCU read lock protects from ABA. */
389 node_ptr
= cds_lfht_add_unique(ht
->ht
,
390 ht
->hash_fct((void *) &node
->key
, lttng_ht_seed
), ht
->match_fct
,
391 (void *) &node
->key
, &node
->node
);
393 LTTNG_ASSERT(node_ptr
== &node
->node
);
397 * Add replace unsigned long node to hashtable.
399 struct lttng_ht_node_ulong
*lttng_ht_add_replace_ulong(struct lttng_ht
*ht
,
400 struct lttng_ht_node_ulong
*node
)
402 struct cds_lfht_node
*node_ptr
;
404 LTTNG_ASSERT(ht
->ht
);
407 /* RCU read lock protects from ABA. */
409 node_ptr
= cds_lfht_add_replace(ht
->ht
,
410 ht
->hash_fct((void *) node
->key
, lttng_ht_seed
), ht
->match_fct
,
411 (void *) node
->key
, &node
->node
);
416 return caa_container_of(node_ptr
, struct lttng_ht_node_ulong
, node
);
418 LTTNG_ASSERT(node_ptr
== &node
->node
);
422 * Add replace unsigned long node to hashtable.
424 struct lttng_ht_node_u64
*lttng_ht_add_replace_u64(struct lttng_ht
*ht
,
425 struct lttng_ht_node_u64
*node
)
427 struct cds_lfht_node
*node_ptr
;
429 LTTNG_ASSERT(ht
->ht
);
432 /* RCU read lock protects from ABA. */
434 node_ptr
= cds_lfht_add_replace(ht
->ht
,
435 ht
->hash_fct(&node
->key
, lttng_ht_seed
), ht
->match_fct
,
436 &node
->key
, &node
->node
);
441 return caa_container_of(node_ptr
, struct lttng_ht_node_u64
, node
);
443 LTTNG_ASSERT(node_ptr
== &node
->node
);
447 * Delete node from hashtable.
449 int lttng_ht_del(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
454 LTTNG_ASSERT(ht
->ht
);
457 /* RCU read lock protects from ABA. */
459 ret
= cds_lfht_del(ht
->ht
, iter
->iter
.node
);
465 * Get first node in the hashtable.
467 void lttng_ht_get_first(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
470 LTTNG_ASSERT(ht
->ht
);
473 cds_lfht_first(ht
->ht
, &iter
->iter
);
477 * Get next node in the hashtable.
479 void lttng_ht_get_next(struct lttng_ht
*ht
, struct lttng_ht_iter
*iter
)
482 LTTNG_ASSERT(ht
->ht
);
485 cds_lfht_next(ht
->ht
, &iter
->iter
);
489 * Return the number of nodes in the hashtable.
491 unsigned long lttng_ht_get_count(struct lttng_ht
*ht
)
497 LTTNG_ASSERT(ht
->ht
);
499 /* RCU read lock protects from ABA and allows RCU traversal. */
501 cds_lfht_count_nodes(ht
->ht
, &scb
, &count
, &sca
);
508 * Return lttng ht string node from iterator.
510 struct lttng_ht_node_str
*lttng_ht_iter_get_node_str(
511 struct lttng_ht_iter
*iter
)
513 struct cds_lfht_node
*node
;
516 node
= cds_lfht_iter_get_node(&iter
->iter
);
520 return caa_container_of(node
, struct lttng_ht_node_str
, node
);
524 * Return lttng ht unsigned long node from iterator.
526 struct lttng_ht_node_ulong
*lttng_ht_iter_get_node_ulong(
527 struct lttng_ht_iter
*iter
)
529 struct cds_lfht_node
*node
;
532 node
= cds_lfht_iter_get_node(&iter
->iter
);
536 return caa_container_of(node
, struct lttng_ht_node_ulong
, node
);
540 * Return lttng ht unsigned long node from iterator.
542 struct lttng_ht_node_u64
*lttng_ht_iter_get_node_u64(
543 struct lttng_ht_iter
*iter
)
545 struct cds_lfht_node
*node
;
548 node
= cds_lfht_iter_get_node(&iter
->iter
);
552 return caa_container_of(node
, struct lttng_ht_node_u64
, node
);
556 * Return lttng ht stream and index id node from iterator.
558 struct lttng_ht_node_two_u64
*lttng_ht_iter_get_node_two_u64(
559 struct lttng_ht_iter
*iter
)
561 struct cds_lfht_node
*node
;
564 node
= cds_lfht_iter_get_node(&iter
->iter
);
568 return caa_container_of(node
, struct lttng_ht_node_two_u64
, node
);