7 #include <cdsannotate.h>
8 #include <specannotation.h>
9 #include <model_memory.h>
16 template <typename t_element, size_t t_size>
17 struct mpmc_boundq_1_alt
23 // elements should generally be cache-line-size padded :
24 t_element m_array[t_size];
26 // rdwr counts the reads & writes that have started
27 atomic<unsigned int> m_rdwr;
28 // "read" and "written" count the number completed
29 atomic<unsigned int> m_read;
30 atomic<unsigned int> m_written;
44 // For this we want MASK = 1; MASK wrap around
53 CLASS = mpmc_boundq_1_alt;
58 @Commutativity: Prepare <-> Prepare: _Method1.__RET__ !=
59 _Method2.__RET__ || !_Method1.__RET__ || !_Method2.__RET__
60 @Commutativity: Prepare <-> Publish: _Method1.__RET__ != _Method2.bin ||
62 @Commutativity: Prepare <-> Fetch: _Method1.__RET__ != _Method2.__RET__
63 || !_Method1.__RET__ || !_Method2.__RET__
64 @Commutativity: Prepare <-> Consume : _Method1.__RET__ != _Method2.bin || !_Method1.__RET__
66 @Commutativity: Publish <-> Publish: _Method1.bin != _Method2.bin
67 @Commutativity: Publish <-> Fetch: _Method1.bin != _Method2.__RET__ ||
69 @Commutativity: Publish <-> Consume : _Method1.bin != _Method2.bin
71 @Commutativity: Fetch <-> Fetch: _Method1.__RET__ != _Method2.__RET__ ||
72 !_Method1.__RET__ || !_Method2.__RET__
73 @Commutativity: Fetch <-> Consume : _Method1.__RET__ != _Method2.bin || !_Method1.__RET__
75 @Commutativity: Consume <-> Consume : _Method1.bin != _Method2.bin
80 //-----------------------------------------------------
85 @Commit_point_set: Fetch_RW_Load_Empty | Fetch_RW_RMW | Fetch_W_Load
86 @ID: (call_id_t) __RET__
87 //@Action: model_print("Fetch: %d\n", __RET__);
90 t_element * read_fetch() {
91 // Since we have a lool to CAS the value of m_rdwr, this can be relaxed
92 unsigned int rdwr = m_rdwr.load(mo_acquire);
93 //unsigned int rdwr = m_rdwr.load(mo_relaxed);
96 @Potential_commit_point_define: true
97 @Label: Fetch_Potential_RW_Load
102 rd = (rdwr>>16) & MASK;
105 if ( wr == rd ) { // empty
109 @Commit_point_define: true
110 @Potential_commit_point_label: Fetch_Potential_RW_Load
111 @Label: Fetch_RW_Load_Empty
118 /**** Inadmissibility (testcase2.cc, MASK = 1, size = 1) ****/
120 m_rdwr.compare_exchange_weak(rdwr,rdwr+(1<<16),mo_acq_rel);
123 @Commit_point_define_check: succ
136 /**** Inadmissibility ****/
137 int written = m_written.load(mo_acquire);
140 @Potential_commit_point_define: true
141 @Label: Fetch_Potential_W_Load
144 if ((written & MASK) != wr) {
147 printf("Fetch: m_written=%d\n", written);
154 @Commit_point_define: true
155 @Potential_commit_point_label: Fetch_Potential_W_Load
160 t_element * p = & ( m_array[ rd % t_size ] );
168 @Commit_point_set: Consume_R_RMW
170 //@Action: model_print("Consume: %d\n", bin);
173 void read_consume(t_element *bin) {
174 /**** Inadmissibility ****/
175 m_read.fetch_add(1,mo_release);
178 @Commit_point_define_check: true
179 @Label: Consume_R_RMW
184 //-----------------------------------------------------
189 @Commit_point_set: Prepare_RW_Load_Full | Prepare_RW_RMW | Prepare_R_Load
190 @ID: (call_id_t) __RET__
191 //@Action: model_print("Prepare: %d\n", __RET__);
194 t_element * write_prepare() {
195 // Try weaker semantics
196 // Since we have a lool to CAS the value of m_rdwr, this can be relaxed
197 unsigned int rdwr = m_rdwr.load(mo_acquire);
198 //unsigned int rdwr = m_rdwr.load(mo_relaxed);
201 @Potential_commit_point_define: true
202 @Label: Prepare_Potential_RW_Load
207 rd = (rdwr>>16) & MASK;
209 //printf("write_prepare: rd=%d, wr=%d\n", rd, wr);
211 if ( wr == ((rd + t_size)&MASK) ) { // full
215 @Commit_point_define: true
216 @Potential_commit_point_label: Prepare_Potential_RW_Load
217 @Label: Prepare_RW_Load_Full
223 /**** Inadmissibility (testcase3.cc, MASK = 1, size = 1) ****/
224 bool succ = m_rdwr.compare_exchange_weak(rdwr,(rd<<16) |
225 ((wr+1)&MASK),mo_acq_rel);
228 @Commit_point_define_check: succ
229 @Label: Prepare_RW_RMW
232 //printf("wr=%d\n", (wr+1)&MASK);
242 /**** Inadmissibility ****/
243 int read = m_read.load(mo_acquire);
246 @Potential_commit_point_define: true
247 @Label: Prepare_Potential_R_Load
250 if ((read & MASK) != rd)
258 @Commit_point_define: true
259 @Potential_commit_point_label: Prepare_Potential_R_Load
260 @Label: Prepare_R_Load
264 t_element * p = & ( m_array[ wr % t_size ] );
272 @Commit_point_set: Publish_W_RMW
274 //@Action: model_print("Publish: %d\n", bin);
277 void write_publish(t_element *bin)
279 /**** Inadmissibility ****/
280 int tmp = m_written.fetch_add(1,mo_release);
283 @Commit_point_define_check: true
284 @Label: Publish_W_RMW
287 printf("publish: m_written=%d\n", tmp + 1);
290 //-----------------------------------------------------