static struct pgt *pop_from_cache_list(vaddr_t vabase, void *ctx) { struct pgt *pgt; struct pgt *p; pgt = SLIST_FIRST(&pgt_cache_list); if (!pgt) return NULL; if (match_pgt(pgt, vabase, ctx)) { SLIST_REMOVE_HEAD(&pgt_cache_list, link); return pgt; } while (true) { p = SLIST_NEXT(pgt, link); if (!p) break; if (match_pgt(p, vabase, ctx)) { SLIST_REMOVE_AFTER(pgt, link); break; } pgt = p; } return p; }
static struct pgt *pop_least_used_from_cache_list(void) { struct pgt *pgt; struct pgt *p_prev = NULL; size_t least_used; pgt = SLIST_FIRST(&pgt_cache_list); if (!pgt) return NULL; if (!pgt->num_used_entries) goto out; least_used = pgt->num_used_entries; while (true) { if (!SLIST_NEXT(pgt, link)) break; if (SLIST_NEXT(pgt, link)->num_used_entries <= least_used) { p_prev = pgt; least_used = SLIST_NEXT(pgt, link)->num_used_entries; } pgt = SLIST_NEXT(pgt, link); } out: if (p_prev) { pgt = SLIST_NEXT(p_prev, link); SLIST_REMOVE_AFTER(p_prev, link); } else { pgt = SLIST_FIRST(&pgt_cache_list); SLIST_REMOVE_HEAD(&pgt_cache_list, link); } return pgt; }
void hashtable_delete(const char *key, uint32_t klen, struct hash_table *ht) { struct item_slh *bucket; struct item *it, *prev; ASSERT(hashtable_get(key, klen, ht) != NULL); bucket = _get_bucket(key, klen, ht); for (prev = NULL, it = SLIST_FIRST(bucket); it != NULL; prev = it, it = SLIST_NEXT(it, i_sle)) { /* iterate through bucket to find item to be removed */ if ((klen == it->klen) && cc_memcmp(key, item_key(it), klen) == 0) { /* found item */ break; } } if (prev == NULL) { SLIST_REMOVE_HEAD(bucket, i_sle); } else { SLIST_REMOVE_AFTER(prev, i_sle); } --(ht->nhash_item); }
static void flush_ctx_range_from_list(struct pgt_cache *pgt_cache, void *ctx, vaddr_t begin, vaddr_t last) { struct pgt *p; struct pgt *next_p; /* * Do the special case where the first element in the list is * removed first. */ p = SLIST_FIRST(pgt_cache); while (pgt_entry_matches(p, ctx, begin, last)) { flush_pgt_entry(p); SLIST_REMOVE_HEAD(pgt_cache, link); push_to_free_list(p); p = SLIST_FIRST(pgt_cache); } /* * p either points to the first element in the list or it's NULL, * if NULL the list is empty and we're done. */ if (!p) return; /* * Do the common case where the next element in the list is * removed. */ while (true) { next_p = SLIST_NEXT(p, link); if (!next_p) break; if (pgt_entry_matches(next_p, ctx, begin, last)) { flush_pgt_entry(next_p); SLIST_REMOVE_AFTER(p, link); push_to_free_list(next_p); continue; } p = SLIST_NEXT(p, link); } }
void pgt_flush_ctx(struct tee_ta_ctx *ctx) { struct pgt *p; struct pgt *pp = NULL; mutex_lock(&pgt_mu); while (true) { p = SLIST_FIRST(&pgt_cache_list); if (!p) goto out; if (p->ctx != ctx) break; SLIST_REMOVE_HEAD(&pgt_cache_list, link); tee_pager_pgt_save_and_release_entries(p); assert(!p->num_used_entries); p->ctx = NULL; p->vabase = 0; push_to_free_list(p); } pp = p; while (true) { p = SLIST_NEXT(pp, link); if (!p) break; if (p->ctx == ctx) { SLIST_REMOVE_AFTER(pp, link); tee_pager_pgt_save_and_release_entries(p); assert(!p->num_used_entries); p->ctx = NULL; p->vabase = 0; push_to_free_list(p); } else { pp = p; } } out: mutex_unlock(&pgt_mu); }