dedicated kthread interface and enablement of lrud auto-recycler
[lunaix-os.git] / lunaix-os / kernel / lrud.c
index 0395e42da500b12fc04f54e46ea12ef77840fb71..137cfa632ba2c84a37e5559f34562f10ae8c6576 100644 (file)
@@ -3,16 +3,18 @@
 #include <lunaix/spike.h>
 #include <lunaix/fs/twimap.h>
 #include <lunaix/fs/twifs.h>
+#include <lunaix/kthread.h>
+#include <lunaix/owloysius.h>
 
 #include <klibc/string.h>
 
 static struct llist_header zone_lead = { .next = &zone_lead, .prev = &zone_lead };
 
 DEFINE_SPINLOCK_OPS(struct lru_zone*, lock);
-
+static DEFINE_SPINLOCK(zone_list_lock);
 
 static void
-__do_evict_lockless(struct lru_zone* zone, struct llist_header* elem)
+__do_evict_nolock(struct lru_zone* zone, struct llist_header* elem)
 {
     llist_delete(elem);
     if (!zone->try_evict(container_of(elem, struct lru_node, lru_nodes))) {
@@ -28,12 +30,16 @@ __do_evict_lockless(struct lru_zone* zone, struct llist_header* elem)
 }
 
 static void
-__lru_evict_all_lockness(struct lru_zone* zone)
+__lru_evict_all_nolock(struct lru_zone* zone)
 {
-    struct llist_header* tail = zone->lead_node.prev;
-    while (tail != &zone->lead_node) {
-        __do_evict_lockless(zone, tail);
+    struct llist_header* tail, *curr;
+
+    tail = zone->lead_node.prev;
+    while (tail != &zone->lead_node) 
+    {
+        curr = tail;
         tail = tail->prev;
+        __do_evict_nolock(zone, curr);
     }
 }
 
@@ -49,9 +55,12 @@ lru_new_zone(const char* name, evict_cb try_evict_cb)
 
     strncpy(zone->name, name, sizeof(zone->name) - 1);
     llist_init_head(&zone->lead_node);
-    llist_append(&zone_lead, &zone->zones);
     spinlock_init(&zone->lock);
 
+    spinlock_acquire(&zone_list_lock);
+    llist_append(&zone_lead, &zone->zones);
+    spinlock_release(&zone_list_lock);
+
     return zone;
 }
 
@@ -60,10 +69,12 @@ lru_free_zone(struct lru_zone* zone)
 {
     lock(zone);
 
-    __lru_evict_all_lockness(zone);
+    __lru_evict_all_nolock(zone);
 
-    if (llist_empty(&zone->lead_node)) {
+    if (llist_empty(&zone->lead_node)) 
+    {
         llist_delete(&zone->zones);
+        unlock(zone);
         vfree(zone);
         return;
     }
@@ -107,24 +118,31 @@ lru_evict_one(struct lru_zone* zone)
 
     struct llist_header* tail = zone->lead_node.prev;
     if (tail == &zone->lead_node) {
-        return;
+        goto done;
     }
 
-    __do_evict_lockless(zone, tail);
+    __do_evict_nolock(zone, tail);
 
+done:
     unlock(zone);
 }
 
 void
 lru_evict_half(struct lru_zone* zone)
 {
+    int target;
+    struct llist_header *tail, *curr;
+    
     lock(zone);
 
-    int target = (int)(zone->objects / 2);
-    struct llist_header* tail = zone->lead_node.prev;
+    target = (int)(zone->objects / 2);
+    tail = zone->lead_node.prev;
+
     while (tail != &zone->lead_node && target > 0) {
-        __do_evict_lockless(zone, tail);
+        curr = tail;
         tail = tail->prev;
+
+        __do_evict_nolock(zone, curr);
         target--;
     }
 
@@ -138,7 +156,7 @@ lru_evict_all(struct lru_zone* zone)
 {
     lock(zone);
     
-    __lru_evict_all_lockness(zone);
+    __lru_evict_all_nolock(zone);
 
     zone->evict_stats.n_full++;
 
@@ -148,16 +166,48 @@ lru_evict_all(struct lru_zone* zone)
 void
 lru_remove(struct lru_zone* zone, struct lru_node* node)
 {
-    lock(zone);
+    if (llist_empty(&node->lru_nodes)) 
+        return;
 
-    if (node->lru_nodes.next && node->lru_nodes.prev) {
-        llist_delete(&node->lru_nodes);
-    }
+    lock(zone);
+    
+    llist_delete(&node->lru_nodes);
     zone->objects--;
 
     unlock(zone);
 }
 
+
+static void
+__lru_pool_daemon()
+{
+    struct lru_zone *pos, *n;
+
+    while (true)
+    {
+        spinlock_acquire(&zone_list_lock);
+        
+        // TODO add a watermark check before doing eviction
+        llist_for_each(pos, n, &zone_lead, zones) {
+            lru_evict_half(pos);
+        }
+
+        spinlock_release(&zone_list_lock);
+
+        kthread_sleep(10);
+    }
+}
+
+static void
+__lru_pool_init()
+{
+    // TODO make sure other are thread-safe first
+
+    // kthread_spawn((ptr_t)__lru_pool_daemon);
+}
+owloysius_fetch_init(__lru_pool_init, on_postboot)
+
+
 static void
 __twimap_read_lru_pool(struct twimap* map)
 {