Ejemplo n.º 1
0
skey_t
alistarh_spray(sl_intset_t *set)
{
    sl_node_t *next, *node;
    int i, level;

retry:
    UPDATE_TRY();
    PARSE_START_TS(3);
    node = set->head;
    next = NULL;
    for(level = starting_height; level>=0; level-=ALISTARH_LEVELS_TO_DESCEND)
    {
        i = (int)rand_range(max_jump_length);
        for (; i>0; i--)
        {
            next = node->next[level];
            if (next==NULL || next->next[0]==NULL)
                break;
            node = next;
        }
    }
    PARSE_END_TS(3, lat_parsing_deleteMin++);
    if (unlikely(node == set->head))
        goto retry;

    if (unlikely(node->val == KEY_MIN+1))
        goto retry;

    return node->key;
}
Ejemplo n.º 2
0
sval_t
fraser_remove(sl_intset_t *set, skey_t key)
{
  UPDATE_TRY();

  sl_node_t* succs[FRASER_MAX_MAX_LEVEL];
  sval_t result = 0;

  PARSE_START_TS(2);
  int found = fraser_search_no_cleanup_succs(set, key, succs);
  PARSE_END_TS(2, lat_parsing_rem++);

  if (!found)
    {
      return false;
    }

  sl_node_t* node_del = succs[0];
  int my_delete = mark_node_ptrs(node_del);

  if (my_delete)
    {
      result = node_del->val;
      fraser_search(set, key, NULL, NULL);
#if GC == 1
      ssmem_free(alloc, (void*) succs[0]);
#endif
    }
  return result;
}
Ejemplo n.º 3
0
bool_t bst_add(skey_t k,sval_t v,  node_t* root){

	node_t* pred;
	node_t* curr;
	node_t* new_node = NULL;
	operation_t* pred_op;
	operation_t* curr_op;
	operation_t* cas_op;
	sval_t  result;

	while(TRUE) {
	  UPDATE_TRY();

		result = bst_find(k, &pred, &pred_op, &curr, &curr_op, root, root);
		if (result & val_mask) {
#if GC == 1
            if (new_node!=NULL) {
                ssmem_free(alloc,new_node);
            }
#endif
			return FALSE;
		}
        
        if (new_node == NULL) {
		    new_node = create_node(k,v,0);
        }

		bool_t is_left = (result == NOT_FOUND_L);
		node_t* old;
		if (is_left) {
			old = (node_t*) curr->left;
		} else {
			old = (node_t*) curr->right;
		}

		cas_op = alloc_op();
		cas_op->child_cas_op.is_left = is_left;
		cas_op->child_cas_op.expected = old;
		cas_op->child_cas_op.update = new_node;

#if defined(__tile__)
		MEM_BARRIER;
#endif
		if (CAS_PTR(&curr->op, curr_op, FLAG(cas_op, STATE_OP_CHILDCAS)) == curr_op) {

			bst_help_child_cas(cas_op, curr, root);
#if GC == 1
            //if (UNFLAG(curr_op)!=0) ssmem_free(alloc,(void*)UNFLAG(curr_op));
#endif
			return TRUE;
		} else {
#if GC == 1
            ssmem_free(alloc,cas_op);
#endif
        }
	}
}
Ejemplo n.º 4
0
/*   
 *   File: optik.c
 *   Author: Vasileios Trigonakis <*****@*****.**>
 *   Description: 
 *
 * Copyright (c) 2014 Vasileios Trigonakis <*****@*****.**>,
 *	      	      Distributed Programming Lab (LPD), EPFL
 *
 * ASCYLIB is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, version 2
 * of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include "linkedlist-optik.h"

RETRY_STATS_VARS;

sval_t
optik_find(intset_l_t *set, skey_t key)
{
  PARSE_TRY();
  node_l_t* curr = set->head;
  while (curr != NULL && curr->key < key)
    {
      curr = curr->next;
    }

  sval_t res = 0;
  if (curr != NULL && curr->key == key)
    {
      res = curr->val;
    }

  return res;
}

#if !defined(LL_GLOBAL_LOCK)
int
optik_insert(intset_l_t *set, skey_t key, sval_t val)
{	
 restart:
  PARSE_TRY();
  volatile node_l_t *curr, *pred = NULL;

  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);
  curr = set->head;

  while (curr != NULL && (curr->key < key))
    {
      pred = curr;
      curr = curr->next;
    }

  UPDATE_TRY();

  if (curr != NULL && curr->key == key)
    {
      return false;
    }

  if (!optik_trylock_version(&set->lock, pred_ver))
    {
      goto restart;
    }

  node_l_t* newnode = new_node_l(key, val, curr, 0);
#ifdef __tile__
  MEM_BARRIER;
#endif

  if (pred != NULL)
    {
      pred->next = newnode;
    }
  else
    {
      set->head = newnode;
    }

  optik_unlock(&set->lock);

  return true;
}
#else  /* LL_GLOBAL_LOCK == 1 :: pessimistic */
int
optik_insert(intset_l_t *set, skey_t key, sval_t val)
{	
  volatile node_l_t *curr, *pred;
  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);

  int r;
  for (r = 0; r < 2; r++)
    {
      PARSE_TRY();

      pred = NULL;
      curr = set->head;

      while (curr != NULL && curr->key < key)
	{
	  pred = curr;
	  curr = curr->next;
	}

      UPDATE_TRY();

      if (curr != NULL && curr->key == key)
	{
	  if (r)
	    {
	      optik_unlock(&set->lock);
	    }
	  return false;
	}

      if (!r && optik_lock_version(&set->lock, pred_ver))
	{
	  break;
	}
    }

  node_l_t* newnode = new_node_l(key, val, curr, 0);
