Example #1
0
// Fraser's SkipList Algorithm
inline void fraser_search(sl_intset_t *set, uint32_t val, sl_node_t **left_list, sl_node_t **right_list)
{
    int i;
    sl_node_t *left, *left_next, *right, *right_next;
retry:
    left = set->head;
    for (i = LEVELMAX - 1; i >= 0; i--) {
        left_next = left->nexts[i];
        if (is_marked((uint32_t)left_next))
            goto retry;
        /* Find unmarked node pair at this level */
        for (right = left_next; ; right = right_next) {
            /* Skip a sequence of marked nodes */
            while(1) {
                right_next = right->nexts[i];
                if (!is_marked((uint32_t)right_next))
                    break;
                right = (sl_node_t*)unset_mark((uint32_t)right_next);
            }
            if (right->val >= val)
                break;
            left = right;
            left_next = right_next;
        }
        
        /* Ensure left and right nodes are adjacent */
        if ((left_next != right) &&
            (!ATOMIC_CAS_MB(&left->nexts[i], left_next, right)))
            goto retry;
        if (left_list != NULL)
            left_list[i] = left;
        if (right_list != NULL)
            right_list[i] = right;
    }
}
Example #2
0
/*
 * [lyj] Disable the interpretation of "deleted" field.
 */
