#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))) {
}
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);
}
}
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;
}
{
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;
}
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--;
}
{
lock(zone);
- __lru_evict_all_lockness(zone);
+ __lru_evict_all_nolock(zone);
zone->evict_stats.n_full++;
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)
{