diff options
Diffstat (limited to 'lume-legacy/src/kernel/bio.cc')
| -rw-r--r-- | lume-legacy/src/kernel/bio.cc | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/lume-legacy/src/kernel/bio.cc b/lume-legacy/src/kernel/bio.cc new file mode 100644 index 0000000..5f1aae9 --- /dev/null +++ b/lume-legacy/src/kernel/bio.cc @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 Richard QIn + */ +#include "kernel/buf.h" +#include "kernel/spinlock.h" +#include "kernel/riscv.h" +#include "drivers/virtio.h" +#include "drivers/uart.h" + +namespace BufferCache +{ + struct + { + Spinlock lock; + struct Buf buf[NBUF]; + struct Buf head; + } bcache; + + void init() + { + bcache.lock.init("bcache"); + // Initialize LRU doubly circular linked list + bcache.head.prev = &bcache.head; + bcache.head.next = &bcache.head; + for (struct Buf *b = bcache.buf; b < bcache.buf + NBUF; ++b) + { + b->lock.init("buffer"); + b->next = bcache.head.next; + b->prev = &bcache.head; + bcache.head.next->prev = b; + bcache.head.next = b; + } + Drivers::uart_puts("[Bio] Buffer cache initialized.\n"); + } + + static struct Buf* bget(uint32 dev, uint32 blockno) + { + struct Buf* b; + bcache.lock.acquire(); + + // Attempt to hit the cache + for (b = bcache.head.next; b != &bcache.head; b = b->next) + { + if (b->dev == dev && b->blockno == blockno) + { + b->refcnt++; + bcache.lock.release(); + b->lock.acquire(); // Acquire Sleep Lock + return b; + } + } + + // Cache miss, evicting LRU + for (b = bcache.head.prev; b != &bcache.head; b = b->prev) + { + if (b->refcnt == 0) + { + b->dev = dev; + b->blockno = blockno; + b->valid = 0; + b->refcnt = 1; + bcache.lock.release(); + b->lock.acquire(); + return b; + } + } + + Drivers::uart_puts("panic: bget: no buffers\n"); + while (1) + ; + } + + struct Buf* bread(uint32 dev, uint32 blockno) + { + struct Buf *b = bget(dev, blockno); + + if (!b->valid) + { + VirtIO::rw(0, b->blockno, (char *)b->data); + b->valid = 1; + } + + return b; + } + + void bwrite(struct Buf *b) + { + if (!b->lock.holding()) + { + Drivers::uart_puts("panic: bwrite\n"); + while (1) + ; + } + VirtIO::rw(1, b->blockno, (char *)b->data); + } + + void brelse(struct Buf *b) + { + if (!b->lock.holding()) + { + Drivers::uart_puts("panic: brelse\n"); + while (1) + ; + } + b->lock.release(); + + bcache.lock.acquire(); + b->refcnt--; + + if (b->refcnt == 0) + { + b->next->prev = b->prev; + b->prev->next = b->next; + + b->next = bcache.head.next; + b->prev = &bcache.head; + bcache.head.next->prev = b; + bcache.head.next = b; + } + + bcache.lock.release(); + } + + void bpin(struct Buf *b) + { + bcache.lock.acquire(); + b->refcnt++; + bcache.lock.release(); + } + + void bunpin(struct Buf* b) + { + bcache.lock.acquire(); + b->refcnt --; + bcache.lock.release(); + } + +} // namespace BufferCache |
