fix: load x87 fpu default settings
[lunaix-os.git] / lunaix-os / kernel / ds / lru.c
1 #include <lunaix/ds/lru.h>
2 #include <lunaix/mm/valloc.h>
3
4 struct llist_header zone_lead = { .next = &zone_lead, .prev = &zone_lead };
5
6 struct lru_zone*
7 lru_new_zone(evict_cb try_evict_cb)
8 {
9     struct lru_zone* zone = vzalloc(sizeof(struct lru_zone));
10     if (!zone) {
11         return NULL;
12     }
13
14     zone->try_evict = try_evict_cb;
15
16     llist_init_head(&zone->lead_node);
17     llist_append(&zone_lead, &zone->zones);
18
19     return zone;
20 }
21
22 void
23 lru_use_one(struct lru_zone* zone, struct lru_node* node)
24 {
25     if (node->lru_nodes.next && node->lru_nodes.prev) {
26         llist_delete(&node->lru_nodes);
27     }
28
29     llist_prepend(&zone->lead_node, &node->lru_nodes);
30     zone->objects++;
31 }
32
33 static void
34 __do_evict(struct lru_zone* zone, struct llist_header* elem)
35 {
36     llist_delete(elem);
37     if (!zone->try_evict(container_of(elem, struct lru_node, lru_nodes))) {
38         llist_append(&zone->lead_node, elem);
39     } else {
40         zone->objects--;
41     }
42 }
43
44 void
45 lru_evict_one(struct lru_zone* zone)
46 {
47     struct llist_header* tail = zone->lead_node.prev;
48     if (tail == &zone->lead_node) {
49         return;
50     }
51
52     __do_evict(zone, tail);
53 }
54
55 void
56 lru_evict_half(struct lru_zone* zone)
57 {
58     int target = (int)(zone->objects / 2);
59     struct llist_header* tail = zone->lead_node.prev;
60     while (tail != &zone->lead_node && target > 0) {
61         __do_evict(zone, tail);
62         tail = tail->prev;
63         target--;
64     }
65 }
66
67 void
68 lru_remove(struct lru_zone* zone, struct lru_node* node)
69 {
70     if (node->lru_nodes.next && node->lru_nodes.prev) {
71         llist_delete(&node->lru_nodes);
72     }
73     zone->objects--;
74 }