#ifdef __tile__
  MEM_BARRIER;
#endif

  if (pred != NULL)
    {
      pred->next = newnode;
    }
  else
    {
      set->head = newnode;
    }

  optik_unlock(&set->lock);

  return true;
}
#endif	/* LL_GLOBAL_LOCK */

#if !defined(LL_GLOBAL_LOCK)
sval_t
optik_delete(intset_l_t *set, skey_t key)
{
 restart:
  PARSE_TRY();
  volatile node_l_t *pred = NULL, *curr;  
  sval_t result = 0;

  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);
  curr = set->head;

  while (curr != NULL && curr->key < key)
    {
      pred = curr;
      curr = curr->next;
    }

  UPDATE_TRY();

  if (curr == NULL || curr->key != key)
    {
      return false;
    }

  if ((!optik_trylock_version(&set->lock, pred_ver)))
    {
      goto restart;
    }

  result = curr->val;
  if (pred != NULL)
    {
      pred->next = curr->next;
    }
  else
    {
      set->head = curr->next;
    }

  optik_unlock(&set->lock);
     
#if GC == 1
   ssmem_free(alloc, (void*) curr);
#endif
 
  return result;
}
#else  /* LL_GLOBAL_LOCK = 1 :: pessimistic locking */
sval_t
optik_delete(intset_l_t *set, skey_t key)
{
  volatile node_l_t *pred, *curr;  
  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);

  int r;
  for (r = 0; r < 2; r++)
    {
      PARSE_TRY();

      pred = NULL;
      curr = set->head;

      while (curr != NULL && curr->key < key)
	{
	  pred = curr;
	  curr = curr->next;
	}

      UPDATE_TRY();

      if (curr == NULL || curr->key != key)
	{
	  if (r)
	    {
	      optik_unlock(&set->lock);
	    }
	  return false;
	}

      if (!r && optik_lock_version(&set->lock, pred_ver))
	{
	  break;
	}
    }

  sval_t result = curr->val;
  if (pred != NULL)
    {
      pred->next = curr->next;
    }
  else
    {
      set->head = curr->next;
    }

  optik_unlock(&set->lock);
     
#if GC == 1
  ssmem_free(alloc, (void*) curr);
#endif
 
  return result;
}
Ejemplo n.º 5
0
/*   
 *   File: optik.c
 *   Author: Vasileios Trigonakis <*****@*****.**>
 *   Description: 
 *
 * Copyright (c) 2014 Vasileios Trigonakis <*****@*****.**>,
 *	      	      Distributed Programming Lab (LPD), EPFL
 *
 * ASCYLIB is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, version 2
 * of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include "linkedlist-optik.h"

RETRY_STATS_VARS;

sval_t
optik_find(intset_l_t *set, skey_t key)
{
  PARSE_TRY();
  node_l_t* curr = set->head;
  while (curr != NULL && curr->key < key)
    {
      curr = curr->next;
    }

  sval_t res = 0;
  if (curr != NULL && curr->key == key)
    {
      res = curr->val;
    }

  return res;
}

#if !defined(LL_GLOBAL_LOCK)
int
optik_insert(intset_l_t *set, skey_t key, sval_t val)
{	
 restart:
  PARSE_TRY();
  volatile node_l_t *curr, *pred = NULL;

  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);
  curr = set->head;

  while (curr != NULL && (curr->key < key))
    {
      pred = curr;
      curr = curr->next;
    }

  UPDATE_TRY();

  if (curr != NULL && curr->key == key)
    {
      return false;
    }

  if (!optik_trylock_version(&set->lock, pred_ver))
    {
      goto restart;
    }

  node_l_t* newnode = new_node_l(key, val, curr, 0);
#ifdef __tile__
  MEM_BARRIER;
#endif

  if (pred != NULL)
    {
      pred->next = newnode;
    }
  else
    {
      set->head = newnode;
    }

  optik_unlock(&set->lock);

  return true;
}
#else  /* LL_GLOBAL_LOCK == 1 :: pessimistic */
int
optik_insert(intset_l_t *set, skey_t key, sval_t val)
{	
  volatile node_l_t *curr, *pred;
  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);

  int r;
  for (r = 0; r < 2; r++)
    {
      PARSE_TRY();

      pred = NULL;
      curr = set->head;

      while (curr != NULL && curr->key < key)
	{
	  pred = curr;
	  curr = curr->next;
	}

      UPDATE_TRY();

      if (curr != NULL && curr->key == key)
	{
	  if (r)
	    {
	      optik_unlock(&set->lock);
	    }
	  return false;
	}

      if (!r && optik_lock_version(&set->lock, pred_ver))
	{
	  break;
	}
    }

  node_l_t* newnode = new_node_l(key, val, curr, 0);
