#include <syscall.h>
#endif
-#define HASH_SIZE 32
-#define RAND_POOL 10000
+#define DEFAULT_HASH_SIZE 32
+#define DEFAULT_RAND_POOL 1000000
/* Make this big enough to include the POWER5+ L3 cacheline size of 256B */
#define CACHE_LINE_SIZE 4096
static unsigned long __thread lookup_fail;
static unsigned long __thread lookup_ok;
-static struct rcu_ht *test_ht;
+static struct cds_lfht *test_ht;
struct test_data {
int a;
/* read-side C.S. duration, in loops */
static unsigned long rduration;
+static unsigned long init_hash_size = DEFAULT_HASH_SIZE;
+static unsigned long rand_pool = DEFAULT_RAND_POOL;
+static int add_only, add_unique;
+
static inline void loop_sleep(unsigned long l)
{
while(l-- != 0)
#define printf_verbose(fmt, args...) \
do { \
if (verbose_mode) \
- printf(fmt, args); \
+ printf(fmt, ## args); \
} while (0)
static unsigned int cpu_affinities[NR_CPUS];
void *thr_reader(void *_count)
{
unsigned long long *count = _count;
- struct rcu_ht_node *node;
+ struct cds_lfht_node *node;
printf_verbose("thread_begin %s, thread id : %lx, tid %lu\n",
"reader", pthread_self(), (unsigned long)gettid());
for (;;) {
rcu_read_lock();
- node = ht_lookup(test_ht,
- (void *)(unsigned long)(rand_r(&rand_lookup) % RAND_POOL),
+ node = cds_lfht_lookup(test_ht,
+ (void *)(unsigned long)(rand_r(&rand_lookup) % rand_pool),
sizeof(void *));
if (node == NULL)
lookup_fail++;
static
void free_node_cb(struct rcu_head *head)
{
- struct rcu_ht_node *node =
- caa_container_of(head, struct rcu_ht_node, head);
+ struct cds_lfht_node *node =
+ caa_container_of(head, struct cds_lfht_node, head);
free(node);
}
void *thr_writer(void *_count)
{
- struct rcu_ht_node *node;
+ struct cds_lfht_node *node, *ret_node;
struct wr_count *count = _count;
int ret;
cmm_smp_mb();
for (;;) {
- if (rand_r(&rand_lookup) & 1) {
- node = malloc(sizeof(struct rcu_ht_node));
+ if (add_only || rand_r(&rand_lookup) & 1) {
+ node = malloc(sizeof(struct cds_lfht_node));
rcu_read_lock();
- ht_node_init(node,
- (void *)(unsigned long)(rand_r(&rand_lookup) % RAND_POOL),
+ cds_lfht_node_init(node,
+ (void *)(unsigned long)(rand_r(&rand_lookup) % rand_pool),
sizeof(void *));
- ret = ht_add_unique(test_ht, node);
+ if (add_unique)
+ ret_node = cds_lfht_add_unique(test_ht, node);
+ else
+ cds_lfht_add(test_ht, node);
rcu_read_unlock();
- if (ret) {
+ if (add_unique && ret_node != node) {
free(node);
nr_addexist++;
} else
} else {
/* May delete */
rcu_read_lock();
- node = ht_lookup(test_ht,
- (void *)(unsigned long)(rand_r(&rand_lookup) % RAND_POOL),
+ node = cds_lfht_lookup(test_ht,
+ (void *)(unsigned long)(rand_r(&rand_lookup) % rand_pool),
sizeof(void *));
if (node)
- ret = ht_remove(test_ht, node);
+ ret = cds_lfht_remove(test_ht, node);
else
ret = -ENOENT;
rcu_read_unlock();
printf(" [-c duration] (reader C.S. duration (in loops))");
printf(" [-v] (verbose output)");
printf(" [-a cpu#] [-a cpu#]... (affinity)");
+ printf(" [-p size] (random key value pool size)");
+ printf(" [-h size] (initial hash table size)");
+ printf(" [-u] Uniquify add.");
+ printf(" [-i] Add only (no removal).");
printf("\n");
}
case 'v':
verbose_mode = 1;
break;
+ case 'p':
+ if (argc < i + 2) {
+ show_usage(argc, argv);
+ return -1;
+ }
+ rand_pool = atol(argv[++i]);
+ break;
+ case 'h':
+ if (argc < i + 2) {
+ show_usage(argc, argv);
+ return -1;
+ }
+ init_hash_size = atol(argv[++i]);
+ break;
+ case 'u':
+ add_unique = 1;
+ break;
+ case 'i':
+ add_only = 1;
+ break;
}
}
+ /* Check if hash size is power of 2 */
+ if (init_hash_size && init_hash_size & (init_hash_size - 1)) {
+ printf("Error: Hash table size %lu is not a power of 2.\n",
+ init_hash_size);
+ return -1;
+ }
+
printf_verbose("running test for %lu seconds, %u readers, %u writers.\n",
duration, nr_readers, nr_writers);
printf_verbose("Writer delay : %lu loops.\n", wdelay);
printf_verbose("Reader duration : %lu loops.\n", rduration);
+ printf_verbose("Random pool size : %lu.\n", rand_pool);
+ printf_verbose("Mode:%s%s.\n",
+ add_only ? " add only" : " add/remove",
+ add_unique ? " uniquify" : "");
+ printf_verbose("Initial hash table size: %lu buckets.\n", init_hash_size);
printf_verbose("thread %-6s, thread id : %lx, tid %lu\n",
"main", pthread_self(), (unsigned long)gettid());
tid_writer = malloc(sizeof(*tid_writer) * nr_writers);
count_reader = malloc(sizeof(*count_reader) * nr_readers);
count_writer = malloc(sizeof(*count_writer) * nr_writers);
- test_ht = ht_new(test_hash, test_compare, 0x42UL,
- HASH_SIZE, call_rcu);
+ test_ht = cds_lfht_new(test_hash, test_compare, 0x42UL,
+ init_hash_size, call_rcu);
+
+ err = create_all_cpu_call_rcu_data(0);
+ assert(!err);
+
next_aff = 0;
for (i = 0; i < nr_readers; i++) {
tot_add += count_writer[i].add;
tot_remove += count_writer[i].remove;
}
- ht_count_nodes(test_ht, &count, &removed);
+ printf("Counting nodes... ");
+ fflush(stdout);
+ cds_lfht_count_nodes(test_ht, &count, &removed);
+ printf("done.\n");
if (count || removed)
printf("WARNING: nodes left in the hash table upon destroy: "
"%lu nodes + %lu logically removed.\n", count, removed);
- (void) ht_destroy(test_ht);
+ ret = cds_lfht_destroy(test_ht);
- printf_verbose("final delete: %d items\n", ret);
+ if (ret)
+ printf_verbose("final delete aborted\n");
+ else
+ printf_verbose("final delete success\n");
printf_verbose("total number of reads : %llu, writes %llu\n", tot_reads,
tot_writes);
printf("SUMMARY %-25s testdur %4lu nr_readers %3u rdur %6lu "
"nr_writers %3u "
- "wdelay %6lu nr_reads %12llu nr_writes %12llu nr_ops %12llu "
+ "wdelay %6lu rand_pool %12llu nr_reads %12llu nr_writes %12llu nr_ops %12llu "
"nr_add %12llu nr_remove %12llu nr_leaked %12llu\n",
argv[0], duration, nr_readers, rduration,
- nr_writers, wdelay, tot_reads, tot_writes,
+ nr_writers, wdelay, rand_pool, tot_reads, tot_writes,
tot_reads + tot_writes, tot_add, tot_remove,
tot_add - tot_remove - count);
free(tid_reader);