1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2022 Ericsson AB
5 #include <rte_seqlock.h>
7 #include <rte_cycles.h>
8 #include <rte_malloc.h>
9 #include <rte_random.h>
19 uint64_t b __rte_cache_aligned;
20 uint64_t c __rte_cache_aligned;
21 } __rte_cache_aligned;
28 #define WRITER_RUNTIME 2.0 /* s */
30 #define WRITER_MAX_DELAY 100 /* us */
32 #define INTERRUPTED_WRITER_FREQUENCY 1000
33 #define WRITER_INTERRUPT_TIME 1 /* us */
38 struct data *data = arg;
41 deadline = rte_get_timer_cycles() +
42 WRITER_RUNTIME * rte_get_timer_hz();
44 while (rte_get_timer_cycles() < deadline) {
49 new_value = rte_rand();
51 interrupted = rte_rand_max(INTERRUPTED_WRITER_FREQUENCY) == 0;
53 rte_seqlock_write_lock(&data->lock);
59 rte_delay_us_block(WRITER_INTERRUPT_TIME);
63 rte_seqlock_write_unlock(&data->lock);
65 delay = rte_rand_max(WRITER_MAX_DELAY);
67 rte_delay_us_block(delay);
73 #define INTERRUPTED_READER_FREQUENCY 1000
74 #define READER_INTERRUPT_TIME 1000 /* us */
79 struct reader *r = arg;
80 int rc = TEST_SUCCESS;
82 while (__atomic_load_n(&r->stop, __ATOMIC_RELAXED) == 0 &&
84 struct data *data = r->data;
91 interrupted = rte_rand_max(INTERRUPTED_READER_FREQUENCY) == 0;
94 sn = rte_seqlock_read_begin(&data->lock);
98 rte_delay_us_block(READER_INTERRUPT_TIME);
102 } while (rte_seqlock_read_retry(&data->lock, sn));
104 if (a != b || b != c) {
105 printf("Reader observed inconsistent data values "
106 "%" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
116 reader_stop(struct reader *reader)
118 __atomic_store_n(&reader->stop, 1, __ATOMIC_RELAXED);
121 #define NUM_WRITERS 2 /* main lcore + one worker */
122 #define MIN_NUM_READERS 2
123 #define MIN_LCORE_COUNT (NUM_WRITERS + MIN_NUM_READERS)
125 /* Only a compile-time test */
126 static rte_seqlock_t __rte_unused static_init_lock = RTE_SEQLOCK_INITIALIZER;
131 struct reader readers[RTE_MAX_LCORE];
132 unsigned int num_lcores;
133 unsigned int num_readers;
136 unsigned int lcore_id;
137 unsigned int reader_lcore_ids[RTE_MAX_LCORE];
138 unsigned int worker_writer_lcore_id = 0;
139 int rc = TEST_SUCCESS;
141 num_lcores = rte_lcore_count();
143 if (num_lcores < MIN_LCORE_COUNT) {
144 printf("Too few cores to run test. Skipping.\n");
148 num_readers = num_lcores - NUM_WRITERS;
150 data = rte_zmalloc(NULL, sizeof(struct data), 0);
153 printf("Failed to allocate memory for seqlock data\n");
158 RTE_LCORE_FOREACH_WORKER(lcore_id) {
160 rte_eal_remote_launch(writer_run, data, lcore_id);
161 worker_writer_lcore_id = lcore_id;
163 unsigned int reader_idx = i - 1;
164 struct reader *reader = &readers[reader_idx];
169 rte_eal_remote_launch(reader_run, reader, lcore_id);
170 reader_lcore_ids[reader_idx] = lcore_id;
175 if (writer_run(data) != 0 ||
176 rte_eal_wait_lcore(worker_writer_lcore_id) != 0)
179 for (i = 0; i < num_readers; i++) {
180 reader_stop(&readers[i]);
181 if (rte_eal_wait_lcore(reader_lcore_ids[i]) != 0)
190 REGISTER_TEST_COMMAND(seqlock_autotest, test_seqlock);