#ifdef __tile__
  MEM_BARRIER;
#endif

  if (pred != NULL)
    {
      pred->next = newnode;
    }
  else
    {
      set->head = newnode;
    }

  optik_unlock(&set->lock);

  return true;
}
Ejemplo n.º 6
0
bool_t bst_insert(skey_t key, sval_t val, node_t* node_r) {
    node_t* new_internal = NULL;
    node_t* new_node = NULL;
    uint created = 0;
    while (1) {
      UPDATE_TRY();

        bst_seek(key, node_r);
        if (seek_record->leaf->key == key) {
#if GC == 1
            if (created) {
                ssmem_free(alloc, new_internal);
                ssmem_free(alloc, new_node);
            }
#endif
            return FALSE;
        }
        node_t* parent = seek_record->parent;
        node_t* leaf = seek_record->leaf;

        node_t** child_addr;
        if (key < parent->key) {
	  child_addr= (node_t**) &(parent->left); 
        } else {
            child_addr= (node_t**) &(parent->right);
        }
        if (likely(created==0)) {
            new_internal=create_node(max(key,leaf->key),0,0);
            new_node = create_node(key,val,0);
            created=1;
        } else {
            new_internal->key=max(key,leaf->key);
        }
        if ( key < leaf->key) {
            new_internal->left = new_node;
            new_internal->right = leaf; 
        } else {
            new_internal->right = new_node;
            new_internal->left = leaf;
        }
 #ifdef __tile__
    MEM_BARRIER;
#endif
        node_t* result = CAS_PTR(child_addr, ADDRESS(leaf), ADDRESS(new_internal));
        if (result == ADDRESS(leaf)) {
            return TRUE;
        }
        node_t* chld = *child_addr; 
        if ( (ADDRESS(chld)==leaf) && (GETFLAG(chld) || GETTAG(chld)) ) {
            bst_cleanup(key); 
        }
    }
}
Ejemplo n.º 7
0
sval_t bst_remove(skey_t key, node_t* node_r) {
    bool_t injecting = TRUE; 
    node_t* leaf;
    sval_t val = 0;
    while (1) {
      UPDATE_TRY();

        bst_seek(key, node_r);
        val = seek_record->leaf->value;
        node_t* parent = seek_record->parent;

        node_t** child_addr;
        if (key < parent->key) {
            child_addr = (node_t**) &(parent->left);
        } else {
            child_addr = (node_t**) &(parent->right);
        }

        if (injecting == TRUE) {
            leaf = seek_record->leaf;
            if (leaf->key != key) {
                return 0;
            }
            node_t* lf = ADDRESS(leaf);
            node_t* result = CAS_PTR(child_addr, lf, FLAG(lf));
            if (result == ADDRESS(leaf)) {
                injecting = FALSE;
                bool_t done = bst_cleanup(key);
                if (done == TRUE) {
                    return val;
                }
            } else {
                node_t* chld = *child_addr;
                if ( (ADDRESS(chld) == leaf) && (GETFLAG(chld) || GETTAG(chld)) ) {
                    bst_cleanup(key);
                }
            }
        } else {
            if (seek_record->leaf != leaf) {
                return val; 
            } else {
                bool_t done = bst_cleanup(key);
                if (done == TRUE) {
                    return val;
                }
            }
        }
    }
}
Ejemplo n.º 8
0
sval_t
optik_delete(intset_l_t *set, skey_t key)
{
 restart:
  PARSE_TRY();
  volatile node_l_t *pred = NULL, *curr;  
  sval_t result = 0;

  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);
  curr = set->head;

  while (curr != NULL && curr->key < key)
    {
      pred = curr;
      curr = curr->next;
    }

  UPDATE_TRY();

  if (curr == NULL || curr->key != key)
    {
      return false;
    }

  if ((!optik_trylock_version(&set->lock, pred_ver)))
    {
      goto restart;
    }

  result = curr->val;
  if (pred != NULL)
    {
      pred->next = curr->next;
    }
  else
    {
      set->head = curr->next;
    }

  optik_unlock(&set->lock);
     
