@@ -404,6 +404,22 @@ mpsc_queue::worker::store_to_log(pmem::obj::string_view data, char *log_data)
404404 pmem::detail::CACHELINE_SIZE ==
405405 0 );
406406
407+ /* Invariant: producer can only produce data to cachelines which have
408+ * first 8 bytes zeroed.
409+ */
410+ #ifndef NDEBUG
411+ auto b = reinterpret_cast <first_block *>(log_data);
412+ auto s = pmem::detail::align_up (data.size () + sizeof (first_block::size),
413+ pmem::detail::CACHELINE_SIZE);
414+ auto e = b + s / pmem::detail::CACHELINE_SIZE;
415+ while (b < e) {
416+ assert (b->size == 0 );
417+ b++;
418+ }
419+ #endif
420+
421+ assert (reinterpret_cast <first_block *>(log_data)->size == 0 );
422+
407423 first_block fblock;
408424 fblock.size = data.size () | size_t (first_block::DIRTY_FLAG);
409425
@@ -591,21 +607,28 @@ mpsc_queue::read_accessor::iterator::skip_consumed(mpsc_queue::first_block *b)
591607 * size bytes are junk.
592608 * 3. First 8 bytes (size) are non-zero and have dirty flag unset - next
593609 * size bytes are ready to be consumed (they represent consistent data).
610+ *
611+ * Invariant: producer can only produce data to cachelines which have
612+ * first 8 bytes zeroed. If we detect that there was a crash during
613+ * producing data (DIRTY_FLAG is set) we must clear those cachline in
614+ * consume.
594615 */
595616 while (b < e) {
596617 if (b->size == 0 ) {
597618 b++;
598619 } else if (b->size & size_t (first_block::DIRTY_FLAG)) {
599- // XXX - we should clear the cachelines here!!!! (add
600- // test for this)
601-
602620 auto size =
603621 b->size & (~size_t (first_block::DIRTY_FLAG));
604622 auto aligned_size = pmem::detail::align_up (
605623 size + sizeof (b->size ),
606624 pmem::detail::CACHELINE_SIZE);
625+ auto e =
626+ b + aligned_size / pmem::detail::CACHELINE_SIZE;
607627
608- b += aligned_size / pmem::detail::CACHELINE_SIZE;
628+ while (b < e) {
629+ b->size = 0 ;
630+ b++;
631+ }
609632 } else {
610633 break ;
611634 }
0 commit comments