[ltt-dev] Review of rculfhash
Paul E. McKenney
paulmck at linux.vnet.ibm.com
Tue Nov 1 09:20:39 EDT 2011
Hello!
Cool stuff!!! A few preliminary comments below, as always. Followed by
a patch for one thing that I am confident in.
Thanx, Paul
------------------------------------------------------------------------
urcu/rculfhash.h:
o A comment for each structure is needed, perhaps somthing like
the following:
_cds_lfht_node: Contains the internal pointers and reverse-hash
value required for traversal of the hash table.
cds_lfht_node: Contains the full key and length required to check
for an actual match, and also contains an rcu_head
structure that is used by RCU to track a node through
a given RCU grace period. There is an instance
of _cds_lfht_node enclosed as a field within each
_cds_lfht_node structure.
cds_lfht_iter: Used to track state while traversing a hash chain.
o So the _cds_lfht_new() is not to be called by ordinary users,
but the only call to it passes rcu_read_lock(). So the idea
is to permit use of any of the predefined RCU implementations,
and "void the warrantee" for any other usage? ;-)
Should there be an API member that returns whether or not
a resize is in progress? Or a callback that can be registered
to be invoked when resizes start and finish? This might allow
users to have greater control over priorities. (Note: This is
speculation on my part. Probably should demonstrated need
for this before providing it. Otherwise, gilded lilies and
all that.)
o Comment for cds_lfht_destroy() should state that attr may be
NULL if the caller does not want/need to be informed of the
value passed to cds_lfht_new().
o Comment for cds_lfht_count_nodes() should say what approx_before,
count, removed, and approx_after have to do with each other.
For example, a node is either counted in *count or in
*removed, but not both. Probably no need to mention dummy
nodes, as they are invisible to the caller. As near as I can
tell, *approx_before and *approx_after are both zero unless
debugging.
rculfhash.c:
o A comment for each structure is needed, perhaps somthing like
the following:
ht_items_count: Counters of additions and deletions used during
stress testing.
rcu_level: Array of pointers into the list. Each element of
this array is analogous to the hash-chain headers found
in other types of hash tables. Resizing a hash table
involves creating a new rcu_level array that replaces
the old array.
rcu_table: Reference to current rcu_level array. Includes
size and desired new size if a resize operation is
in progress.
But why isn't the size kept with the array? This would eliminate
many of the memory barriers, for example, the cmm_smp_wmb()
in init_table(), fini_table(), and the ones that should be
there that is not in cds_lfht_lookup() &c. Unless I am confused,
the current code allows one size to be used on another array.
(That said, not sure I yet understand the relationship of ->size
and the various arrays.)
cds_lfht: Top-level data structure representing a lock-free
hash table. Presumably defined in the .c file in
order to make it be an opaque cookie to users.
rcu_resize_work: ???
partition_resize_work: ???
o Cute trick for generating the bit-reversal table. ;-)
o fls_ulong(): Shouldn't the CAA_BITS_PER_lONG instead be
CAA_BITS_PER_LONG?
o What defines POISON_FREE? I don't see anything but #ifdefs
of it.
o Any chance of a comment saying what CDS_LFHT_ACCOUNTING does?
It seems to short-circuit ht_count_add() and ht_count_del().
Appears to be debug-only checks of addition/deletion counts.
o lookup_bucket()
o ht_count_add() is interesting in that it does not appear to
clear out ht->split_count[index].add. The places that read it
do not appear to mask the upper bits, either. A comment
explaining why this is legitimate?
Ditto for ht_count_del().
o cds_lfht_lookup() applies clear_flag() to the pointer twice.
Unless I am missing something, the clear_flag() in the "if"
statement in the loop can be omitted.
Also, the ->next value returned does have its flag bits set.
However, this seems to be necessary for cds_lfht_next_duplicate()
to work correctly.
o cds_lfht_next_duplicate() would be more clear if ->compare_fct()
was ->is_different() or some such. But I guess if that is an
obstacle, you probably shouldn't be looking at this stuff in the
first place.
Need to document what happens if an insertion of a
duplicate key happens between a cds_lfht_lookup() and a
cds_lfht_next_duplicate(). Looks to me like they will be seen.
tests/test_urcu_hash.c:
o test_compare() -- Why the return -1 if the keys are not equal in
length, but then fail an assert if not equal to size of unsigned
long?
------------------------------------------------------------------------
Fix CAA_BITS_PER_lONG typo
Should instead be CAA_BITS_PER_LONG.
Signed-off-by: Paul E. McKenney <paul.mckenney at linaro.org>
diff --git a/rculfhash.c b/rculfhash.c
index d786a3d..314cca8 100644
--- a/rculfhash.c
+++ b/rculfhash.c
@@ -454,7 +454,7 @@ unsigned int fls_u32(uint32_t x)
unsigned int fls_ulong(unsigned long x)
{
-#if (CAA_BITS_PER_lONG == 32)
+#if (CAA_BITS_PER_LONG == 32)
return fls_u32(x);
#else
return fls_u64(x);
More information about the lttng-dev
mailing list