blob: ea0238ef146f84fe318e254dc5073be5a63d96ce [file] [log] [blame]
Austin Schuh20b2b082019-09-11 20:42:56 -07001#ifndef AOS_IPC_LIB_QUEUE_RACER_H_
2#define AOS_IPC_LIB_QUEUE_RACER_H_
3
Tyler Chatowbf0609c2021-07-31 16:13:27 -07004#include <cstring>
Austin Schuh20b2b082019-09-11 20:42:56 -07005
6#include "aos/ipc_lib/lockless_queue.h"
7
8namespace aos {
9namespace ipc_lib {
10
11struct ThreadState;
12
13// Class to test the queue by spinning up a bunch of writing threads and racing
14// them together to all write at once.
15class QueueRacer {
16 public:
Brian Silvermanfc0d2e82020-08-12 19:58:35 -070017 QueueRacer(LocklessQueue queue, int num_threads, uint64_t num_messages);
Austin Schuh20b2b082019-09-11 20:42:56 -070018
19 // Runs an iteration of the race.
20 //
21 // This spins up num_threads, each of which sends num_messages. These must
22 // both be able to fit in the queue without wrapping.
23 //
24 // Then, this reads back all the messages and confirms that all were received
25 // in order, and none were missed.
26 //
27 // If race_reads is set, start reading (and retry if data isn't ready yet)
28 // while writes are still happening.
29 //
30 // If wrap_writes is nonzero, write enough to overwrite old data. This
31 // necesitates a loser check at the end.
32 //
33 // If both are set, run an even looser test.
34 void RunIteration(bool race_reads, int write_wrap_count);
35
36 size_t CurrentIndex() {
Brian Silvermanfc0d2e82020-08-12 19:58:35 -070037 return LocklessQueueReader(queue_).LatestIndex().index();
Austin Schuh20b2b082019-09-11 20:42:56 -070038 }
39
40 private:
41 // Wipes the queue memory out so we get a clean start.
Brian Silvermanfc0d2e82020-08-12 19:58:35 -070042 void Reset() {
43 memset(queue_.memory(), 0, LocklessQueueMemorySize(queue_.config()));
44 }
Austin Schuh20b2b082019-09-11 20:42:56 -070045
46 // This is a separate method so that when all the ASSERT_* methods, we still
47 // clean up all the threads. Otherwise we get an assert on the way out of
48 // RunIteration instead of getting all the way back to gtest.
49 void CheckReads(bool race_reads, int write_wrap_count,
50 ::std::vector<ThreadState> *threads);
51
Brian Silvermanfc0d2e82020-08-12 19:58:35 -070052 LocklessQueue queue_;
Austin Schuh20b2b082019-09-11 20:42:56 -070053 const uint64_t num_threads_;
54 const uint64_t num_messages_;
55
56 // The overall number of writes executed will always be between the two of
57 // these. We can't atomically count writes, so we have to bound them.
58 //
59 // Number of writes about to be started.
60 ::std::atomic<uint64_t> started_writes_;
61 // Number of writes completed.
62 ::std::atomic<uint64_t> finished_writes_;
Austin Schuh20b2b082019-09-11 20:42:56 -070063};
64
65} // namespace ipc_lib
66} // namespace aos
67
68#endif // AOS_IPC_LIB_QUEUE_RACER_H_