Lecture 28

11 Other approaches

11.1 Atomic (Lock-Free) Data-Structure

This is not a general solution.
There is some internal locking going on behind the scene.

11.1.1 Compare and Assign Instrcution

CAA basically says the following:

  • I want the val to be changed from comp to nval
  • when CAA routine is trying to assign nval to val,
    • if val is not comp, return false and fail the assignment
    • else, proceed and return true
int Lock = OPEN; // shared

bool CAA(int & val, int comp, int nval){
  //begin atomic
  if(val == comp){
    val = nval;
    return true;
  }
  return false;
  //end atomic
}

void Task::main(){
  while(!CAA(Lock, OPEN, CLOSEd));
  // critical section
  Lock = OPEN;
}

11.1.2 Lock-Free Stack

class Stack{
  Node *top;
 public:
  struct Node{
    //data
    Node * next;
  };
  
  void push(Node & n){
    for(;;){
      n.next = top;
     if(CAA(top, n.next, &n)) break;
    }
  };
  
  Node * pop(){
    Node * t;
    for(;;){
      t = top;
     if(t == nullptr) return t;
     if(CAA(top, t, t->next)) return t;
    }
  };
}

push() works, but pop() does not, at least not always.

11.1.3 ABA problem

Consider this to be the stack: top -> A -> B -> C

pop() would not work if,

  1. pop() called CAA(top, A, B), and gets time sliced.
    so it wants to change top from A to B
  2. Other task interrupts and calls 2 pops(), and pushes A back into the stack.
    A -> B -> C -> C -> A -> C
  3. pop() routine comes back, and sees that top is still A, so it thinks nothing has been changed; the routine assignes top to be B which is popped off.
    top -> B -> ????

This cannot be fixed easily.

11.1.4 Hardware Fix

A solution for the problem above is to take advantage of double-wide CAVD instruction.

This compares/assigns 64(or 128) bit values for 32(or 64) bit architectures.

For CAV function itself, everything looks the same except the data types.
But we will include some tickets attached to the node struct.

bool CAVD(uintS_t & val, uintS_t comp, uintS_t nval){
  //begin atomic
  if(val == comp){
    val = nval;
    return true;
  }
  return false;
  //end atomic
}

class Stack{
  Node *top;
  union Link{
    struct{            // 32/64 bit data * 2
      Node *top;       // pointer to top node
      uintptr_t count; // ticket
    };
    uintS_t atom;      // raw form of above struct
  } link;
 public:
  struct Node{
    //data
    Link * next;
  };
  Stack() {link.atom = 0;}

좋은 웹페이지 즐겨찾기