Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions xv6-os/ci/test/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def read_header(qemu: Qemu):
prefix = [qemu.readline() for _ in range(7)]
assert_eq(prefix[2], "xv6 kernel is booting")
assert_eq(prefix[3], "")
# ingenious skip of buddy allocator metadata
if "bd: memory sz" in prefix[4]:
prefix = prefix[0:4] + [qemu.readline() for _ in range(3)]
assert prefix[4] in (f"hart {i + 1} starting" for i in range(2))
assert prefix[5] in (f"hart {i + 1} starting" for i in range(2))
assert_eq(prefix[6], "init: starting sh")
Expand Down
34 changes: 23 additions & 11 deletions xv6-os/kernel/buddy.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "riscv.h"
#include "defs.h"
#include "list.h"
#include <stdbool.h>

// Buddy allocator

Expand Down Expand Up @@ -58,6 +59,15 @@ void bit_clear(char *array, int index) {
array[index / 8] = (b & ~m);
}

// Invert bit at position index in array which stands for xor'ed bits of pair blocks at (2 * index) and (2 * index + 1) positions
void bit_invert(char *array, int index) {
int b_idx = index / 2; // Every bit is xor'ed with the next one thus flag in
// the array has a bit index two times smaller
char b = array[b_idx / 8];
char m = (1 << (b_idx % 8));
array[b_idx / 8] = (b ^ m);
}

