Esempio n. 1
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
        }
	}
}
Esempio n. 2
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); 
        }
    }
}
Esempio n. 3
0
sval_t
cpy_delete(copy_on_write_t* set, skey_t key)
{
  size_t bucket = key & set->hash;
  array_ll_t* all_old;

#if CPY_ON_WRITE_READ_ONLY_FAIL == 1
  all_old = (array_ll_t*) set->array[bucket];
  if (cpy_array_search(all_old, key) == 0)
    {
      return 0;
    }
#endif

  sval_t removed = 0;

  GL_LOCK(set->lock);
  LOCK(set->lock + bucket);
  all_old = (array_ll_t*) set->array[bucket];
  array_ll_t* all_new = array_ll_new(all_old->size - 1);

  int i, n;
  for (i = 0, n = 0; i < all_old->size; i++, n++)
    {
      if (unlikely(all_old->kvs[i].key == key))
	{
	  removed = all_old->kvs[i].val;
	  n--;
	  continue;
	}

      all_new->kvs[n].key = all_old->kvs[i].key;
      all_new->kvs[n].val = all_old->kvs[i].val;
    }

  if (removed)
    {
      set->array[bucket] = all_new;
      ssmem_free(alloc, (void*) all_old);
    }
  else
    {
      ssmem_free(alloc, (void*) all_new);
    }

  GL_UNLOCK(set->lock);
  UNLOCK(set->lock + bucket);
  return removed;
}
Esempio n. 4
0
bool_t bst_help_relocate(operation_t* op, node_t* pred, operation_t* pred_op, node_t* curr, node_t* root){
  CLEANUP_TRY();

	int seen_state = op->relocate_op.state;
	if (seen_state == STATE_OP_ONGOING) {
		// VCAS in original implementation
		operation_t* seen_op = CAS_PTR(&(op->relocate_op.dest->op), op->relocate_op.dest_op, FLAG(op, STATE_OP_RELOCATE));
		if ((seen_op == op->relocate_op.dest_op) || (seen_op == (operation_t *)FLAG(op, STATE_OP_RELOCATE))){
			CAS_U32(&(op->relocate_op.state), STATE_OP_ONGOING, STATE_OP_SUCCESSFUL);
			seen_state = STATE_OP_SUCCESSFUL;
            if (seen_op == op->relocate_op.dest_op) {
#if GC == 1
                if (UNFLAG(seen_op)!=0) ssmem_free(alloc,(void*)UNFLAG(seen_op));
#endif
            } 
		} else {
			// VCAS in original implementation
			seen_state = CAS_U32(&(op->relocate_op.state), STATE_OP_ONGOING, STATE_OP_FAILED);
		}
	}

	if (seen_state == STATE_OP_SUCCESSFUL) {

		skey_t UNUSED dummy0 = CAS_PTR(&(op->relocate_op.dest->key), op->relocate_op.remove_key, op->relocate_op.replace_key);
		skey_t UNUSED dummy1 = CAS_PTR(&(op->relocate_op.dest->value), op->relocate_op.remove_value, op->relocate_op.replace_value);
		void* UNUSED dummy2 = CAS_PTR(&(op->relocate_op.dest->op), FLAG(op, STATE_OP_RELOCATE), FLAG(op, STATE_OP_NONE));
	}
Esempio n. 5
0
void
queue_delete_node(queue_node_t *n)
{
#if GC == 1
  ssmem_free(alloc, (void*) n);
#endif
}
Esempio n. 6
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;
}
Esempio n. 7
0
void
node_delete(node_t *node) 
{
#if GC == 1
  ssmem_free(alloc, node);
#else
  /* ssfree(node); */
#endif
}
Esempio n. 8
0
void
node_delete(node_t *node) 
{
#if GC == 1 && SEQ_SSMEM_NO_FREE != 1
  ssmem_free(alloc, (void*) node);
#else

#endif
}
Esempio n. 9
0
void
node_delete(node_t *node) 
{
#if GC == 1 && SEQ_SSMEM_NO_FREE != 1
  ssmem_free(alloc, node);
#else
  /* ssfree(node); */
#endif
}
Esempio n. 10
0
int
cpy_insert(copy_on_write_t* set, skey_t key, sval_t val) 
{
  size_t bucket = key & set->hash;
  array_ll_t* all_old;

#if CPY_ON_WRITE_READ_ONLY_FAIL == 1
  all_old = (array_ll_t*) set->array[bucket];
  if (cpy_array_search(all_old, key) == 1)
    {
      return 0;
    }
#endif

  GL_LOCK(set->lock);
  LOCK(set->lock + bucket);

  all_old = (array_ll_t*) set->array[bucket];
  array_ll_t* all_new = array_ll_new(all_old->size + 1);

  int i;
  for (i = 0; i < all_old->size; i++)
    {
      if (unlikely(all_old->kvs[i].key == key))
	{
	  ssmem_free(alloc, (void*) all_new);
	  GL_UNLOCK(set->lock);
	  UNLOCK(set->lock + bucket);
	  return 0;
	}
      all_new->kvs[i].key = all_old->kvs[i].key;
      all_new->kvs[i].val = all_old->kvs[i].val;
    }

  all_new->kvs[i].key = key;
  all_new->kvs[i].val = val;
  
  set->array[bucket] = all_new;
  ssmem_free(alloc, (void*) all_old);

  GL_UNLOCK(set->lock);
  UNLOCK(set->lock + bucket);
  return 1;
}
Esempio n. 11
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;
}
Esempio n. 12
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;
}
Esempio n. 13
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;
}
Esempio n. 14
0
sval_t
chm_rem(chm_t* set, skey_t key)
{
  chm_node_t** bucket = &set->table[key & set->hash];

  ptlock_t* seg_lock = &set->locks[key & set->hash_seg];
  LOCK_A(seg_lock);

  chm_node_t* curr = *bucket;

  chm_node_t* pred = NULL;
  while (curr != NULL)
    {
      if (curr->key == key)
	{
	  /* do the remove */
	  if (pred != NULL)
	    {
	      pred->next = curr->next;
	    }
	  else
	    {
	      *bucket = curr->next;
	    }
#if GC == 1
	  ssmem_free(alloc, (void*) curr);
#endif
	  UNLOCK_A(seg_lock);
	  return curr->val;
	}
      pred = curr;
      curr = curr->next;
    }

  UNLOCK_A(seg_lock);
  return 0;
}
Esempio n. 15
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;
}
Esempio n. 16
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;
    }
}
Esempio n. 17
0
void*
test(void* thread) 
{
  size_t num_retry_cas1 = 0, num_retry_cas2 = 0, num_retry_cas3 = 0 , num_retry_cas4 = 0, num_retry_cas5 = 0;
  thread_data_t* td = (thread_data_t*) thread;
  uint8_t ID = td->id;
  phys_id = the_cores[ID % (NUMBER_OF_SOCKETS * CORES_PER_SOCKET)];
  set_cpu(phys_id);

  ssmem_allocator_t* alloc = (ssmem_allocator_t*) memalign(CACHE_LINE_SIZE, sizeof(ssmem_allocator_t));
  assert(alloc != NULL);
  ssmem_alloc_init(alloc, SSMEM_DEFAULT_MEM_SIZE, ID);

  ssmem_gc_thread_init(alloc, ID);

  PF_INIT(3, SSPFD_NUM_ENTRIES, ID);

#if defined(COMPUTE_LATENCY)
  volatile ticks my_putting_succ = 0;
  volatile ticks my_putting_fail = 0;
  volatile ticks my_getting_succ = 0;
  volatile ticks my_getting_fail = 0;
  volatile ticks my_removing_succ = 0;
  volatile ticks my_removing_fail = 0;
#endif
  uint64_t my_putting_count = 0;
  uint64_t my_getting_count = 0;
  uint64_t my_removing_count = 0;

  uint64_t my_putting_count_succ = 0;
  uint64_t my_getting_count_succ = 0;
  uint64_t my_removing_count_succ = 0;
    
#if defined(COMPUTE_LATENCY) && PFD_TYPE == 0
  volatile ticks start_acq, end_acq;
  volatile ticks correction = getticks_correction_calc();
#endif
    
  seeds = seed_rand();
    
  MEM_BARRIER;

  barrier_cross(&barrier);

  barrier_cross(&barrier_global);

  size_t obj_size_bytes = obj_size * sizeof(size_t);
  volatile size_t* dat = (size_t*) malloc(obj_size_bytes);
  assert(dat != NULL);

  size_t* obj = NULL;

  while (stop == 0) 
    {
      size_t rand = (my_random(&(seeds[0]), &(seeds[1]), &(seeds[2])));
      size_t k = (rand & 1) + 2;
      rand &= 1023;

      /* search baby! */

      int i;
      for (i = 0; i < KEY_BUCKT; i++)
	{
	  volatile uintptr_t v = val[i];
	  if (snap->map[i] == MAP_VALID && key[i] == k)
	    {
	      if (val[i] == v)
		{
		  if (GET_VAL(v) != k)
		    {
		      printf("[%02d] :get: key != val for %zu\n", ID, k);
		    }
		  break;
		}
	    }
	}

      if (rand > 513)
	{
	  my_putting_count++;

	  if (obj != NULL)
	    {
	      ssmem_free(alloc, (void*) obj);
	    }
	  obj = ssmem_alloc(alloc, 8);
	  *obj = k;


	  int empty_index = -2;
	  clht_snapshot_t s;

	retry:
	  s.snapshot = snap->snapshot;

	  int i;
	  for (i = 0; i < KEY_BUCKT; i++)
	    {
	      volatile uintptr_t v = val[i];
	      if (snap->map[i] == MAP_VALID && key[i] == k)
		{
		  if (val[i] == v)
		    {
		      if (empty_index > 0)
			{
			  snap->map[empty_index] = MAP_INVLD;
			}
		      goto end;
		    }
		}
	    }

	  clht_snapshot_all_t s1;
	  if (empty_index < 0)
	    {
	      empty_index = snap_get_empty_index(s.snapshot);
	      if (empty_index < 0)
		{
		  num_retry_cas1++;
		  goto end;
		}

	      s1 = snap_set_map(s.snapshot, empty_index, MAP_INSRT);
	      if (CAS_U64(&snap->snapshot, s.snapshot, s1) != s.snapshot)
		{
		  empty_index = -2;
		  num_retry_cas2++;
		  goto retry;
		}

	      val[empty_index] = (uintptr_t) obj;
	      key[empty_index] = k;
	    }
	  else
	    {
	      s1 = snap_set_map(s.snapshot, empty_index, MAP_INSRT);
	    }

	  clht_snapshot_all_t s2 = snap_set_map_and_inc_version(s1, empty_index, MAP_VALID);
	  if (CAS_U64(&snap->snapshot, s1, s2) != s1)
	    {
	      num_retry_cas3++;
	      /* key[empty_index] = 0; */
	      /* val[empty_index] = 0; */
	      goto retry;
	    }

	  obj = NULL;
	  my_putting_count_succ++;
	end:
	  ;
	}
      else
	{
	  my_removing_count++;
	  clht_snapshot_t s;

	retry_rem:
	  s.snapshot = snap->snapshot;

	  volatile uintptr_t v; 
	  int i, removed = 0;
	  for (i = 0; i < KEY_BUCKT && !removed; i++)
	    {
	      if (key[i] == k && s.map[i] == MAP_VALID)
		{
		  v = val[i];
		  clht_snapshot_all_t s1 = snap_set_map(s.snapshot, i, MAP_INVLD);
		  if (CAS_U64(&snap->snapshot, s.snapshot, s1) == s.snapshot)
		    {
		      /* snap->map[i] = MAP_INVLD; */
		      removed = 1;
		    }
		  else
		    {
		      num_retry_cas4++;
		      goto retry_rem;
		    }
		}
	    }
	  if (removed)
	    {
	      ssmem_free(alloc, (void*) v);
	      my_removing_count_succ++;
	    }
	}
    }

  free((void*) dat);
   
#if defined(DEBUG)
  if (put_num_restarts | put_num_failed_expand | put_num_failed_on_new)
    {
      /* printf("put_num_restarts = %3u / put_num_failed_expand = %3u / put_num_failed_on_new = %3u \n", */
      /* 	     put_num_restarts, put_num_failed_expand, put_num_failed_on_new); */
    }
#endif

  if (ID < 2)
    {
      printf("#retry-stats-thread-%d: #cas1: %-8zu / #cas2: %-8zu /"
	     "#cas3: %-8zu / #cas4: %-8zu / #cas5: %-8zu\n", 
	     ID, num_retry_cas1, num_retry_cas2, num_retry_cas3, num_retry_cas4, num_retry_cas5);
    }

  /* printf("gets: %-10llu / succ: %llu\n", num_get, num_get_succ); */
  /* printf("rems: %-10llu / succ: %llu\n", num_rem, num_rem_succ); */
  barrier_cross(&barrier);

#if defined(COMPUTE_LATENCY)
  putting_succ[ID] += my_putting_succ;
  putting_fail[ID] += my_putting_fail;
  getting_succ[ID] += my_getting_succ;
  getting_fail[ID] += my_getting_fail;
  removing_succ[ID] += my_removing_succ;
  removing_fail[ID] += my_removing_fail;
#endif
  putting_count[ID] += my_putting_count;
  getting_count[ID] += my_getting_count;
  removing_count[ID]+= my_removing_count;

  putting_count_succ[ID] += my_putting_count_succ;
  getting_count_succ[ID] += my_getting_count_succ;
  removing_count_succ[ID]+= my_removing_count_succ;

#if (PFD_TYPE == 1) && defined(COMPUTE_LATENCY)
  if (ID == 0)
    {
      printf("get ----------------------------------------------------\n");
      SSPFDPN(0, SSPFD_NUM_ENTRIES, print_vals_num);
      printf("put ----------------------------------------------------\n");
      SSPFDPN(1, SSPFD_NUM_ENTRIES, print_vals_num);
      printf("rem ----------------------------------------------------\n");
      SSPFDPN(2, SSPFD_NUM_ENTRIES, print_vals_num);

    }
#endif

  /* SSPFDTERM(); */

  pthread_exit(NULL);
}
Esempio 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
            }
		}
	}
}
Esempio n. 19
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;
	}
    }
}