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()
93 struct lru_cache *lc; in lc_create() local
114 lc = kzalloc(sizeof(*lc), GFP_KERNEL); in lc_create()
115 if (!lc) in lc_create()
118 INIT_LIST_HEAD(&lc->in_use); in lc_create()
119 INIT_LIST_HEAD(&lc->lru); in lc_create()
120 INIT_LIST_HEAD(&lc->free); in lc_create()
121 INIT_LIST_HEAD(&lc->to_be_changed); in lc_create()
123 lc->name = name; in lc_create()
124 lc->element_size = e_size; in lc_create()
125 lc->element_off = e_off; in lc_create()
126 lc->nr_elements = e_count; in lc_create()
127 lc->max_pending_changes = max_pending_changes; in lc_create()
128 lc->lc_cache = cache; in lc_create()
129 lc->lc_element = element; in lc_create()
130 lc->lc_slot = slot; in lc_create()
137 memset(p, 0, lc->element_size); in lc_create()
142 list_add(&e->list, &lc->free); in lc_create()
146 return lc; in lc_create()
153 kfree(lc); in lc_create()
160 static void lc_free_by_index(struct lru_cache *lc, unsigned i) in lc_free_by_index() argument
162 void *p = lc->lc_element[i]; in lc_free_by_index()
165 p -= lc->element_off; in lc_free_by_index()
166 kmem_cache_free(lc->lc_cache, p); in lc_free_by_index()
174 void lc_destroy(struct lru_cache *lc) in lc_destroy() argument
177 if (!lc) in lc_destroy()
179 for (i = 0; i < lc->nr_elements; i++) in lc_destroy()
180 lc_free_by_index(lc, i); in lc_destroy()
181 kfree(lc->lc_element); in lc_destroy()
182 kfree(lc->lc_slot); in lc_destroy()
183 kfree(lc); in lc_destroy()
193 void lc_reset(struct lru_cache *lc) in lc_reset() argument
197 INIT_LIST_HEAD(&lc->in_use); in lc_reset()
198 INIT_LIST_HEAD(&lc->lru); in lc_reset()
199 INIT_LIST_HEAD(&lc->free); in lc_reset()
200 INIT_LIST_HEAD(&lc->to_be_changed); in lc_reset()
201 lc->used = 0; in lc_reset()
202 lc->hits = 0; in lc_reset()
203 lc->misses = 0; in lc_reset()
204 lc->starving = 0; in lc_reset()
205 lc->locked = 0; in lc_reset()
206 lc->changed = 0; in lc_reset()
207 lc->pending_changes = 0; in lc_reset()
208 lc->flags = 0; in lc_reset()
209 memset(lc->lc_slot, 0, sizeof(struct hlist_head) * lc->nr_elements); in lc_reset()
211 for (i = 0; i < lc->nr_elements; i++) { in lc_reset()
212 struct lc_element *e = lc->lc_element[i]; in lc_reset()
214 p -= lc->element_off; in lc_reset()
215 memset(p, 0, lc->element_size); in lc_reset()
220 list_add(&e->list, &lc->free); in lc_reset()
229 void lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) in lc_seq_printf_stats() argument
239 lc->name, lc->used, lc->nr_elements, in lc_seq_printf_stats()
240 lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); in lc_seq_printf_stats()
243 static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) in lc_hash_slot() argument
245 return lc->lc_slot + (enr % lc->nr_elements); in lc_hash_slot()
249 static struct lc_element *__lc_find(struct lru_cache *lc, unsigned int enr, in __lc_find() argument
254 BUG_ON(!lc); in __lc_find()
255 BUG_ON(!lc->nr_elements); in __lc_find()
256 hlist_for_each_entry(e, lc_hash_slot(lc, enr), colision) { in __lc_find()
280 struct lc_element *lc_find(struct lru_cache *lc, unsigned int enr) in lc_find() argument
282 return __lc_find(lc, enr, 0); in lc_find()
295 bool lc_is_used(struct lru_cache *lc, unsigned int enr) in lc_is_used() argument
297 struct lc_element *e = __lc_find(lc, enr, 1); in lc_is_used()
309 void lc_del(struct lru_cache *lc, struct lc_element *e) in lc_del() argument
312 PARANOIA_LC_ELEMENT(lc, e); in lc_del()
317 list_move(&e->list, &lc->free); in lc_del()
321 static struct lc_element *lc_prepare_for_change(struct lru_cache *lc, unsigned new_number) in lc_prepare_for_change() argument
326 if (!list_empty(&lc->free)) in lc_prepare_for_change()
327 n = lc->free.next; in lc_prepare_for_change()
328 else if (!list_empty(&lc->lru)) in lc_prepare_for_change()
329 n = lc->lru.prev; in lc_prepare_for_change()
334 PARANOIA_LC_ELEMENT(lc, e); in lc_prepare_for_change()
339 hlist_add_head(&e->colision, lc_hash_slot(lc, new_number)); in lc_prepare_for_change()
340 list_move(&e->list, &lc->to_be_changed); in lc_prepare_for_change()
345 static int lc_unused_element_available(struct lru_cache *lc) in lc_unused_element_available() argument
347 if (!list_empty(&lc->free)) in lc_unused_element_available()
349 if (!list_empty(&lc->lru)) in lc_unused_element_available()
361 static struct lc_element *__lc_get(struct lru_cache *lc, unsigned int enr, unsigned int flags) in __lc_get() argument
366 if (lc->flags & LC_STARVING) { in __lc_get()
367 ++lc->starving; in __lc_get()
371 e = __lc_find(lc, enr, 1); in __lc_get()
387 ++lc->hits; in __lc_get()
391 ++lc->hits; in __lc_get()
393 lc->used++; in __lc_get()
394 list_move(&e->list, &lc->in_use); /* Not evictable... */ in __lc_get()
399 ++lc->misses; in __lc_get()
405 test_and_set_bit(__LC_DIRTY, &lc->flags); in __lc_get()
410 if (test_bit(__LC_LOCKED, &lc->flags)) { in __lc_get()
411 ++lc->locked; in __lc_get()
418 if (!lc_unused_element_available(lc)) { in __lc_get()
419 __set_bit(__LC_STARVING, &lc->flags); in __lc_get()
426 if (lc->pending_changes >= lc->max_pending_changes) in __lc_get()
429 e = lc_prepare_for_change(lc, enr); in __lc_get()
432 clear_bit(__LC_STARVING, &lc->flags); in __lc_get()
434 lc->used++; in __lc_get()
435 lc->pending_changes++; in __lc_get()
480 struct lc_element *lc_get(struct lru_cache *lc, unsigned int enr) in lc_get() argument
482 return __lc_get(lc, enr, LC_GET_MAY_CHANGE); in lc_get()
500 struct lc_element *lc_get_cumulative(struct lru_cache *lc, unsigned int enr) in lc_get_cumulative() argument
502 return __lc_get(lc, enr, LC_GET_MAY_CHANGE|LC_GET_MAY_USE_UNCOMMITTED); in lc_get_cumulative()
521 struct lc_element *lc_try_get(struct lru_cache *lc, unsigned int enr) in lc_try_get() argument
523 return __lc_get(lc, enr, 0); in lc_try_get()
534 void lc_committed(struct lru_cache *lc) in lc_committed() argument
539 list_for_each_entry_safe(e, tmp, &lc->to_be_changed, list) { in lc_committed()
541 ++lc->changed; in lc_committed()
543 list_move(&e->list, &lc->in_use); in lc_committed()
545 lc->pending_changes = 0; in lc_committed()
559 unsigned int lc_put(struct lru_cache *lc, struct lc_element *e) in lc_put() argument
562 PARANOIA_LC_ELEMENT(lc, e); in lc_put()
567 list_move(&e->list, &lc->lru); in lc_put()
568 lc->used--; in lc_put()
569 clear_bit_unlock(__LC_STARVING, &lc->flags); in lc_put()
579 struct lc_element *lc_element_by_index(struct lru_cache *lc, unsigned i) in lc_element_by_index() argument
581 BUG_ON(i >= lc->nr_elements); in lc_element_by_index()
582 BUG_ON(lc->lc_element[i] == NULL); in lc_element_by_index()
583 BUG_ON(lc->lc_element[i]->lc_index != i); in lc_element_by_index()
584 return lc->lc_element[i]; in lc_element_by_index()
592 unsigned int lc_index_of(struct lru_cache *lc, struct lc_element *e) in lc_index_of() argument
594 PARANOIA_LC_ELEMENT(lc, e); in lc_index_of()
606 void lc_set(struct lru_cache *lc, unsigned int enr, int index) in lc_set() argument
611 if (index < 0 || index >= lc->nr_elements) in lc_set()
614 e = lc_element_by_index(lc, index); in lc_set()
621 lh = &lc->free; in lc_set()
623 hlist_add_head(&e->colision, lc_hash_slot(lc, enr)); in lc_set()
624 lh = &lc->lru; in lc_set()
638 void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char *utext, in lc_seq_dump_details() argument
641 unsigned int nr_elements = lc->nr_elements; in lc_seq_dump_details()
647 e = lc_element_by_index(lc, i); in lc_seq_dump_details()