#if GC == 1
   ssmem_free(alloc, (void*) curr);
#endif
 
  return result;
}
Ejemplo n.º 9
0
/*
 * Logically remove an element by setting a mark bit to 1 
 * before removing it physically.
 */
sval_t
parse_delete(intset_l_t *set, skey_t key)
{
  node_l_t *pred, *curr;
  sval_t result = 0;
  int done = 0;
	
  do
    {
      PARSE_TRY();
      pred = set->head;
      curr = pred->next;
      while (likely(curr->key < key))
	{
	  pred = curr;
	  curr = curr->next;
	}

      UPDATE_TRY();

      GL_LOCK(set->lock);		/* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */
      LOCK(ND_GET_LOCK(pred));
      LOCK(ND_GET_LOCK(curr));

      if (parse_validate(pred, curr))
	{
	  if (key == curr->key)
	    {
	      result = curr->val;
	      node_l_t* c_nxt = curr->next;
	      curr->marked = 1;
	      pred->next = c_nxt;
#if GC == 1
	      ssmem_free(alloc, (void*) curr);
#endif
	    }
	  done = 1;
	}

      GL_UNLOCK(set->lock);
      UNLOCK(ND_GET_LOCK(curr));
      UNLOCK(ND_GET_LOCK(pred));
    }
  while (!done);
  return result;
}
Ejemplo n.º 10
0
int
optik_insert(intset_l_t *set, skey_t key, sval_t val)
{	
 restart:
  PARSE_TRY();
  volatile node_l_t *curr, *pred = NULL;

  COMPILER_NO_REORDER(optik_t pred_ver = set->lock);
  curr = set->head;

  while (curr != NULL && (curr->key < key))
    {
      pred = curr;
      curr = curr->next;
    }

  UPDATE_TRY();

  if (curr != NULL && curr->key == key)
    {
      return false;
    }

  if (!optik_trylock_version(&set->lock, pred_ver))
    {
      goto restart;
    }

  node_l_t* newnode = new_node_l(key, val, curr, 0);
#ifdef __tile__
  MEM_BARRIER;
#endif

  if (pred != NULL)
    {
      pred->next = newnode;
    }
  else
    {
      set->head = newnode;
    }

  optik_unlock(&set->lock);

  return true;
}
Ejemplo n.º 11
0
int
parse_insert(intset_l_t *set, skey_t key, sval_t val)
{
  node_l_t *curr, *pred, *newnode;
  int result = -1;
	
  do
    {
      PARSE_TRY();
      pred = set->head;
      curr = pred->next;
      while (likely(curr->key < key))
	{
	  pred = curr;
	  curr = curr->next;
	}

      UPDATE_TRY();

      GL_LOCK(set->lock);		/* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */
      LOCK(ND_GET_LOCK(pred));
      LOCK(ND_GET_LOCK(curr));

      if (parse_validate(pred, curr))
	{
	  result = (curr->key != key);
	  if (result) 
	    {
	      newnode = new_node_l(key, val, curr, 0);
#ifdef __tile__
  MEM_BARRIER;
#endif
	      pred->next = newnode;
	    } 
	}
      GL_UNLOCK(set->lock);
      UNLOCK(ND_GET_LOCK(curr)); 
      UNLOCK(ND_GET_LOCK(pred));
    }
  while (result < 0);
  return result;
}
Ejemplo n.º 12
0
/* 
 * Similar algorithm for the delete, find, and insert:
 * Lock the first two elements (locking each before getting the copy of the element)
 * then unlock previous, keep ownership of the current, and lock next in a loop.
 */
