Lines Matching refs:lc
29 BUG_ON(!lc); \
30 BUG_ON(!lc->nr_elements); \
31 BUG_ON(test_and_set_bit(__LC_PARANOIA, &lc->flags)); \
35 clear_bit_unlock(__LC_PARANOIA, &lc->flags); \
39 #define PARANOIA_LC_ELEMENT(lc, e) do { \ argument
40 struct lru_cache *lc_ = (lc); \
55 int lc_try_lock(struct lru_cache *lc) in lc_try_lock() argument
59 val = cmpxchg(&lc->flags, 0, LC_LOCKED); in lc_try_lock()
68 old = lc->flags & LC_PARANOIA; in lc_try_lock()
70 val = cmpxchg(&lc->flags, old, new); in lc_try_lock()
94 struct lru_cache *lc; in lc_create() local
115 lc = kzalloc(sizeof(*lc), GFP_KERNEL); in lc_create()
116 if (!lc) in lc_create()
119 INIT_LIST_HEAD(&lc->in_use); in lc_create()
120 INIT_LIST_HEAD(&lc->lru); in lc_create()
121 INIT_LIST_HEAD(&lc->free); in lc_create()
122 INIT_LIST_HEAD(&lc->to_be_changed); in lc_create()
124 lc->name = name; in lc_create()
125 lc->element_size = e_size; in lc_create()
126 lc->element_off = e_off; in lc_create()
127 lc->nr_elements = e_count; in lc_create()
128 lc->max_pending_changes = max_pending_changes; in lc_create()
129 lc->lc_cache = cache; in lc_create()
130 lc->lc_element = element; in lc_create()
131 lc->lc_slot = slot; in lc_create()
138 memset(p, 0, lc->element_size); in lc_create()
143 list_add(&e->list, &lc->free); in lc_create()
147 return lc; in lc_create()
154 kfree(lc); in lc_create()
161 static void lc_free_by_index(struct lru_cache *lc, unsigned i) in lc_free_by_index() argument
163 void *p = lc->lc_element[i]; in lc_free_by_index()
166 p -= lc->element_off; in lc_free_by_index()
167 kmem_cache_free(lc->lc_cache, p); in lc_free_by_index()
175 void lc_destroy(struct lru_cache *lc) in lc_destroy() argument
178 if (!lc) in lc_destroy()
180 for (i = 0; i < lc->nr_elements; i++) in lc_destroy()
181 lc_free_by_index(lc, i); in lc_destroy()
182 kfree(lc->lc_element); in lc_destroy()
183 kfree(lc->lc_slot); in lc_destroy()
184 kfree(lc); in lc_destroy()
194 void lc_reset(struct lru_cache *lc) in lc_reset() argument
198 INIT_LIST_HEAD(&lc->in_use); in lc_reset()
199 INIT_LIST_HEAD(&lc->lru); in lc_reset()
200 INIT_LIST_HEAD(&lc->free); in lc_reset()
201 INIT_LIST_HEAD(&lc->to_be_changed); in lc_reset()
202 lc->used = 0; in lc_reset()
203 lc->hits = 0; in lc_reset()
204 lc->misses = 0; in lc_reset()
205 lc->starving = 0; in lc_reset()
206 lc->locked = 0; in lc_reset()
207 lc->changed = 0; in lc_reset()
208 lc->pending_changes = 0; in lc_reset()
209 lc->flags = 0; in lc_reset()
210 memset(lc->lc_slot, 0, sizeof(struct hlist_head) * lc->nr_elements); in lc_reset()
212 for (i = 0; i < lc->nr_elements; i++) { in lc_reset()
213 struct lc_element *e = lc->lc_element[i]; in lc_reset()
215 p -= lc->element_off; in lc_reset()
216 memset(p, 0, lc->element_size); in lc_reset()
221 list_add(&e->list, &lc->free); in lc_reset()
230 void lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) in lc_seq_printf_stats() argument
240 lc->name, lc->used, lc->nr_elements, in lc_seq_printf_stats()
241 lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); in lc_seq_printf_stats()
244 static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) in lc_hash_slot() argument
246 return lc->lc_slot + (enr % lc->nr_elements); in lc_hash_slot()
250 static struct lc_element *__lc_find(struct lru_cache *lc, unsigned int enr, in __lc_find() argument
255 BUG_ON(!lc); in __lc_find()
256 BUG_ON(!lc->nr_elements); in __lc_find()
257 hlist_for_each_entry(e, lc_hash_slot(lc, enr), colision) { in __lc_find()
281 struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr) in lc_find() argument
283 return __lc_find(lc, enr, 0); in lc_find()
296 bool lc_is_used(struct lru_cache *lc, unsigned int enr) in lc_is_used() argument
298 struct lc_element *e = __lc_find(lc, enr, 1); in lc_is_used()
310 void lc_del(struct lru_cache *lc, struct lc_element *e) in lc_del() argument
313 PARANOIA_LC_ELEMENT(lc, e); in lc_del()
318 list_move(&e->list, &lc->free); in lc_del()
322 static struct lc_element *lc_prepare_for_change(struct lru_cache *lc, unsigned new_number) in lc_prepare_for_change() argument
327 if (!list_empty(&lc->free)) in lc_prepare_for_change()
328 n = lc->free.next; in lc_prepare_for_change()
329 else if (!list_empty(&lc->lru)) in lc_prepare_for_change()
330 n = lc->lru.prev; in lc_prepare_for_change()
335 PARANOIA_LC_ELEMENT(lc, e); in lc_prepare_for_change()
340 hlist_add_head(&e->colision, lc_hash_slot(lc, new_number)); in lc_prepare_for_change()
341 list_move(&e->list, &lc->to_be_changed); in lc_prepare_for_change()
346 static int lc_unused_element_available(struct lru_cache *lc) in lc_unused_element_available() argument
348 if (!list_empty(&lc->free)) in lc_unused_element_available()
350 if (!list_empty(&lc->lru)) in lc_unused_element_available()
362 static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, unsigned int flags) in __lc_get() argument
367 if (lc->flags & LC_STARVING) { in __lc_get()
368 ++lc->starving; in __lc_get()
372 e = __lc_find(lc, enr, 1); in __lc_get()
388 ++lc->hits; in __lc_get()
392 ++lc->hits; in __lc_get()
394 lc->used++; in __lc_get()
395 list_move(&e->list, &lc->in_use); /* Not evictable... */ in __lc_get()
400 ++lc->misses; in __lc_get()
406 test_and_set_bit(__LC_DIRTY, &lc->flags); in __lc_get()
411 if (test_bit(__LC_LOCKED, &lc->flags)) { in __lc_get()
412 ++lc->locked; in __lc_get()
419 if (!lc_unused_element_available(lc)) { in __lc_get()
420 __set_bit(__LC_STARVING, &lc->flags); in __lc_get()
427 if (lc->pending_changes >= lc->max_pending_changes) in __lc_get()
430 e = lc_prepare_for_change(lc, enr); in __lc_get()
433 clear_bit(__LC_STARVING, &lc->flags); in __lc_get()
435 lc->used++; in __lc_get()
436 lc->pending_changes++; in __lc_get()
481 struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr) in lc_get() argument
483 return __lc_get(lc, enr, LC_GET_MAY_CHANGE); in lc_get()
501 struct lc_element *lc_get_cumulative(struct lru_cache *lc, unsigned int enr) in lc_get_cumulative() argument
503 return __lc_get(lc, enr, LC_GET_MAY_CHANGE|LC_GET_MAY_USE_UNCOMMITTED); in lc_get_cumulative()
522 struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr) in lc_try_get() argument
524 return __lc_get(lc, enr, 0); in lc_try_get()
535 void lc_committed(struct lru_cache *lc) in lc_committed() argument
540 list_for_each_entry_safe(e, tmp, &lc->to_be_changed, list) { in lc_committed()
542 ++lc->changed; in lc_committed()
544 list_move(&e->list, &lc->in_use); in lc_committed()
546 lc->pending_changes = 0; in lc_committed()
560 unsigned int lc_put(struct lru_cache *lc, struct lc_element *e) in lc_put() argument
563 PARANOIA_LC_ELEMENT(lc, e); in lc_put()
568 list_move(&e->list, &lc->lru); in lc_put()
569 lc->used--; in lc_put()
570 clear_bit_unlock(__LC_STARVING, &lc->flags); in lc_put()
580 struct lc_element *lc_element_by_index(struct lru_cache *lc, unsigned i) in lc_element_by_index() argument
582 BUG_ON(i >= lc->nr_elements); in lc_element_by_index()
583 BUG_ON(lc->lc_element[i] == NULL); in lc_element_by_index()
584 BUG_ON(lc->lc_element[i]->lc_index != i); in lc_element_by_index()
585 return lc->lc_element[i]; in lc_element_by_index()
593 unsigned int lc_index_of(struct lru_cache *lc, struct lc_element *e) in lc_index_of() argument
595 PARANOIA_LC_ELEMENT(lc, e); in lc_index_of()
607 void lc_set(struct lru_cache *lc, unsigned int enr, int index) in lc_set() argument
612 if (index < 0 || index >= lc->nr_elements) in lc_set()
615 e = lc_element_by_index(lc, index); in lc_set()
622 lh = &lc->free; in lc_set()
624 hlist_add_head(&e->colision, lc_hash_slot(lc, enr)); in lc_set()
625 lh = &lc->lru; in lc_set()
639 void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char *utext, in lc_seq_dump_details() argument
642 unsigned int nr_elements = lc->nr_elements; in lc_seq_dump_details()
648 e = lc_element_by_index(lc, i); in lc_seq_dump_details()