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; }
/* FIXME: This is a very simplistic, inefficient, memory allocator, * it will just free the oldest entries regardless of expiration if it * cycled the whole freebits map and found no empty slot */ static int sss_mc_find_free_slots(struct sss_mc_ctx *mcc, int num_slots) { struct sss_mc_rec *rec; uint32_t tot_slots; uint32_t cur; uint32_t i; uint32_t t; bool used; tot_slots = mcc->ft_size * 8; /* Try to find a free slot w/o removing a nything first */ /* FIXME: is it really worth it ? May be it is easier to * just recycle the next set of slots ? */ if ((mcc->next_slot + num_slots) > tot_slots) { cur = 0; } else { cur = mcc->next_slot; } /* search for enough (num_slots) consecutive zero bits, indicating * consecutive empty slots */ for (i = 0; i < mcc->ft_size; i++) { t = cur / 8; /* if all full in this byte skip directly to the next */ if (mcc->free_table[t] == 0xff) { cur = ((cur + 8) & ~7); if (cur >= tot_slots) { cur = 0; } continue; } /* at least one bit in this byte is marked as empty */ for (t = ((cur + 8) & ~7) ; cur < t; cur++) { MC_PROBE_BIT(mcc->free_table, cur, used); if (!used) break; } /* check if we have enough slots before hitting the table end */ if ((cur + num_slots) > tot_slots) { cur = 0; continue; } /* check if we have at least num_slots empty starting from the first * we found in the previous steps */ for (t = cur + num_slots; cur < t; cur++) { MC_PROBE_BIT(mcc->free_table, cur, used); if (used) break; } if (cur == t) { /* ok found num_slots consecutive free bits */ return cur - num_slots; } } /* no free slots found, free occupied slots after next_slot */ if ((mcc->next_slot + num_slots) > tot_slots) { cur = 0; } else { cur = mcc->next_slot; } for (i = 0; i < num_slots; i++) { MC_PROBE_BIT(mcc->free_table, cur + i, used); if (!used) continue; rec = MC_SLOT_TO_PTR(mcc->data_table, cur + i, struct sss_mc_rec); for (t = i + MC_SIZE_TO_SLOTS(rec->len); i < t; i++) { MC_CLEAR_BIT(mcc->free_table, cur + i); } sss_mc_invalidate_rec(mcc, rec); } mcc->next_slot = cur + num_slots; return cur; }