volatile qnode * hclh_acquire(local_queue *lq, global_queue *gq, qnode *my_qnode) { volatile qnode* my_pred; do { #if defined(OPTERON_OPTIMIZE) PREFETCHW(lq); #endif /* OPTERON_OPTIMIZE */ my_pred = *lq; } while (CAS_PTR(lq, my_pred, my_qnode)!=my_pred); if (my_pred != NULL) { uint16_t i_own_lock = wait_for_grant_or_cluster_master(my_pred, my_qnode->fields.cluster_id); if (i_own_lock) { return my_pred; } } PAUSE; PAUSE; volatile qnode * local_tail; do { #if defined(OPTERON_OPTIMIZE) PREFETCHW(gq); PREFETCHW(lq); #endif /* OPTERON_OPTIMIZE */ my_pred = *gq; local_tail = *lq; PAUSE; } while(CAS_PTR(gq, my_pred, local_tail)!=my_pred); local_tail->fields.tail_when_spliced = 1; #if defined(OPTERON_OPTIMIZE) PREFETCHW(my_pred); #endif /* OPTERON_OPTIMIZE */ while (my_pred->fields.successor_must_wait) { PAUSE; #if defined(OPTERON_OPTIMIZE) pause_rep(23); PREFETCHW(my_pred); #endif /* OPTERON_OPTIMIZE */ } return my_pred; }
volatile qnode * hclh_acquire(local_queue *lq, global_queue *gq, qnode *my_qnode) { //splice my_qnode into local queue volatile qnode* my_pred; do { my_pred = *lq; } while (CAS_PTR(lq, my_pred, my_qnode)!=my_pred); if (my_pred != NULL) { uint16_t i_own_lock = wait_for_grant_or_cluster_master(my_pred, my_qnode->fields.cluster_id); if (i_own_lock) { //I have the lock; return qnode just released by previous owner return my_pred; } } //at this point, I'm cluster master. Wait to allow time for other acquireres to show up. PAUSE; PAUSE; volatile qnode * local_tail; //splice local queue into global queue do { my_pred = *gq; local_tail = *lq; PAUSE; } while(CAS_PTR(gq, my_pred, local_tail)!=my_pred); //inform successor that it is the new master local_tail->fields.tail_when_spliced = 1; //wait for predecessor to release lock while (my_pred->fields.successor_must_wait) { PAUSE; } //I have the lock. return qnode just released by previous owner for next lock access return my_pred; }