1919int TEST_DATA_R = 0xABBA ;
2020int TEST_DATA_W = 0xACDC ;
2121
22+ /* mock prepared to check negative case (simulate wrong implementation) */
23+ template <typename T>
24+ class mock_atomic_self_relative_ptr {
25+ public:
26+ using value_type = pmem::obj::experimental::self_relative_ptr<T>;
27+
28+ void
29+ store (value_type val)
30+ {
31+ ptr.store (val);
32+ pmem::obj::pool_by_vptr (this ).persist (&ptr, sizeof (ptr));
33+ }
34+
35+ value_type
36+ load ()
37+ {
38+ return ptr.load ();
39+ }
40+
41+ private:
42+ std::atomic<pmem::obj::experimental::self_relative_ptr<T>> ptr;
43+ };
44+
2245namespace nvobj = pmem::obj;
2346template <typename T>
2447using self_relative_ptr = nvobj::experimental::self_relative_ptr<T>;
@@ -31,9 +54,12 @@ struct root {
3154 atomic_ptr<int , std::true_type> ptr_r;
3255 /* write-optimized */
3356 atomic_ptr<int , std::false_type> ptr_w;
57+ /* mock for negative case */
58+ mock_atomic_self_relative_ptr<int > ptr_neg;
3459
3560 self_relative_ptr<int > read_r;
3661 self_relative_ptr<int > read_w;
62+ self_relative_ptr<int > read_neg;
3763};
3864
3965void
@@ -63,6 +89,29 @@ insert_and_read(nvobj::pool<root> &pop)
6389 });
6490}
6591
92+ void
93+ insert_and_read_mock (nvobj::pool<root> &pop)
94+ {
95+ parallel_xexec (
96+ 2 ,
97+ [&](size_t thread_id, std::function<void (void )> syncthreads) {
98+ syncthreads ();
99+ auto r = pop.root ();
100+
101+ if (thread_id == 0 ) {
102+ VALGRIND_PMC_EMIT_LOG (" PMREORDER_MARKER.BEGIN" );
103+ /* insert test data into mock atomic ptr */
104+ r->ptr_neg .store (
105+ reinterpret_cast <int *>(TEST_DATA_R));
106+ VALGRIND_PMC_EMIT_LOG (" PMREORDER_MARKER.END" );
107+ } else {
108+ /* read test data into self relative ptr */
109+ r->read_neg = r->ptr_neg .load ();
110+ pop.persist (r->read_neg .to_persistent_ptr ());
111+ }
112+ });
113+ }
114+
66115void
67116check_consistency (nvobj::pool<root> &pop)
68117{
@@ -77,11 +126,18 @@ check_consistency(nvobj::pool<root> &pop)
77126 r->ptr_r .load ().get () == r->read_r .get ());
78127}
79128
129+ void
130+ check_consistency_mock (nvobj::pool<root> &pop)
131+ {
132+ auto r = pop.root ();
133+ UT_ASSERT (r->ptr_neg .load ().get () == r->read_neg .get ());
134+ }
135+
80136static void
81137test (int argc, char *argv[])
82138{
83- if (argc != 3 || strchr (" cio " , argv[1 ][0 ]) == nullptr )
84- UT_FATAL (" usage: %s <c|i|o> file-name" , argv[0 ]);
139+ if (argc != 3 || strchr (" ciomn " , argv[1 ][0 ]) == nullptr )
140+ UT_FATAL (" usage: %s <c|i|o|m|n > file-name" , argv[0 ]);
85141
86142 const char *path = argv[2 ];
87143
@@ -99,6 +155,7 @@ test(int argc, char *argv[])
99155 pop.root ()->ptr_w = nullptr ;
100156 pop.root ()->read_r = nullptr ;
101157 pop.root ()->read_w = nullptr ;
158+ pop.root ()->read_neg = nullptr ;
102159 });
103160
104161 } else if (argv[1 ][0 ] == ' i' ) {
@@ -110,6 +167,16 @@ test(int argc, char *argv[])
110167 /* re-open at the end, for consistency check */
111168 pop = nvobj::pool<root>::open (path, LAYOUT);
112169 check_consistency (pop);
170+
171+ } else if (argv[1 ][0 ] == ' m' ) {
172+ /* mock store and load in parallel */
173+ pop = nvobj::pool<root>::open (path, LAYOUT);
174+ insert_and_read_mock (pop);
175+
176+ } else if (argv[1 ][0 ] == ' n' ) {
177+ /* re-open at the end, for negative consistency check */
178+ pop = nvobj::pool<root>::open (path, LAYOUT);
179+ check_consistency_mock (pop);
113180 }
114181 } catch (pmem::pool_error &pe) {
115182 UT_FATAL (" !pool::create: %s %s" , pe.what (), path);
0 commit comments