sval_t
lockc_delete(intset_l_t *set, skey_t key)
{
  PARSE_TRY();
  UPDATE_TRY();

  node_l_t *curr, *next;
  sval_t res = 0;
	
  GL_LOCK(set->lock);		/* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */
  LOCK(ND_GET_LOCK(set->head));
  curr = set->head;
  LOCK(ND_GET_LOCK(curr->next));
  next = curr->next;
	
  while (next->key < key) 
    {
      UNLOCK(ND_GET_LOCK(curr));
      curr = next;
      LOCK(ND_GET_LOCK(next->next));
      next = next->next;
    }

  if (key == next->key)
    {
      res = next->val;
      curr->next = next->next;
      UNLOCK(ND_GET_LOCK(next));
      node_delete_l(next);
      UNLOCK(ND_GET_LOCK(curr));
    } 
  else 
    {
      UNLOCK(ND_GET_LOCK(curr));
      UNLOCK(ND_GET_LOCK(next));
    }  
  GL_UNLOCK(set->lock);

  return res;
}
Ejemplo n.º 13
0
int
lockc_insert(intset_l_t *set, skey_t key, sval_t val) 
{
  PARSE_TRY();
  UPDATE_TRY();

  node_l_t *curr, *next, *newnode;
  int found;
	
  GL_LOCK(set->lock);		/* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */
  LOCK(ND_GET_LOCK(set->head));
  curr = set->head;
  LOCK(ND_GET_LOCK(curr->next));
  next = curr->next;
	
  while (next->key < key) 
    {
      UNLOCK(ND_GET_LOCK(curr));
      curr = next;
      LOCK(ND_GET_LOCK(next->next));
      next = curr->next;
    }
  found = (key == next->key);
  if (!found) 
    {
      newnode =  new_node_l(key, val, next, 1);
#ifdef __tile__
  MEM_BARRIER;
#endif
      curr->next = newnode;
    }
  GL_UNLOCK(set->lock);
  UNLOCK(ND_GET_LOCK(curr));
  UNLOCK(ND_GET_LOCK(next));
  return !found;
}
Ejemplo n.º 14
0
/*
 * Function optimistic_delete is similar to the method remove of the paper.
 * Here we avoid the fast search parameter as the comparison is faster in C 
 * than calling the Java compareTo method of the Comparable interface 
 * (cf. p132 of SIROCCO'07 proceedings).
 */
