bool ck_hs_grow(struct ck_hs *hs, unsigned long capacity) { struct ck_hs_map *map, *update; void **bucket, *previous; unsigned long k, i, j, offset, probes; restart: map = hs->map; if (map->capacity > capacity) return false; update = ck_hs_map_create(hs, capacity); if (update == NULL) return false; for (k = 0; k < map->capacity; k++) { unsigned long h; previous = map->entries[k]; if (previous == CK_HS_EMPTY || previous == CK_HS_TOMBSTONE) continue; #ifdef CK_HS_PP if (hs->mode & CK_HS_MODE_OBJECT) previous = (void *)((uintptr_t)previous & (((uintptr_t)1 << CK_MD_VMA_BITS) - 1)); #endif h = hs->hf(previous, hs->seed); offset = h & update->mask; i = probes = 0; for (;;) { bucket = (void *)((uintptr_t)&update->entries[offset] & ~(CK_MD_CACHELINE - 1)); for (j = 0; j < CK_HS_PROBE_L1; j++) { void **cursor = bucket + ((j + offset) & (CK_HS_PROBE_L1 - 1)); if (probes++ == update->probe_limit) break; if (CK_CC_LIKELY(*cursor == CK_HS_EMPTY)) { *cursor = map->entries[k]; update->n_entries++; if (probes > update->probe_maximum) update->probe_maximum = probes; break; } } if (j < CK_HS_PROBE_L1) break; offset = ck_hs_map_probe_next(update, offset, h, i++, probes); } if (probes > update->probe_limit) { /* * We have hit the probe limit, map needs to be even larger. */ ck_hs_map_destroy(hs->m, update, false); capacity <<= 1; goto restart; } } ck_pr_fence_store(); ck_pr_store_ptr(&hs->map, update); ck_hs_map_destroy(hs->m, map, true); return true; }
bool ck_rhs_grow(struct ck_rhs *hs, unsigned long capacity) { struct ck_rhs_map *map, *update; void *previous, *prev_saved; unsigned long k, offset, probes; restart: map = hs->map; if (map->capacity > capacity) return false; update = ck_rhs_map_create(hs, capacity); if (update == NULL) return false; for (k = 0; k < map->capacity; k++) { unsigned long h; prev_saved = previous = ck_rhs_entry(map, k); if (previous == CK_RHS_EMPTY) continue; #ifdef CK_RHS_PP if (hs->mode & CK_RHS_MODE_OBJECT) previous = CK_RHS_VMA(previous); #endif h = hs->hf(previous, hs->seed); offset = h & update->mask; probes = 0; for (;;) { void **cursor = ck_rhs_entry_addr(update, offset); if (probes++ == update->probe_limit) { /* * We have hit the probe limit, map needs to be even larger. */ ck_rhs_map_destroy(hs->m, update, false); capacity <<= 1; goto restart; } if (CK_CC_LIKELY(*cursor == CK_RHS_EMPTY)) { *cursor = prev_saved; update->n_entries++; ck_rhs_set_probes(update, offset, probes); ck_rhs_map_bound_set(update, h, probes); break; } else if (ck_rhs_probes(update, offset) < probes) { void *tmp = prev_saved; unsigned int old_probes; prev_saved = previous = *cursor; #ifdef CK_RHS_PP if (hs->mode & CK_RHS_MODE_OBJECT) previous = CK_RHS_VMA(previous); #endif *cursor = tmp; ck_rhs_map_bound_set(update, h, probes); h = hs->hf(previous, hs->seed); old_probes = ck_rhs_probes(update, offset); ck_rhs_set_probes(update, offset, probes); probes = old_probes - 1; continue; } ck_rhs_wanted_inc(update, offset); offset = ck_rhs_map_probe_next(update, offset, probes); } } ck_pr_fence_store(); ck_pr_store_ptr(&hs->map, update); ck_rhs_map_destroy(hs->m, map, true); return true; }