static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec, uint32_t hash) { struct sss_mc_rec *cur; uint32_t slot; slot = mcc->hash_table[hash]; if (slot == MC_INVALID_VAL) { /* no previous record/collision, just add to hash table */ mcc->hash_table[hash] = MC_PTR_TO_SLOT(mcc->data_table, rec); return; } do { cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec); if (cur == rec) { /* rec already stored in hash chain */ return; } slot = cur->next; } while (slot != MC_INVALID_VAL); /* end of chain, append our record here */ /* changing a single uint32_t is atomic, so there is no * need to use barriers in this case */ cur->next = MC_PTR_TO_SLOT(mcc->data_table, rec); }
static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec, uint32_t hash) { struct sss_mc_rec *cur; uint32_t slot; if (hash > MC_HT_ELEMS(mcc->ht_size)) { /* Invalid hash. This should never happen, but better * return than trying to access out of bounds memory */ return; } slot = mcc->hash_table[hash]; if (slot == MC_INVALID_VAL) { /* no previous record/collision, just add to hash table */ mcc->hash_table[hash] = MC_PTR_TO_SLOT(mcc->data_table, rec); return; } do { cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec); if (cur == rec) { /* rec already stored in hash chain */ return; } slot = sss_mc_next_slot_with_hash(cur, hash); } while (slot != MC_INVALID_VAL); /* end of chain, append our record here */ slot = MC_PTR_TO_SLOT(mcc->data_table, rec); sss_mc_chain_slot_to_record_with_hash(cur, hash, slot); }
static void sss_mc_free_slots(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec) { uint32_t slot; uint32_t num; uint32_t i; slot = MC_PTR_TO_SLOT(mcc->data_table, rec); num = MC_SIZE_TO_SLOTS(rec->len); for (i = 0; i < num; i++) { MC_CLEAR_BIT(mcc->free_table, slot + i); } }
static struct sss_mc_rec *sss_mc_get_record(struct sss_mc_ctx *mcc, size_t rec_len, struct sized_string *key) { struct sss_mc_rec *old_rec = NULL; struct sss_mc_rec *rec; int old_slots; int num_slots; uint32_t base_slot; int i; num_slots = MC_SIZE_TO_SLOTS(rec_len); old_rec = sss_mc_find_record(mcc, key); if (old_rec) { old_slots = MC_SIZE_TO_SLOTS(old_rec->len); if (old_slots == num_slots) { return old_rec; } /* slot size changed, invalidate record and fall through to get a * fully new record */ base_slot = MC_PTR_TO_SLOT(mcc->data_table, old_rec); sss_mc_invalidate_rec(mcc, old_rec); /* and now free slots */ for (i = 0; i < old_slots; i++) { MC_CLEAR_BIT(mcc->free_table, base_slot + i); } } /* we are going to use more space, find enough free slots */ base_slot = sss_mc_find_free_slots(mcc, num_slots); rec = MC_SLOT_TO_PTR(mcc->data_table, base_slot, struct sss_mc_rec); /* mark as not valid yet */ MC_RAISE_INVALID_BARRIER(rec); rec->len = rec_len; rec->next = MC_INVALID_VAL; MC_LOWER_BARRIER(rec); /* and now mark slots as used */ for (i = 0; i < num_slots; i++) { MC_SET_BIT(mcc->free_table, base_slot + i); } return rec; }