static void * critbit_delete_inplace(critbit_root *root, const char *key, int keylen) { if(!root->head) return NULL; const uint8_t *bytes = (void *)key; uint8_t *p = root->head; void **wherep = &root->head, **whereq = 0; critbit_node *q = NULL; int dir = 0; while(IS_INTERNAL(p)) { whereq = wherep; q = TO_NODE(p); dir = get_direction(q, bytes, keylen); wherep = q->child + dir; p = *wherep; } if(strcmp(key, (const char *)p) != 0) { return NULL; } if(!whereq) { root->head = NULL; return p; } *whereq = q->child[1 - dir]; __sync_synchronize(); return FROM_NODE(q); }
static void clear_node(void *p) { if(IS_INTERNAL(p)) { // Internal node critbit_node *node = TO_NODE(p); clear_node(node->child[0]); clear_node(node->child[1]); free(node); } else { free_string(p); } }
int critbit_delete(critbit_root *root, const char *key) { const size_t len = strlen(key); // begin critical section pthread_mutex_lock(&root->wlock); void * p = critbit_delete_inplace(root, key, len); pthread_rwlock_t *lock = root->cur_rwlock; pthread_rwlock_t *newlock = root->prev_rwlock; // swap two locks if(!__sync_val_compare_and_swap(&root->cur_rwlock, lock, newlock)) { printf("!!!\n"); } if(!__sync_val_compare_and_swap(&root->prev_rwlock, newlock, lock)) { printf("!!!\n"); } // wait until all readers are out pthread_rwlock_wrlock(lock); pthread_rwlock_unlock(lock); // end critical section pthread_mutex_unlock(&root->wlock); if(!p) return 1; if(!IS_INTERNAL(p)) { free_string(p); } else { critbit_node *node = TO_NODE(p); if(!IS_INTERNAL(node->child[0]) && strcmp(key, (const char *)node->child[0]) == 0) { free_string(node->child[0]); free_node(root, node); } else { free_string(node->child[1]); free_node(root, node); } } return 0; }
/* * Locate a nasid which doesn't exist. Perform a bte_copy from that * node to our local node. */ static int brt_tst_invalid_xfers(void) { int i; int free_nasid = -1; int cpu; int error_cnt; u64 ret_code; if (ix_srcnasid != -1) { free_nasid = ix_srcnasid; } else { /* Only looking for nasids from C-Nodes. */ for (i = 0; i < PLAT_MAX_NODE_NUMBER; i += 2) { if (local_node_data->physical_node_map[i] == -1) { free_nasid = i; break; } } } if (free_nasid == -1) { printk("tst_invalid_xfers: No free nodes found. " "Exiting.\n"); return (0); } printk("tst_invalid_xfers: Using source nasid of %d\n", free_nasid); error_cnt = 0; for (i = 0; i < ix_iterations; i++) { if (verbose >= 1) { printk("-------------------------------" "-------------------------------" "--------------\n"); } if ((verbose >= 1) || !(i % 10)) { printk(" Loop %d\n", i); } for (cpu = 0; cpu < smp_num_cpus; cpu++) { set_cpus_allowed(current, (1UL << cpu)); if (verbose > 1) { printk("Testing with CPU %d\n", smp_processor_id()); } /* >>> Need a better means of calculating a * remote addr. */ ret_code = bte_copy(TO_NODE(free_nasid, 0), __pa(nodepda->bte_if[0]. bte_test_buf), 4 * L1_CACHE_BYTES, BTE_NOTIFY, NULL); error_cnt += (ret_code ? 1 : 0); } } ret_code = ((error_cnt != (ix_iterations * smp_num_cpus)) ? 1 : 0); return (ret_code); }
static int critbit_insert_inplace(critbit_root *root, const char *key, int keylen, const void* value) { const uint8_t *bytes = (void *)key; uint8_t *p = root->head; if(!p) { p = alloc_string(key, keylen, value); if(!p) return 1; root->head = p; return 0; } p = find_nearest(root->head, bytes, keylen); uint32_t newbyte; uint8_t newotherbits; for(newbyte = 0; newbyte < keylen; ++newbyte) { if(p[newbyte] != bytes[newbyte]) { newotherbits = p[newbyte] ^ bytes[newbyte]; goto found; } } if(p[newbyte]) { newotherbits = p[newbyte]; goto found; } return 1; found: while(newotherbits & (newotherbits - 1)) { newotherbits &= newotherbits - 1; } newotherbits ^= 0xFF; uint8_t c = p[newbyte]; int newdirection = (1 + (newotherbits | c)) >> 8; struct critbit_node *node = alloc_aligned(sizeof(struct critbit_node)); if(!node) return 1; char *x = alloc_string(key, keylen, value); if(!x) { free(node); return 1; } node->byte = newbyte; node->otherbits = newotherbits; node->child[1 - newdirection] = x; void **wherep = &root->head; for(;;) { uint8_t *p = *wherep; if(!IS_INTERNAL(p)) break; struct critbit_node *q = TO_NODE(p); if(q->byte > newbyte) break; if(q->byte == newbyte && q->otherbits > newotherbits) break; wherep = q->child + get_direction(q, bytes, keylen); } node->child[newdirection] = *wherep; __sync_synchronize(); *wherep = FROM_NODE(node); __sync_synchronize(); return 0; }