Lines Matching refs:lc
41 BUG_ON(!lc); \
42 BUG_ON(!lc->nr_elements); \
43 BUG_ON(test_and_set_bit(__LC_PARANOIA, &lc->flags)); \
47 clear_bit_unlock(__LC_PARANOIA, &lc->flags); \
51 #define PARANOIA_LC_ELEMENT(lc, e) do { \ argument
52 struct lru_cache *lc_ = (lc); \
67 int lc_try_lock(struct lru_cache *lc) in lc_try_lock() argument
71 val = cmpxchg(&lc->flags, 0, LC_LOCKED); in lc_try_lock()
80 old = lc->flags & LC_PARANOIA; in lc_try_lock()
82 val = cmpxchg(&lc->flags, old, new); in lc_try_lock()
105 struct lru_cache *lc; in lc_create() local
126 lc = kzalloc(sizeof(*lc), GFP_KERNEL); in lc_create()
127 if (!lc) in lc_create()
130 INIT_LIST_HEAD(&lc->in_use); in lc_create()
131 INIT_LIST_HEAD(&lc->lru); in lc_create()
132 INIT_LIST_HEAD(&lc->free); in lc_create()
133 INIT_LIST_HEAD(&lc->to_be_changed); in lc_create()
135 lc->name = name; in lc_create()
136 lc->element_size = e_size; in lc_create()
137 lc->element_off = e_off; in lc_create()
138 lc->nr_elements = e_count; in lc_create()
139 lc->max_pending_changes = max_pending_changes; in lc_create()
140 lc->lc_cache = cache; in lc_create()
141 lc->lc_element = element; in lc_create()
142 lc->lc_slot = slot; in lc_create()
149 memset(p, 0, lc->element_size); in lc_create()
154 list_add(&e->list, &lc->free); in lc_create()
158 return lc; in lc_create()
165 kfree(lc); in lc_create()
172 static void lc_free_by_index(struct lru_cache *lc, unsigned i) in lc_free_by_index() argument
174 void *p = lc->lc_element[i]; in lc_free_by_index()
177 p -= lc->element_off; in lc_free_by_index()
178 kmem_cache_free(lc->lc_cache, p); in lc_free_by_index()
186 void lc_destroy(struct lru_cache *lc) in lc_destroy() argument
189 if (!lc) in lc_destroy()
191 for (i = 0; i < lc->nr_elements; i++) in lc_destroy()
192 lc_free_by_index(lc, i); in lc_destroy()
193 kfree(lc->lc_element); in lc_destroy()
194 kfree(lc->lc_slot); in lc_destroy()
195 kfree(lc); in lc_destroy()
205 void lc_reset(struct lru_cache *lc) in lc_reset() argument
209 INIT_LIST_HEAD(&lc->in_use); in lc_reset()
210 INIT_LIST_HEAD(&lc->lru); in lc_reset()
211 INIT_LIST_HEAD(&lc->free); in lc_reset()
212 INIT_LIST_HEAD(&lc->to_be_changed); in lc_reset()
213 lc->used = 0; in lc_reset()
214 lc->hits = 0; in lc_reset()
215 lc->misses = 0; in lc_reset()
216 lc->starving = 0; in lc_reset()
217 lc->locked = 0; in lc_reset()
218 lc->changed = 0; in lc_reset()
219 lc->pending_changes = 0; in lc_reset()
220 lc->flags = 0; in lc_reset()
221 memset(lc->lc_slot, 0, sizeof(struct hlist_head) * lc->nr_elements); in lc_reset()
223 for (i = 0; i < lc->nr_elements; i++) { in lc_reset()
224 struct lc_element *e = lc->lc_element[i]; in lc_reset()
226 p -= lc->element_off; in lc_reset()
227 memset(p, 0, lc->element_size); in lc_reset()
232 list_add(&e->list, &lc->free); in lc_reset()
241 size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) in lc_seq_printf_stats() argument
251 lc->name, lc->used, lc->nr_elements, in lc_seq_printf_stats()
252 lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); in lc_seq_printf_stats()
257 static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) in lc_hash_slot() argument
259 return lc->lc_slot + (enr % lc->nr_elements); in lc_hash_slot()
263 static struct lc_element *__lc_find(struct lru_cache *lc, unsigned int enr, in __lc_find() argument
268 BUG_ON(!lc); in __lc_find()
269 BUG_ON(!lc->nr_elements); in __lc_find()
270 hlist_for_each_entry(e, lc_hash_slot(lc, enr), colision) { in __lc_find()
294 struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr) in lc_find() argument
296 return __lc_find(lc, enr, 0); in lc_find()
309 bool lc_is_used(struct lru_cache *lc, unsigned int enr) in lc_is_used() argument
311 struct lc_element *e = __lc_find(lc, enr, 1); in lc_is_used()
323 void lc_del(struct lru_cache *lc, struct lc_element *e) in lc_del() argument
326 PARANOIA_LC_ELEMENT(lc, e); in lc_del()
331 list_move(&e->list, &lc->free); in lc_del()
335 static struct lc_element *lc_prepare_for_change(struct lru_cache *lc, unsigned new_number) in lc_prepare_for_change() argument
340 if (!list_empty(&lc->free)) in lc_prepare_for_change()
341 n = lc->free.next; in lc_prepare_for_change()
342 else if (!list_empty(&lc->lru)) in lc_prepare_for_change()
343 n = lc->lru.prev; in lc_prepare_for_change()
348 PARANOIA_LC_ELEMENT(lc, e); in lc_prepare_for_change()
353 hlist_add_head(&e->colision, lc_hash_slot(lc, new_number)); in lc_prepare_for_change()
354 list_move(&e->list, &lc->to_be_changed); in lc_prepare_for_change()
359 static int lc_unused_element_available(struct lru_cache *lc) in lc_unused_element_available() argument
361 if (!list_empty(&lc->free)) in lc_unused_element_available()
363 if (!list_empty(&lc->lru)) in lc_unused_element_available()
375 static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, unsigned int flags) in __lc_get() argument
380 if (lc->flags & LC_STARVING) { in __lc_get()
381 ++lc->starving; in __lc_get()
385 e = __lc_find(lc, enr, 1); in __lc_get()
401 ++lc->hits; in __lc_get()
405 ++lc->hits; in __lc_get()
407 lc->used++; in __lc_get()
408 list_move(&e->list, &lc->in_use); /* Not evictable... */ in __lc_get()
413 ++lc->misses; in __lc_get()
419 test_and_set_bit(__LC_DIRTY, &lc->flags); in __lc_get()
424 if (test_bit(__LC_LOCKED, &lc->flags)) { in __lc_get()
425 ++lc->locked; in __lc_get()
432 if (!lc_unused_element_available(lc)) { in __lc_get()
433 __set_bit(__LC_STARVING, &lc->flags); in __lc_get()
440 if (lc->pending_changes >= lc->max_pending_changes) in __lc_get()
443 e = lc_prepare_for_change(lc, enr); in __lc_get()
446 clear_bit(__LC_STARVING, &lc->flags); in __lc_get()
448 lc->used++; in __lc_get()
449 lc->pending_changes++; in __lc_get()
494 struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr) in lc_get() argument
496 return __lc_get(lc, enr, LC_GET_MAY_CHANGE); in lc_get()
514 struct lc_element *lc_get_cumulative(struct lru_cache *lc, unsigned int enr) in lc_get_cumulative() argument
516 return __lc_get(lc, enr, LC_GET_MAY_CHANGE|LC_GET_MAY_USE_UNCOMMITTED); in lc_get_cumulative()
535 struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr) in lc_try_get() argument
537 return __lc_get(lc, enr, 0); in lc_try_get()
548 void lc_committed(struct lru_cache *lc) in lc_committed() argument
553 list_for_each_entry_safe(e, tmp, &lc->to_be_changed, list) { in lc_committed()
555 ++lc->changed; in lc_committed()
557 list_move(&e->list, &lc->in_use); in lc_committed()
559 lc->pending_changes = 0; in lc_committed()
573 unsigned int lc_put(struct lru_cache *lc, struct lc_element *e) in lc_put() argument
576 PARANOIA_LC_ELEMENT(lc, e); in lc_put()
581 list_move(&e->list, &lc->lru); in lc_put()
582 lc->used--; in lc_put()
583 clear_bit_unlock(__LC_STARVING, &lc->flags); in lc_put()
593 struct lc_element *lc_element_by_index(struct lru_cache *lc, unsigned i) in lc_element_by_index() argument
595 BUG_ON(i >= lc->nr_elements); in lc_element_by_index()
596 BUG_ON(lc->lc_element[i] == NULL); in lc_element_by_index()
597 BUG_ON(lc->lc_element[i]->lc_index != i); in lc_element_by_index()
598 return lc->lc_element[i]; in lc_element_by_index()
606 unsigned int lc_index_of(struct lru_cache *lc, struct lc_element *e) in lc_index_of() argument
608 PARANOIA_LC_ELEMENT(lc, e); in lc_index_of()
620 void lc_set(struct lru_cache *lc, unsigned int enr, int index) in lc_set() argument
625 if (index < 0 || index >= lc->nr_elements) in lc_set()
628 e = lc_element_by_index(lc, index); in lc_set()
635 lh = &lc->free; in lc_set()
637 hlist_add_head(&e->colision, lc_hash_slot(lc, enr)); in lc_set()
638 lh = &lc->lru; in lc_set()
652 void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char *utext, in lc_seq_dump_details() argument
655 unsigned int nr_elements = lc->nr_elements; in lc_seq_dump_details()
661 e = lc_element_by_index(lc, i); in lc_seq_dump_details()