struct llist_header zone_lead = { .next = &zone_lead, .prev = &zone_lead };
struct lru_zone*
-lru_new_zone()
+lru_new_zone(evict_cb try_evict_cb)
{
- struct lru_zone* zone = valloc(sizeof(struct lru_zone));
+ struct lru_zone* zone = vzalloc(sizeof(struct lru_zone));
if (!zone) {
return NULL;
}
+ zone->try_evict = try_evict_cb;
+
llist_init_head(&zone->lead_node);
llist_append(&zone_lead, &zone->zones);
}
llist_prepend(&zone->lead_node, &node->lru_nodes);
+ zone->objects++;
+}
+
+static void
+__do_evict(struct lru_zone* zone, struct llist_header* elem)
+{
+ llist_delete(elem);
+ if (!zone->try_evict(container_of(elem, struct lru_node, lru_nodes))) {
+ llist_append(&zone->lead_node, elem);
+ } else {
+ zone->objects--;
+ }
}
-struct lru_node*
+void
lru_evict_one(struct lru_zone* zone)
{
struct llist_header* tail = zone->lead_node.prev;
return;
}
- llist_delete(tail);
+ __do_evict(zone, tail);
+}
- return container_of(tail, struct lru_node, lru_nodes);
+void
+lru_evict_half(struct lru_zone* zone)
+{
+ int target = (int)(zone->objects / 2);
+ struct llist_header* tail = zone->lead_node.prev;
+ while (tail != &zone->lead_node && target > 0) {
+ __do_evict(zone, tail);
+ tail = tail->prev;
+ target--;
+ }
}
void
-lru_remove(struct lru_node* node)
+lru_remove(struct lru_zone* zone, struct lru_node* node)
{
if (node->lru_nodes.next && node->lru_nodes.prev) {
llist_delete(&node->lru_nodes);
}
+ zone->objects--;
}
\ No newline at end of file