decoupling lock free data structures from memory
play

Decoupling Lock-Free Data Structures from Memory Reclamation for - PowerPoint PPT Presentation

Decoupling Lock-Free Data Structures from Memory Reclamation for Static Analysis [POPL'19] Roland Meyer and Sebastian Wol ff TU Braunschweig, Germany Lock-free Queue (Michael&Scott) void dequeue() { Head a while (true) { head =


  1. Decoupling Lock-Free Data Structures from 
 Memory Reclamation for Static Analysis [POPL'19] Roland Meyer and Sebastian Wol ff TU Braunschweig, Germany

  2. Lock-free Queue (Michael&Scott) void dequeue() { Head a while (true) { head = Head; next = head -> next; b // ... if (CAS(Head, head, next)) { // leak head? c return; }}}

  3. Lock-free Queue (Michael&Scott) void dequeue() { Head a while (true) { 1 2 X head = Head; next = head -> next; b // ... if (CAS(Head, head, next)) { // leak head? c return; }}}

  4. Lock-free Queue (Michael&Scott) void dequeue() { Head head X a while (true) { 1 2 head = Head; X next = head -> next; b // ... if (CAS(Head, head, next)) { // leak head? c return; }}}

  5. Lock-free Queue (Michael&Scott) void dequeue() { head 1 Head head X a while (true) { head 2 head = Head; 1 2 X next = head -> next; b // ... if (CAS(Head, head, next)) { // leak head? c return; }}}

  6. Lock-free Queue (Michael&Scott) void dequeue() { head 1 Head head X a while (true) { head 2 head = Head; X next = head -> next; next 1 b next 2 // ... 1 2 if (CAS(Head, head, next)) { // leak head? c return; }}}

  7. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { head 2 head = Head; X next = head -> next; next 1 Head b next 2 // ... 2 if (CAS(Head, head, next)) { 1 // leak head? c return; }}}

  8. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { 2 head = Head; X next = head -> next; next 1 Head b // ... if (CAS(Head, head, next)) { 1 // leak head? c return; }}}

  9. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { head = Head; X next = head -> next; next 1 Head b head 2 // ... 2 if (CAS(Head, head, next)) { 1 // leak head? next 2 c return; }}}

  10. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { head = Head; X next = head -> next; next 1 b head 2 // ... if (CAS(Head, head, next)) { 1 2 // leak head? Head next 2 c return; }}}

  11. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { head = Head; X next = head -> next; next 1 b head 2 // ... if (CAS(Head, head, next)) { 1 2 delete head; Head next 2 c return; }}}

  12. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { head = Head; X next = head -> next; next 1 b head 2 // ... if (CAS(Head, head, next)) { delete head; Head next 2 c 1 2 return; }}}

  13. Lock-free Queue (Michael&Scott) void dequeue() { head 1 head X a while (true) { head = Head; X next = head -> next; next 1 b head 2 // ... if (CAS(Head, head, next)) { delete head; Head next 2 c 1 2 return; }}}

  14. Reclamation • Lock-free data structures (LFDS) ➡ unsynchronized traversal ➡ threads cannot detect whether a dereference is safe • Safe memory reclamation (SMR) ➡ defers deletion until it is safe ➡ controlled by LFDS ➡ various sophisticated techniques exist

  15. Lock-free Queue (Michael&Scott) data_t dequeue() { Head a while (true) { 1 X head = Head; protect(head); next = head -> next; b // ... if (CAS(Head, head, next)) { retire(head); c return; }}}

  16. Lock-free Queue (Michael&Scott) data_t dequeue() { Head head X a while (true) { 1 head = Head; protect(head); X next = head -> next; b // ... if (CAS(Head, head, next)) { retire(head); c return; }}}

  17. Lock-free Queue (Michael&Scott) data_t dequeue() { X Head head X a while (true) { 1 head = Head; protect(head); X next = head -> next; b // ... if (CAS(Head, head, next)) { retire(head); c return; }}}

  18. Lock-free Queue (Michael&Scott) data_t dequeue() { head 1 X Head head X a while (true) { head = Head; protect(head); 1 X next = head -> next; b // ... if (CAS(Head, head, next)) { retire(head); c return; }}}

  19. Lock-free Queue (Michael&Scott) data_t dequeue() { head 1 X Head head X a while (true) { head = Head; protect(head); 1 X next = head -> next; b // ... if (CAS(Head, head, next)) { retire(head); c return; }}}

  20. Lock-free Queue (Michael&Scott) data_t dequeue() { head 1 X head X a while (true) { head = Head; protect(head); next 1 X next = head -> next; Head b // ... if (CAS(Head, head, next)) { 1 retire(head); c return; }}}

  21. Lock-free Queue (Michael&Scott) Z Z Z data_t dequeue() { head 1 X head X a while (true) { head = Head; protect(head); next 1 X next = head -> next; Head b // ... if (CAS(Head, head, next)) { retire(head); c 1 return; }}}

  22. Lock-free Queue (Michael&Scott) Z Z Z data_t dequeue() { head 1 X a while (true) { X head = Head; protect(head); next 1 next = head -> next; Head b // ... if (CAS(Head, head, next)) { retire(head); c 1 return; }}}

  23. Lock-free Queue (Michael&Scott) Z Z Z data_t dequeue() { head 1 X a while (true) { head = Head; protect(head); X next 1 next = head -> next; Head head X b // ... if (CAS(Head, head, next)) { retire(head); c 1 return; }}}

  24. Lock-free Queue (Michael&Scott) Z Z Z data_t dequeue() { head 1 a while (true) { head = Head; protect(head); next 1 X X next = head -> next; Head head X b // ... if (CAS(Head, head, next)) { retire(head); c 1 return; }}}

  25. Lock-free Queue (Michael&Scott) data_t dequeue() { head 1 a while (true) { head = Head; protect(head); next 1 X X next = head -> next; Head head X b // ... if (CAS(Head, head, next)) { retire(head); c 1 return; }}}

  26. State-of-the-art Verification of Data Structures • Pen&paper, mechanized/tool-supported ➡ require deep understanding of proof technique, LFDS, and SMR ➡ few works consider reclamation • Automated (model-checking) ➡ only done for GC ➡ or custom semantics (allowing accesses of deleted memory) ➡ no works consider SMR

  27. Verification LFDS+SMR struct Node { shared: void init() { data_t data; Node* Head; Head = new Node(); Node* node; Node* Tail; Head-> next = null; } Tail = Head; } void enqueue(data_t val) { data_t dequeue() { Node* node = new Node(); while (true) { node->data = val; Node* head = Head; GC Implementation node->next = null; while (true) { Node* tail = Tail; Node* tail = Tail; Node* next = head -> next; (automated verification possible) Node* next = tail -> next; if (Head != head) continue; if (Tail != tail) continue; if (head == tail) { if (next == null) { if (next == null) return empty_t; if (CAS(tail->next, null, node)) { else CAS(Tail, tail, next); CAS(Tail, tail, node); } else { } data = head -> data; } else { if (CAS(Head, head, next)) { CAS(Tail, tail, next); } return data; } } } } } 46 LOC }

  28. Verification LFDS+SMR struct Node { shared: void init() { data_t data; Node* Head; Head = new Node(); Node* node; Node* Tail; Head-> next = null; } Tail = Head; } void enqueue(data_t val) { data_t dequeue() { Node* node = new Node(); while (true) { node->data = val; Node* head = Head; node->next = null; protect(head, 0); while (true) { if (Head != head) continue; Node* tail = Tail; Node* tail = Tail; protect(tail, 0); Node* next = head -> next; if (Tail != tail) continue; protect(next, 1); Node* next = tail -> next; if (Head != head) continue; if (Tail != tail) continue; if (head == tail) { if (next == null) { if (next == null) return empty_t; if (CAS(tail->next, null, node)) { else CAS(Tail, tail, next); CAS(Tail, tail, node); } else { } data = head -> data; } else { if (CAS(Head, head, next)) { CAS(Tail, tail, next); retire(head); } return data; } } } } } 46+6 LOC }

Recommend


More recommend