While it is true that "serializing" instructions, like LOCK CMPXCHG will act like a fence, it won't act like a flush+fence which is what you need for a store barrier. Since there's no "compare-and-swap-and-flush" atomic instruction, the CMPXCHG only provides atomicity with respect to visibility, not persistence. Future systems that provide persistent CPU caches will make visibility and persistence the same thing, so LOCK CMPXCHG will work as expected even on pmem on those systems.
I've seem some code use flushes before each LOCK CMPXCHG to create the logic: If the CMPXCHG succeeds, I know the previous value was persistent and hasn't changed since I read it. This, coupled with a flush+fence after the LOCK CMPXCHG might meet the needs of some non-blocking algorithms, but I have to say I think the code is difficult to write, maintain, and not as useful as it may seem. Here's why I say that:
Imagine a non-blocking algorithm for adding a node to a linked list in DRAM. The algorithm allocates the new node, fills it in, and then uses CAS operations to link it in without grabbing traditional mutex locks. If the program crashes before the operation is complete, the memory allocated isn't a memory leak because it was all volatile and it goes back to the system when the program exits.
Now convert that algorithm to pmem. Even with the most carefully coded non-blocking code, you will need to handle the memory allocation in a way that avoids a persistent memory leak if the program crashes. Is it possible to do that with entirely non-blocking code? Perhaps. More likely you'd just use a transactional memory allocator like the one we have in libpmemobj. It has been tuned and optimized for several years now and provide a high-performing, crash safe allocator. But it uses transaction-style logic to do that (and other tricks like thread-local locks and caches to help it scale). So if the algorithm already uses a transaction to create the new node, why not just link in the new node in under that transaction instead of creating a complex non-blocking code path?
Of course, I'm not trying to discourage you from working on non-blocking pmem code, I'm just pointing out that in many of the cases we looked at, where someone was converting a non-blocking algorithm to work with pmem, just switching the code to use transactions often turned out to be much easier and still performant.
We've talked a few times about adding a CAS operation to PMDK. I'm still interested in hearing about specific use cases and I'm happy to see it get added if it makes sense. So far, the demand for it really hasn't been there, but I'm keeping an open mind about it.