Exploring Persistent Data Structure in Persistent Memory (PMem) for a Lock-Free Multi-Thread Security

  1. This paper introduces the problems and solutions of data visibility and consistency in PMem lock-free programming.
  2. This paper introduces a PR that is recently incorporated into libpmemobj-cpp by the author of this paper, which is a built-in Atomic Persistent Pointer for the convenience of realizing Single-Writer-Multiple-Reader (SWMR), a multi-threaded persistent data structure. You can refer to the discussion and development process of this PR here.
//Thread 1
//Pmem - > a is initialized to 0
atomic_ store(&pmem->a, 1); // Visibility: Yes, persistence: unknown
pmem_ persist(&pmem->a, sizeof(pmem->a)); // Visibility: Yes, persistence: Yes
//Thread 2
//Pmem - > b initialized to 0
if (atomic_load(&pmem->a) == 1) {
pmem - > b = 1; // visibility: Yes, persistence: unknown
pmem_persist (& pmem - > b, sizeof (pmem - > b)); // visibility: Yes, persistence: Yes
}
  1. If the program aborts before thread 1 starts, pmem -> a = 0, pmem -> b = 0
  2. If the program aborts after both threads are completed, pmem -> a = 1, pmem -> b = 1
  3. If the program aborts after thread 1 ends, pmem -> a = 1, pmem -> b = 0
Figure 1: Data Consistency Problem
//Thread 2
//pmem - > b initialized to 0
if (atomic_load(&pmem->a) == 1) {
pmem_persist (& pmem - > a, sizeof (pmem - > a)); // visibility: Yes, persistence: Yes
pmem - > b = 1; // visibility: Yes, persistence: unknown
pmem_persist (& pmem - > b, sizeof (pmem - > b)); // visibility: Yes, persistence: Yes
}
  • Modify the incoming self_relative_ptr address. Set the lowest bit to 1, indicating that the pointer is not persistent
  • The modified self_relative_ptr is written by atom and saved to the internal atomic object
  • The internal atomic object is obtained through atomic reading, self_relative_ptr
  • If this self_relative_ptr lowest value is 1, a persistent operation is performed, and CAS (compare and swap, an atomic operation supported by the standard atomic class, which is assigned when the condition is true) is used to clear the lowest PTR of self_relative_ptr in the internal atomic object
  • Returns the self_relative_ptr after the lowest bit is cleared
//Using the transaction of libpmemobj-cpp to allocate PMem objects can ensure no external memory leakage
self_relative_ptr<int> one;
try {
pmem::obj::transaction::run(pop, [&] {
one = nvobj::make_persistent<int>(); //allocate an int in PMem
*one = 1; //Set to 1
pmem_persist(one, sizeof(int)); //Persist
});
} catch (...) {
ASSERT_UNREACHABLE;
}
//Thread 1
atomic_ persistent_ aware_ ptr<int> a;
a.store(one); // Directly use the store function provided by atomic_persistent_aware_ptr
//Thread 2
atomic_ persistent_ aware_ ptr<int> b;
If (* (a.load()) = = 1) { // directly use the Load function provided by atomic_persistent_aware_ptr
b.store(one);
}

--

--

--

memark.io — Leveraging Modern Storage Architecture for System Enhancement

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

A Day in the Life of a Front End Developer

3 tricks Python of `lru_cache`

lru_cache pythoh

Creating A GitHub App to Validate IAM Policies

How to allow traffic out of service mesh by project

How to Install Docker Compose on CentOS7

[CRATOS] Token burn and mint

AZURE CLOUD PLATFORM BASED ON THE SHARED CLOUD ARCHITECTURE (Article 01)

The Open Graph Protocol

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
MemArk

MemArk

memark.io — Leveraging Modern Storage Architecture for System Enhancement

More from Medium

Guns, Germs and Databases

Promise Theory and the Container Supply Chain Model

Synapse setup PowerShell

C4E Chapter 15 — Presenting