tests: use SPDX identifiers
[urcu.git] / tests / benchmark / test_urcu_hash.h
CommitLineData
ce29b371
MJ
1// SPDX-FileCopyrightText: 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
2//
3// SPDX-License-Identifier: GPL-2.0-or-later
4
18ca7a5b
MD
5#ifndef _TEST_URCU_HASH_H
6#define _TEST_URCU_HASH_H
7
8/*
18ca7a5b 9 * Userspace RCU library - test program
18ca7a5b
MD
10 */
11
18ca7a5b
MD
12#include <stdio.h>
13#include <pthread.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/types.h>
17#include <sys/wait.h>
18#include <unistd.h>
19#include <stdio.h>
18ca7a5b
MD
20#include <errno.h>
21#include <signal.h>
22
01477510 23#include <urcu/assert.h>
bd252a04 24#include <urcu/tls-compat.h>
094c8c59 25#include <compat-rand.h>
94df6318 26#include "thread-id.h"
2650042a 27#include "../common/debug-yield.h"
18ca7a5b
MD
28
29#define DEFAULT_HASH_SIZE 32
30#define DEFAULT_MIN_ALLOC_SIZE 1
31#define DEFAULT_RAND_POOL 1000000
32
33/*
34 * Note: the hash seed should be a random value for hash tables
35 * targeting production environments to provide protection against
36 * denial of service attacks. We keep it a static value within this test
37 * program to compare identical benchmark runs.
38 */
39#define TEST_HASH_SEED 0x42UL
40
18ca7a5b
MD
41/* hardcoded number of CPUs */
42#define NR_CPUS 16384
43
44#ifdef POISON_FREE
45#define poison_free(ptr) \
46 do { \
47 memset(ptr, 0x42, sizeof(*(ptr))); \
48 free(ptr); \
49 } while (0)
50#else
51#define poison_free(ptr) free(ptr)
52#endif
53
18ca7a5b
MD
54#ifndef DYNAMIC_LINK_TEST
55#define _LGPL_SOURCE
56#else
57#define debug_yield_read()
58#endif
59#include <urcu-qsbr.h>
60#include <urcu/rculfhash.h>
61#include <urcu-call-rcu.h>
62
63struct wr_count {
64 unsigned long update_ops;
65 unsigned long add;
66 unsigned long add_exist;
67 unsigned long remove;
68};
69
bd252a04
MD
70extern DECLARE_URCU_TLS(unsigned int, rand_lookup);
71extern DECLARE_URCU_TLS(unsigned long, nr_add);
72extern DECLARE_URCU_TLS(unsigned long, nr_addexist);
73extern DECLARE_URCU_TLS(unsigned long, nr_del);
74extern DECLARE_URCU_TLS(unsigned long, nr_delnoent);
75extern DECLARE_URCU_TLS(unsigned long, lookup_fail);
76extern DECLARE_URCU_TLS(unsigned long, lookup_ok);
18ca7a5b
MD
77
78extern struct cds_lfht *test_ht;
79
80struct test_data {
81 int a;
82 int b;
83};
84
85struct lfht_test_node {
86 struct cds_lfht_node node;
87 void *key;
88 unsigned int key_len;
89 /* cache-cold for iteration */
90 struct rcu_head head;
91};
92
93static inline struct lfht_test_node *
94to_test_node(struct cds_lfht_node *node)
95{
96 return caa_container_of(node, struct lfht_test_node, node);
97}
98
99static inline
100void lfht_test_node_init(struct lfht_test_node *node, void *key,
101 size_t key_len)
102{
103 cds_lfht_node_init(&node->node);
104 node->key = key;
105 node->key_len = key_len;
106}
107
108static inline struct lfht_test_node *
109cds_lfht_iter_get_test_node(struct cds_lfht_iter *iter)
110{
111 return to_test_node(cds_lfht_iter_get_node(iter));
112}
113
114extern volatile int test_go, test_stop;
115
116extern unsigned long wdelay;
117
118extern unsigned long duration;
119
120/* read-side C.S. duration, in loops */
121extern unsigned long rduration;
122
123extern unsigned long init_hash_size;
124extern unsigned long min_hash_alloc_size;
125extern unsigned long max_hash_buckets_size;
126extern unsigned long init_populate;
127extern int opt_auto_resize;
128extern int add_only, add_unique, add_replace;
129extern const struct cds_lfht_mm_type *memory_backend;
130
131extern unsigned long init_pool_offset, lookup_pool_offset, write_pool_offset;
132extern unsigned long init_pool_size,
133 lookup_pool_size,
134 write_pool_size;
135extern int validate_lookup;
136
495913bf
MD
137extern unsigned long nr_hash_chains;
138
18ca7a5b
MD
139extern int count_pipe[2];
140
ab0aacbe 141static inline void loop_sleep(unsigned long loops)
18ca7a5b 142{
ab0aacbe 143 while (loops-- != 0)
18ca7a5b
MD
144 caa_cpu_relax();
145}
146
147extern int verbose_mode;
148
149#define printf_verbose(fmt, args...) \
150 do { \
151 if (verbose_mode) \
152 printf(fmt, ## args); \
153 } while (0)
154
155extern unsigned int cpu_affinities[NR_CPUS];
156extern unsigned int next_aff;
157extern int use_affinity;
158
159extern pthread_mutex_t affinity_mutex;
160
18ca7a5b
MD
161void set_affinity(void);
162
18ca7a5b
MD
163/*
164 * returns 0 if test should end.
165 */
166static inline int test_duration_write(void)
167{
168 return !test_stop;
169}
170
171static inline int test_duration_read(void)
172{
173 return !test_stop;
174}
175
bd252a04
MD
176extern DECLARE_URCU_TLS(unsigned long long, nr_writes);
177extern DECLARE_URCU_TLS(unsigned long long, nr_reads);
18ca7a5b
MD
178
179extern unsigned int nr_readers;
180extern unsigned int nr_writers;
181
182void rcu_copy_mutex_lock(void);
183void rcu_copy_mutex_unlock(void);
184
185/*
186 * Hash function
187 * Source: http://burtleburtle.net/bob/c/lookup3.c
188 * Originally Public Domain
189 */
190
191#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
192
193#define mix(a, b, c) \
194do { \
195 a -= c; a ^= rot(c, 4); c += b; \
196 b -= a; b ^= rot(a, 6); a += c; \
197 c -= b; c ^= rot(b, 8); b += a; \
198 a -= c; a ^= rot(c, 16); c += b; \
199 b -= a; b ^= rot(a, 19); a += c; \
200 c -= b; c ^= rot(b, 4); b += a; \
201} while (0)
202
203#define final(a, b, c) \
204{ \
205 c ^= b; c -= rot(b, 14); \
206 a ^= c; a -= rot(c, 11); \
207 b ^= a; b -= rot(a, 25); \
208 c ^= b; c -= rot(b, 16); \
209 a ^= c; a -= rot(c, 4);\
210 b ^= a; b -= rot(a, 14); \
211 c ^= b; c -= rot(b, 24); \
212}
213
214static inline __attribute__((unused))
215uint32_t hash_u32(
216 const uint32_t *k, /* the key, an array of uint32_t values */
217 size_t length, /* the length of the key, in uint32_ts */
218 uint32_t initval) /* the previous hash, or an arbitrary value */
219{
220 uint32_t a, b, c;
221
222 /* Set up the internal state */
223 a = b = c = 0xdeadbeef + (((uint32_t) length) << 2) + initval;
224
225 /*----------------------------------------- handle most of the key */
226 while (length > 3) {
227 a += k[0];
228 b += k[1];
229 c += k[2];
230 mix(a, b, c);
231 length -= 3;
232 k += 3;
233 }
234
235 /*----------------------------------- handle the last 3 uint32_t's */
236 switch (length) { /* all the case statements fall through */
8771d88d
MJ
237 case 3: c += k[2]; /* fall through */
238 case 2: b += k[1]; /* fall through */
18ca7a5b
MD
239 case 1: a += k[0];
240 final(a, b, c);
8771d88d 241 /* fall through */
18ca7a5b
MD
242 case 0: /* case 0: nothing left to add */
243 break;
244 }
245 /*---------------------------------------------- report the result */
246 return c;
247}
248
249static inline
250void hashword2(
251 const uint32_t *k, /* the key, an array of uint32_t values */
252 size_t length, /* the length of the key, in uint32_ts */
253 uint32_t *pc, /* IN: seed OUT: primary hash value */
254 uint32_t *pb) /* IN: more seed OUT: secondary hash value */
255{
256 uint32_t a, b, c;
257
258 /* Set up the internal state */
259 a = b = c = 0xdeadbeef + ((uint32_t) (length << 2)) + *pc;
260 c += *pb;
261
262 /*----------------------------------------- handle most of the key */
263 while (length > 3) {
264 a += k[0];
265 b += k[1];
266 c += k[2];
267 mix(a, b, c);
268 length -= 3;
269 k += 3;
270 }
271
272 /*----------------------------------- handle the last 3 uint32_t's */
273 switch (length) { /* all the case statements fall through */
447c9339
MJ
274 case 3: c += k[2]; /* fall through */
275 case 2: b += k[1]; /* fall through */
18ca7a5b
MD
276 case 1: a += k[0];
277 final(a, b, c);
447c9339 278 /* fall through */
18ca7a5b
MD
279 case 0: /* case 0: nothing left to add */
280 break;
281 }
282 /*---------------------------------------------- report the result */
283 *pc = c;
284 *pb = b;
285}
286
287#if (CAA_BITS_PER_LONG == 32)
288static inline
495913bf 289unsigned long test_hash_mix(const void *_key, size_t length, unsigned long seed)
18ca7a5b
MD
290{
291 unsigned int key = (unsigned int) _key;
292
01477510 293 urcu_posix_assert(length == sizeof(unsigned int));
18ca7a5b
MD
294 return hash_u32(&key, 1, seed);
295}
296#else
297static inline
495913bf 298unsigned long test_hash_mix(const void *_key, size_t length, unsigned long seed)
18ca7a5b
MD
299{
300 union {
301 uint64_t v64;
302 uint32_t v32[2];
303 } v;
304 union {
305 uint64_t v64;
306 uint32_t v32[2];
307 } key;
308
01477510 309 urcu_posix_assert(length == sizeof(unsigned long));
18ca7a5b
MD
310 v.v64 = (uint64_t) seed;
311 key.v64 = (uint64_t) _key;
312 hashword2(key.v32, 2, &v.v32[0], &v.v32[1]);
313 return v.v64;
314}
315#endif
316
495913bf
MD
317/*
318 * Hash function with nr_hash_chains != 0 for testing purpose only!
319 * Creates very long hash chains, deteriorating the hash table into a
320 * few linked lists, depending on the nr_hash_chains value. The purpose
321 * of this test is to check how the hash table behaves with hash chains
322 * containing different values, which is a rare case in a normal hash
323 * table.
324 */
325static inline
326unsigned long test_hash(const void *_key, size_t length,
327 unsigned long seed)
328{
329 if (nr_hash_chains == 0) {
330 return test_hash_mix(_key, length, seed);
331 } else {
332 unsigned long v;
333
01477510 334 urcu_posix_assert(length == sizeof(unsigned long));
495913bf
MD
335 v = (unsigned long) _key;
336 return v % nr_hash_chains;
337 }
338}
339
18ca7a5b
MD
340unsigned long test_compare(const void *key1, size_t key1_len,
341 const void *key2, size_t key2_len);
342
343static inline
344int test_match(struct cds_lfht_node *node, const void *key)
345{
346 struct lfht_test_node *test_node = to_test_node(node);
347
348 return !test_compare(test_node->key, test_node->key_len,
349 key, sizeof(unsigned long));
350}
351
352static inline
353void cds_lfht_test_lookup(struct cds_lfht *ht, void *key, size_t key_len,
354 struct cds_lfht_iter *iter)
355{
01477510 356 urcu_posix_assert(key_len == sizeof(unsigned long));
18ca7a5b
MD
357
358 cds_lfht_lookup(ht, test_hash(key, key_len, TEST_HASH_SEED),
359 test_match, key, iter);
360}
361
362void free_node_cb(struct rcu_head *head);
363
f52c1ef7
MD
364/* rw test */
365void test_hash_rw_sigusr1_handler(int signo);
366void test_hash_rw_sigusr2_handler(int signo);
367void *test_hash_rw_thr_reader(void *_count);
368void *test_hash_rw_thr_writer(void *_count);
369int test_hash_rw_populate_hash(void);
370
20adf780
MD
371/* unique test */
372void test_hash_unique_sigusr1_handler(int signo);
373void test_hash_unique_sigusr2_handler(int signo);
374void *test_hash_unique_thr_reader(void *_count);
375void *test_hash_unique_thr_writer(void *_count);
376int test_hash_unique_populate_hash(void);
377
18ca7a5b 378#endif /* _TEST_URCU_HASH_H */
This page took 0.083183 seconds and 4 git commands to generate.