sval_t
optimistic_delete(sl_intset_t *set, skey_t key)
{
  sl_node_t *succs[HERLIHY_MAX_MAX_LEVEL], *preds[HERLIHY_MAX_MAX_LEVEL];
  sl_node_t *node_todel, *prev_pred; 
  sl_node_t *pred, *succ;
  int is_marked, toplevel, highest_locked, i, valid, found;	
  unsigned int backoff;

  node_todel = NULL;
  is_marked = 0;
  toplevel = -1;
  backoff = 1;
	
  PARSE_START_TS(2);
  while(1)
    {
      UPDATE_TRY();
      found = optimistic_search(set, key, preds, succs, 1);
      PARSE_END_TS(2, lat_parsing_rem);

      /* If not marked and ok to delete, then mark it */
      if (is_marked || (found != -1 && ok_to_delete(succs[found], found)))
	{	
	  GL_LOCK(set->lock); /* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */
	  if (!is_marked)
	    {
	      node_todel = succs[found];

	      LOCK(ND_GET_LOCK(node_todel));
	      toplevel = node_todel->toplevel;
	      /* Unless it has been marked meanwhile */

	      if (node_todel->marked)
		{
		  GL_UNLOCK(set->lock);
		  UNLOCK(ND_GET_LOCK(node_todel));
		  PARSE_END_INC(lat_parsing_rem);
		  return 0;
		}

	      node_todel->marked = 1;
	      is_marked = 1;
	    }

	  /* Physical deletion */
	  highest_locked = -1;
	  prev_pred = NULL;
	  valid = 1;
	  for (i = 0; valid && (i < toplevel); i++)
	    {
	      pred = preds[i];
	      succ = succs[i];
	      if (pred != prev_pred)
		{
		  LOCK(ND_GET_LOCK(pred));
		  highest_locked = i;
		  prev_pred = pred;
		}

	      valid = (!pred->marked && ((volatile sl_node_t*) pred->next[i] == 
					 (volatile sl_node_t*) succ));
	    }

	  if (!valid)
	    {	
	      unlock_levels(set, preds, highest_locked);
	      if (backoff > 5000) 
		{
		  nop_rep(backoff & MAX_BACKOFF);
		}
	      backoff <<= 1;
	      continue;
	    }
			
	  for (i = (toplevel-1); i >= 0; i--)
	    {
	      preds[i]->next[i] = node_todel->next[i];
	    }

	  sval_t val = node_todel->val;
#if GC == 1
	  ssmem_free(alloc, (void*) node_todel);
#endif

	  UNLOCK(ND_GET_LOCK(node_todel));
	  unlock_levels(set, preds, highest_locked);

	  PARSE_END_INC(lat_parsing_rem);
	  return val;
	}
      else
	{
	  PARSE_END_INC(lat_parsing_rem);
	  return 0;
	}
    }
}
Ejemplo n.º 15
0
int
optimistic_insert(sl_intset_t *set, skey_t key, sval_t val)
{
    PARSE_TRY();
    UPDATE_TRY();
    PARSE_START_TS(1);
    sl_node_t* update[HERLIHY_MAX_MAX_LEVEL];
    sl_node_t* succ;
    sl_node_t* pred = set->head;
    int lvl;
    for (lvl = levelmax - 1; lvl >= 0; lvl--)
    {
        succ = pred->next[lvl];
        while (succ->key < key)
        {
            pred = succ;
            succ = succ->next[lvl];
        }
        if (unlikely(succ->key == key))	/* at any search level */
        {
            return false;
        }
        update[lvl] = pred;
    }
    PARSE_END_TS(1, lat_parsing_put++);

    int rand_lvl = get_rand_level(); /* do the rand_lvl outside the CS */

    GL_LOCK(set->lock);
    pred = get_lock(pred, key, 0);
    if (unlikely(pred->next[0]->key == key))
    {
        UNLOCK(ND_GET_LOCK(pred));
        GL_UNLOCK(set->lock);
        return false;
    }

    sl_node_t* n = sl_new_simple_node(key, val, rand_lvl, 0);
    LOCK(ND_GET_LOCK(n));

    n->next[0] = pred->next[0];	/* we already hold the lock for lvl 0 */
#ifdef __tile__
    MEM_BARRIER;
#endif
    pred->next[0] = n;
    UNLOCK(ND_GET_LOCK(pred));

    for (lvl = 1; lvl < n->toplevel; lvl++)
    {
        pred = get_lock(update[lvl], key, lvl);
        n->next[lvl] = pred->next[lvl];
#ifdef __tile__
        MEM_BARRIER;
#endif
        pred->next[lvl] = n;
        UNLOCK(ND_GET_LOCK(pred));
    }
    UNLOCK(ND_GET_LOCK(n));
    GL_UNLOCK(set->lock);

    return 1;
}
Ejemplo n.º 16
0
sval_t
optimistic_delete(sl_intset_t *set, skey_t key)
{
    PARSE_TRY();
    UPDATE_TRY();
    PARSE_START_TS(2);
    sl_node_t* update[HERLIHY_MAX_MAX_LEVEL];
    sl_node_t* succ = NULL;
    sl_node_t* pred = set->head;
    int lvl;
    for (lvl = levelmax - 1; lvl >= 0; lvl--)
    {
        succ = pred->next[lvl];
        while (succ->key < key)
        {
            pred = succ;
            succ = succ->next[lvl];
        }
        update[lvl] = pred;
    }
    PARSE_END_TS(2, lat_parsing_rem++);

    GL_LOCK(set->lock);

    succ = pred;
    int is_garbage;
    do
    {
        succ = succ->next[0];
        if (succ->key > key)
        {
            GL_UNLOCK(set->lock);
            return false;
        }

        LOCK(ND_GET_LOCK(succ));
        is_garbage = (succ->key > succ->next[0]->key);
        if (is_garbage || succ->key != key)
        {
            UNLOCK(ND_GET_LOCK(succ));
        }
        else
        {
            break;
        }
    }
    while(true);

    for (lvl = succ->toplevel - 1; lvl >= 0; lvl--)
    {
        pred = get_lock(update[lvl], key, lvl);
        pred->next[lvl] = succ->next[lvl];
        succ->next[lvl] = pred;	/* pointer reversal! :-) */
        UNLOCK(ND_GET_LOCK(pred));
    }

    UNLOCK(ND_GET_LOCK(succ));
    GL_UNLOCK(set->lock);
#if GC == 1
    ssmem_free(alloc, (void*) succ);
#endif

    return succ->val;
}
Ejemplo n.º 17
0
sval_t
alistarh_deleteMin(sl_intset_t *set)
{
    skey_t key;
    sval_t result;
    sl_node_t *next, *node;
    sl_node_t *update[HERLIHY_MAX_MAX_LEVEL];
    sl_node_t *succ, *pred;
    int i, level, continue_flag;

retry:
    if (unlikely(rand_range(100) <= cleaner_percentage))
    {   //become cleaner
        result = 0;
        PARSE_START_TS(4);
        node = last_dummy_entry->next[0];
        while(node->next[0]!=NULL && result==0)
        {
            if (unlikely(node->key > node->next[0]->key))
            {
                node = node->next[0];
                continue;
            }

            succ = NULL;
            pred = set->head;
            key = node->key;
            continue_flag = 0;

            for (level = levelmax - 1; level >= 0; level--)
            {
                succ = pred->next[level];
                while (succ->key < key)
                {
                    pred = succ;
                    succ = succ->next[level];
                }
                update[level] = pred;
            }
            PARSE_END_TS(3, lat_parsing_deleteMin++);

            GL_LOCK(set->lock);

            succ = pred;
            int is_garbage;
            do
            {
                succ = succ->next[0];
                if (succ->key > key)
                {
                    GL_UNLOCK(set->lock);
                    continue_flag = 1;
                    break;
                }

                LOCK(ND_GET_LOCK(succ));
                is_garbage = (succ->key > succ->next[0]->key);
                if (is_garbage || succ->key != key)
                {
                    UNLOCK(ND_GET_LOCK(succ));
                }
                else
                {
                    break;
                }
            } while(true);

            if (continue_flag)
            {
                node = node->next[0];
                continue;
            }

            for (level = succ->toplevel - 1; level >= 0; level--)
            {
                pred = get_lock(update[level], key, level);
                pred->next[level] = succ->next[level];
                succ->next[level] = pred;	// pointer reversal! :-)
                UNLOCK(ND_GET_LOCK(pred));
            }

            result = node->val;

            UNLOCK(ND_GET_LOCK(succ));
            GL_UNLOCK(set->lock);
#if GC == 1
            ssmem_free(alloc, (void*) succ);
#endif
        }
        PARSE_END_TS(4, lat_parsing_cleaner++);

        return result;
    }
    else //spray & mark as deleted
    {
        UPDATE_TRY();

        PARSE_START_TS(3);
        result = 0;
        node = set->head;
        next = NULL;
        for(level = starting_height; level>=0; level-=ALISTARH_LEVELS_TO_DESCEND)
        {
            i = (int)rand_range(max_jump_length);
            for (; i>0; i--)
            {
                next = node->next[level];
                if (next==NULL || next->next[0]==NULL)
                    break;
                node = next;
            }
        }

        if (unlikely(node == set->head))
            goto retry;

        if (unlikely(node->val == KEY_MIN+1))
            goto retry;

        if (unlikely(node->key > node->next[0]->key))
            goto retry;

        succ = NULL;
        pred = set->head;
        key = node->key;

        for (level = levelmax - 1; level >= 0; level--)
        {
            succ = pred->next[level];
            while (succ->key < key)
            {
                pred = succ;
                succ = succ->next[level];
            }
            update[level] = pred;
        }
        PARSE_END_TS(3, lat_parsing_deleteMin++);

        GL_LOCK(set->lock);

        succ = pred;
        int is_garbage;
        do
        {
            succ = succ->next[0];
            if (succ->key > key)
            {
                GL_UNLOCK(set->lock);
                goto retry;
            }

            LOCK(ND_GET_LOCK(succ));
            is_garbage = (succ->key > succ->next[0]->key);
            if (is_garbage || succ->key != key)
            {
                UNLOCK(ND_GET_LOCK(succ));
            }
            else
            {
                break;
            }
        }
        while(true);

        for (level = succ->toplevel - 1; level >= 0; level--)
        {
            pred = get_lock(update[level], key, level);
            pred->next[level] = succ->next[level];
            succ->next[level] = pred;	// pointer reversal! :-)
            UNLOCK(ND_GET_LOCK(pred));
        }

        result = node->val;

        UNLOCK(ND_GET_LOCK(succ));
        GL_UNLOCK(set->lock);
#if GC == 1
        ssmem_free(alloc, (void*) succ);
#endif

        return result;
    }
}
Ejemplo n.º 18
0
sval_t bst_remove(skey_t k, node_t* root){

	node_t* pred;
	node_t* curr;
	node_t* replace;
    sval_t val;
	operation_t* pred_op;
	operation_t* curr_op;
	operation_t* replace_op;
	operation_t* reloc_op=NULL;

	while(TRUE) {
	  UPDATE_TRY();

        sval_t res = bst_find(k, &pred, &pred_op, &curr, &curr_op, root, root);
		if (!(res & val_mask)) {
#if GC == 1
            //if (reloc_op!=NULL) ssmem_free(alloc,reloc_op);
#endif
			return 0;
		}

		if (ISNULL((node_t*) curr->right) || ISNULL((node_t*) curr->left)) { // node has less than two children
			if (CAS_PTR(&(curr->op), curr_op, FLAG(curr_op, STATE_OP_MARK)) == curr_op) {
				bst_help_marked(pred, pred_op, curr, root);
#if GC == 1
                //if (reloc_op!=NULL) ssmem_free(alloc,reloc_op);
                if (UNFLAG(curr->op)!=0) ssmem_free(alloc,(void*)UNFLAG(curr->op));
                ssmem_free(alloc,curr);
#endif
				return res;
			}
		} else { // node has two children
			val = bst_find(k, &pred, &pred_op, &replace, &replace_op, curr, root);
			if ((val == ABORT) || (curr->op != curr_op)) {
				continue;
			} 
            
            //if (reloc_op==NULL) {
			    reloc_op = alloc_op(); 
            //}
			reloc_op->relocate_op.state = STATE_OP_ONGOING;
			reloc_op->relocate_op.dest = curr;
			reloc_op->relocate_op.dest_op = curr_op;
			reloc_op->relocate_op.remove_key = k;
			reloc_op->relocate_op.remove_value = res;
			reloc_op->relocate_op.replace_key = replace->key;
			reloc_op->relocate_op.replace_value = replace->value;

#if defined(__tile__)
			MEM_BARRIER;
#endif
			if (CAS_PTR(&(replace->op), replace_op, FLAG(reloc_op, STATE_OP_RELOCATE)) == replace_op) {
#if GC == 1
                if (UNFLAG(replace_op)!=0) ssmem_free(alloc,(void*)UNFLAG(replace_op));
#endif
				if (bst_help_relocate(reloc_op, pred, pred_op, replace, root)) {
                    //if (UNFLAG(replace->op)!=0) ssmem_free(alloc,(void*)UNFLAG(replace->op));
#if GC == 1
                    //ssmem_free(alloc,replace);
#endif
					return res;
				}
			} else {
#if GC == 1
               ssmem_free(alloc,reloc_op);
             //   reloc_op=NULL;
#endif
            }
		}
	}
}
Ejemplo n.º 19
0
/*
 * Function optimistic_insert stands for the add method of the original paper.
 * Unlocking and freeing the memory are done at the right places.
 */