// Print a bit vector as a list of ranges of 1 bits
void bd_print_vector(char *vector, int len) {
int last, lb;
Expand Down Expand Up @@ -132,13 +142,13 @@ void *bd_malloc(uint64 nbytes) {

// Found a block; pop it and potentially split it.
char *p = lst_pop(&bd_sizes[k].free);
bit_set(bd_sizes[k].alloc, blk_index(k, p));
bit_invert(bd_sizes[k].alloc, blk_index(k, p));
for (; k > fk; k--) {
// split a block at size k and mark one half allocated at size k-1
// and put the buddy on the free list at size k-1
char *q = p + BLK_SIZE(k - 1); // p's buddy
bit_set(bd_sizes[k].split, blk_index(k, p));
bit_set(bd_sizes[k - 1].alloc, blk_index(k - 1, p));
bit_invert(bd_sizes[k - 1].alloc, blk_index(k - 1, p));
lst_push(&bd_sizes[k - 1].free, q);
}
release(&lock);
Expand Down Expand Up @@ -166,8 +176,8 @@ void bd_free(void *p) {
for (k = size(p); k < MAXSIZE; k++) {
int bi = blk_index(k, p);
int buddy = (bi % 2 == 0) ? bi + 1 : bi - 1;
bit_clear(bd_sizes[k].alloc, bi); // free p at size k
if (bit_isset(bd_sizes[k].alloc, buddy)) { // is buddy allocated?
bit_invert(bd_sizes[k].alloc, bi); // free p at size k
if (bit_isset(bd_sizes[k].alloc, buddy / 2)) { // is buddy allocated?
break; // break out of loop
}
// budy is free; merge with buddy
Expand Down Expand Up @@ -215,20 +225,21 @@ void bd_mark(void *start, void *stop) {
// if a block is allocated at size k, mark it as split too.
bit_set(bd_sizes[k].split, bi);
}
bit_set(bd_sizes[k].alloc, bi);
bit_invert(bd_sizes[k].alloc, bi);
}
}
}

// If a block is marked as allocated and the buddy is free, put the
// buddy on the free list at size k.
int bd_initfree_pair(int k, int bi) {
int bd_initfree_pair(int k, int bi, bool use_buddy) {
int buddy = (bi % 2 == 0) ? bi + 1 : bi - 1;
int free = 0;
if (bit_isset(bd_sizes[k].alloc, bi) != bit_isset(bd_sizes[k].alloc, buddy)) {
if (bit_isset(bd_sizes[k].alloc, bi / 2)) {
// one of the pair is free
free = BLK_SIZE(k);
if (bit_isset(bd_sizes[k].alloc, bi))
// put buddy on free list, depending on the flag
if (use_buddy)
lst_push(&bd_sizes[k].free, addr(k, buddy)); // put buddy on free list
else
lst_push(&bd_sizes[k].free, addr(k, bi)); // put bi on free list
Expand All @@ -245,9 +256,9 @@ int bd_initfree(void *bd_left, void *bd_right) {
for (int k = 0; k < MAXSIZE; k++) { // skip max size
int left = blk_index_next(k, bd_left);
int right = blk_index(k, bd_right);
free += bd_initfree_pair(k, left);
free += bd_initfree_pair(k, left, false);
if (right <= left) continue;
free += bd_initfree_pair(k, right);
free += bd_initfree_pair(k, right, true);
}
return free;
}
Expand Down Expand Up @@ -297,7 +308,8 @@ void bd_init(void *base, void *end) {
// initialize free list and allocate the alloc array for each size k
for (int k = 0; k < nsizes; k++) {
lst_init(&bd_sizes[k].free);
sz = sizeof(char) * ROUNDUP(NBLK(k), 8) / 8;
// optimisation takes 2 times less blocks
sz = sizeof(char) * ROUNDUP(NBLK(k) / 2, 8) / 8;
bd_sizes[k].alloc = p;
memset(bd_sizes[k].alloc, 0, sz);
p += sz;
Expand Down
2 changes: 1 addition & 1 deletion xv6-os/kernel/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ int cpuid(void);
void exit(int);
int fork(void);
int growproc(int);
void proc_mapstacks(pagetable_t);
// void proc_mapstacks(pagetable_t);
pagetable_t proc_pagetable(struct proc *);
void proc_freepagetable(pagetable_t, uint64);
int kill(int);
Expand Down
48 changes: 19 additions & 29 deletions xv6-os/kernel/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
#include "proc.h"

struct devsw devsw[NDEV];
struct {
struct spinlock lock;
struct file file[NFILE];
} ftable;
// struct {
// struct spinlock lock;
// struct file file[NFILE];
// } ftable;

void
fileinit(void)
{
initlock(&ftable.lock, "ftable");
// initlock(&ftable.lock, "ftable");
}

// Allocate a file structure.
Expand All @@ -31,55 +31,45 @@ filealloc(void)
{
struct file *f;

acquire(&ftable.lock);
for(f = ftable.file; f < ftable.file + NFILE; f++){
if(f->ref == 0){
f->ref = 1;
release(&ftable.lock);
return f;
}
f = (struct file*) bd_malloc(sizeof(struct file));

if (f == 0) {
return 0;
}
release(&ftable.lock);
return 0;

memset(f, 0, sizeof(struct file));
f->ref = 1;
return f;
}

// Increment ref count for file f.
struct file*
filedup(struct file *f)
{
acquire(&ftable.lock);
if(f->ref < 1)
panic("filedup");
f->ref++;
release(&ftable.lock);
return f;
}

// Close file f. (Decrement ref count, close when reaches 0.)
void
fileclose(struct file *f)
{
struct file ff;

acquire(&ftable.lock);
if(f->ref < 1)
panic("fileclose");
if(--f->ref > 0){
release(&ftable.lock);
return;
}
ff = *f;
f->ref = 0;
f->type = FD_NONE;
release(&ftable.lock);

if(ff.type == FD_PIPE){
pipeclose(ff.pipe, ff.writable);
} else if(ff.type == FD_INODE || ff.type == FD_DEVICE){
if(f->type == FD_PIPE){
pipeclose(f->pipe, f->writable);
} else if(f->type == FD_INODE || f->type == FD_DEVICE){
begin_op();
iput(ff.ip);
iput(f->ip);
end_op();
}

bd_free(f);
}

// Get metadata about file f.
Expand Down
51 changes: 5 additions & 46 deletions xv6-os/kernel/kalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,16 @@
#include "riscv.h"
#include "defs.h"

void freerange(void *pa_start, void *pa_end);

extern char end[]; // first address after kernel.
// defined by kernel.ld.

struct run {
struct run *next;
};

struct {
struct spinlock lock;
struct run *freelist;
} kmem;

void
kinit()
{
initlock(&kmem.lock, "kmem");
freerange(end, (void*)PHYSTOP);
}

void
freerange(void *pa_start, void *pa_end)
{
char *p;
p = (char*)PGROUNDUP((uint64)pa_start);
for(; p + PGSIZE <= (char*)pa_end; p += PGSIZE)
kfree(p);
// Align `end` to the next page boundary
void *start = (char *)PGROUNDUP((uint64)end);
bd_init(start, (void *)PHYSTOP);
}

// Free the page of physical memory pointed at by pa,
Expand All @@ -46,20 +28,7 @@ freerange(void *pa_start, void *pa_end)
void
kfree(void *pa)
{
struct run *r;

if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)
panic("kfree");

// Fill with junk to catch dangling refs.
memset(pa, 1, PGSIZE);

r = (struct run*)pa;

acquire(&kmem.lock);
r->next = kmem.freelist;
kmem.freelist = r;
release(&kmem.lock);
bd_free(pa);
}

// Allocate one 4096-byte page of physical memory.
Expand All @@ -68,15 +37,5 @@ kfree(void *pa)
void *
kalloc(void)
{
struct run *r;

acquire(&kmem.lock);
r = kmem.freelist;
if(r)
kmem.freelist = r->next;
release(&kmem.lock);

if(r)
memset((char*)r, 5, PGSIZE); // fill with junk
return (void*)r;
return bd_malloc(PGSIZE);
}
Loading
Loading