fix: the correct way to detect ahci LBA48 support
[lunaix-os.git] / lunaix-os / kernel / ds / lru.c
index ebabeef5709effa520127033566f375ca8005829..08083b11fb1d06ded2a557d7437fabf882f1963f 100644 (file)
@@ -4,13 +4,15 @@
 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);
 
@@ -25,9 +27,21 @@ lru_use_one(struct lru_zone* zone, struct lru_node* node)
     }
 
     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;
@@ -35,15 +49,26 @@ lru_evict_one(struct lru_zone* zone)
         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