void fraser_insert(sl_intset_t *set, uint32_t v, bool lin)
{
    sl_node_t *NEW, *new_next, *pred, *succ, *succs[LEVELMAX], *preds[LEVELMAX];
    uint32_t i;
    uint32_t status;
   // uint32_t attempts = 0;
    NEW = sl_new_simple_node(v, get_rand_level(), lin);
retry:
    fraser_search(set, v, preds, succs);
    for (i = 0; i < NEW->toplevel; i++)
        NEW->nexts[i] = succs[i];
    /* Node is visible once inserted at lowest level */
    if (!ATOMIC_CAS_MB(&preds[0]->nexts[0], succs[0], NEW))
        goto retry;
    
//retry_HTM:
    status = _xbegin();
    if(status == _XBEGIN_STARTED)
    {
        for (i = 1; i < NEW->toplevel; i++) {
            if(preds[i]->nexts[i] == succs[i])
                preds[i]->nexts[i] = NEW;
            else
                _xabort(66);
        }
        _xend();
        return;
    }/*else
    {
        if ((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 66) {
        }
        else if (++attempts < MAX_ATTEMPT_NUM) {
            goto retry_HTM;
        }
    }*/
    
    for (i = 1; i < NEW->toplevel; i++) {
        while (1) {
            pred = preds[i];
            succ = succs[i];
            /* Update the forward pointer if it is stale */
            new_next = NEW->nexts[i];
            if ((new_next != succ) &&
                (!ATOMIC_CAS_MB(&NEW->nexts[i], unset_mark((uint32_t)new_next), succ)))
                break;
            /* Give up if pointer is marked */
            /* We retry the search if the CAS fails */
            if (ATOMIC_CAS_MB(&pred->nexts[i], succ, NEW))
                break;
            fraser_search(set, v, preds, succs);
        }
    }
}
Example #3
0
int		
fraser_search(sl_intset_t *set, skey_t key, sl_node_t **left_list, sl_node_t **right_list)
{
  int i;
  sl_node_t *left, *left_next, *right = NULL, *right_next;

 retry:
  PARSE_TRY();

  left = set->head;
  for (i = levelmax - 1; i >= 0; i--)
    {
      left_next = left->next[i];
      if ((is_marked((uintptr_t)left_next)))
	{
	  goto retry;
	}
      /* Find unmarked node pair at this level */
      for (right = left_next; ; right = right_next)
	{
	  /* Skip a sequence of marked nodes */
	  right_next = right->next[i];
	  while ((is_marked((uintptr_t)right_next)))
	    {
	      right = (sl_node_t*)unset_mark((uintptr_t)right_next);
	      right_next = right->next[i];
	    }

	  if (right->key >= key)
	    {
	      break;
	    }
	  left = right; 
	  left_next = right_next;
	}
      /* Ensure left and right nodes are adjacent */
      if ((left_next != right) && (!ATOMIC_CAS_MB(&left->next[i], left_next, right)))
	{
	  goto retry;
	}

      if (left_list != NULL)
      	{
	  left_list[i] = left;
      	}
      if (right_list != NULL)
      	{
	  right_list[i] = right;
	}
    }
  return (right->key == key);
}
Example #4
0
void fraser_search(sl_intset_t *set, val_t val, sl_node_t **left_list, sl_node_t **right_list) {
  int i;
  sl_node_t *left, *left_next, *right, *right_next;

#ifdef DEBUG
  printf("++> fraser_search\n");
  IO_FLUSH;
#endif

retry:
  left = set->head;
  for (i = levelmax - 1; i >= 0; i--) {
    left_next = left->next[i];
    if (is_marked((uintptr_t)left_next))
      goto retry;
    /* Find unmarked node pair at this level */
    for (right = left_next; ; right = right_next) {
      /* Skip a sequence of marked nodes */
      while(1) {
        right_next = right->next[i];
        if (!is_marked((uintptr_t)right_next))
          break;
        right = (sl_node_t*)unset_mark((uintptr_t)right_next);
      }
      if (right->val >= val)
        break;
      left = right; 
      left_next = right_next;
    }
    /* Ensure left and right nodes are adjacent */
    if ((left_next != right) && 
        (!ATOMIC_CAS_MB(&left->next[i], left_next, right)))
      goto retry;
    if (left_list != NULL)
      left_list[i] = left;
    if (right_list != NULL)	
      right_list[i] = right;
  }

#ifdef DEBUG
  printf("++> fraser_search ends\n");
  IO_FLUSH;
#endif
}
Example #5
0
int naive_delete_min(sl_intset_t *set, val_t *val, thread_data_t *d) {
  sl_node_t *first;
  int result;

  first = set->head;

  while(1) {
    do {
      first = (sl_node_t*)unset_mark((uintptr_t)first->next[0]);
    } while(first->next[0] && first->deleted);
   if (ATOMIC_FETCH_AND_INC_FULL(&first->deleted) != 0) {
     d->nb_collisions++;
   } else {
     break;
   }
  }

  result = (first->next[0] != NULL);
  if (!result) {
    return 1;
  }
  
  *val = (first->val);
  mark_node_ptrs(first);

  // unsigned int *seed = &d->seed2;
  // *seed = _MarsagliaXOR(*seed);
  // if (*seed % (d->nb_threads) == 0) {
  //   fraser_search(set, first->val, NULL, NULL);    
  // }

  if (!first->next[0]->deleted)
     fraser_search(set, first->val, NULL, NULL);    

  return result; 
}
Example #6
0
inline val_t get_val(sl_node_t *n) {
  return ((sl_node_t *)unset_mark((uintptr_t)n))->val;
}
Example #7
0
int spray_delete_min(sl_intset_t *set, val_t *val, thread_data_t *d) {
  unsigned int n = d->nb_threads;
  unsigned int *seed = &d->seed2;

#ifndef DISTRIBUTION_EXPERIMENT 
  *seed = _MarsagliaXOR(*seed);
  if (n == 1 || *seed % n/*/floor_log_2(n)*/ == 0) { // n == 1 is equivalent to naive delete_min
    d->nb_clean++;
    return naive_delete_min(set, val, d);
  }
#endif

  sl_node_t *cur;
  int result;
  int scanlen;
  int height = SCANHEIGHT; 
  int scanmax = SCANMAX;
  int scan_inc = SCANINC;

  cur = set->head;

  int i = height;
  int dummy = 0;
  while(1) {
    *seed = _MarsagliaXOR(*seed);
    scanlen = *seed % (scanmax+1); 

    while (dummy < n*floor_log_2(n)/2 && scanlen > 0) {
      dummy += (1 << i);
      scanlen--;
    }


    while (scanlen > 0 && cur->next[i]) { // Step right //here: cur->next[0], or cur->next[i]??
      cur = (sl_node_t*)unset_mark((uintptr_t)cur->next[i]);
      if (!cur->deleted) scanlen--;
    } 

    // TODO: This is probably a reasonable condition to become a 'cleaner' since the list is so small
    //       We can also just ignore it since it shouldn't happen in benchmarks?
    if (!cur->next[0]) return 0; //got to end of list

    scanmax += scan_inc;

    if (i == 0) break;
    if (i <= SCANSKIP) { i = 0; continue; } // need to guarantee bottom level gets scanned
    i -= SCANSKIP;
  }

  if (cur == set->head) // still in dummy range
    return 0; // TODO: clean instead? something else?

  while (cur->deleted && cur->next[0]) {
    cur = (sl_node_t*)unset_mark((uintptr_t)cur->next[0]); // Find first non-deleted node
  } 

  if (!cur->next[0]) return 0;

#ifdef DISTRIBUTION_EXPERIMENT 
  *val = (cur->val);
  return 1;
#endif

  result = 1;
  if (cur->deleted == 0 )
  {
    result = ATOMIC_FETCH_AND_INC_FULL(&cur->deleted);
  }
  if (result != 0) {
    d->nb_collisions++;  
    return 0; // TODO: Retry and eventually 'clean'
  }

  *val = (cur->val);
  mark_node_ptrs(cur);

  // if (((*seed) & 0x10)) return 1;  

  // TODO: batch deletes (this method is somewhat inefficient)
  // fraser_search(set, cur->val, NULL, NULL);

  return 1; 
}
Example #8
0
long get_unmarked_ref(long w) {
    return unset_mark(w);
}
Example #9
0
long set_mark(long i) {
    i = unset_mark(i);
    i += 1;
    return i;
}