int
optimistic_insert(sl_intset_t *set, skey_t key, sval_t val)
{
  sl_node_t *succs[HERLIHY_MAX_MAX_LEVEL], *preds[HERLIHY_MAX_MAX_LEVEL];
  sl_node_t  *node_found, *prev_pred, *new_node;
  sl_node_t *pred, *succ;
  int toplevel, highest_locked, i, valid, found;
  unsigned int backoff;

  toplevel = get_rand_level();
  backoff = 1;
	
  PARSE_START_TS(1);
  while (1) 
    {
      UPDATE_TRY();
      found = optimistic_search(set, key, preds, succs, 1);
      PARSE_END_TS(1, lat_parsing_put);

      if (found != -1)
	{
	  node_found = succs[found];
	  if (!node_found->marked)
	    {
	      while (!node_found->fullylinked)
		{
		  PAUSE;
		}
	      PARSE_END_INC(lat_parsing_put);
	      return 0;
	    }
	  continue;
	}

      GL_LOCK(set->lock);		/* when GL_[UN]LOCK is defined the [UN]LOCK is not ;-) */
      highest_locked = -1;
      prev_pred = NULL;
      valid = 1;
      for (i = 0; valid && (i < toplevel); i++)
	{
	  pred = preds[i];
	  succ = succs[i];
	  if (pred != prev_pred)
	    {
	      LOCK(ND_GET_LOCK(pred));
	      highest_locked = i;
	      prev_pred = pred;
	    }	
			
	  valid = (!pred->marked && !succ->marked && 
		   ((volatile sl_node_t*) pred->next[i] == 
		    (volatile sl_node_t*) succ));
	}
	
      if (!valid) 
	{			 /* Unlock the predecessors before leaving */ 
	  unlock_levels(set, preds, highest_locked); /* unlocks the global-lock in the GL case */
	  if (backoff > 5000) 
	    {
	      nop_rep(backoff & MAX_BACKOFF);
	    }
	  backoff <<= 1;
	  continue;
	}
		
      new_node = sl_new_simple_node(key, val, toplevel, 0);

      for (i = 0; i < toplevel; i++)
	{
	  new_node->next[i] = succs[i];
	}

#if defined(__tile__)
      MEM_BARRIER;
#endif

      for (i = 0; i < toplevel; i++)
	{
	  preds[i]->next[i] = new_node;
	}
		
      new_node->fullylinked = 1;

      unlock_levels(set, preds, highest_locked);
      PARSE_END_INC(lat_parsing_put);
      return 1;
    }
}