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
Empty file modified ci/docker/run.sh
100644 → 100755
Empty file.
177 changes: 95 additions & 82 deletions kernel/buddy.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,26 @@ typedef struct list Bd_list;
// 8 blocks).
struct sz_info {
Bd_list free;
char *alloc;
char *xor_alloc;
char *split;
};
typedef struct sz_info Sz_info;

static inline int pair_index(int bi) { return bi >> 1; }

static inline int buddy_index(int bi) { return bi ^ 1; }

static Sz_info *bd_sizes;
static void *bd_base; // start address of memory managed by the buddy allocator
static struct spinlock lock;

// flip the bit in xor_array and return the result (new value)
int bit_flip(char *array, int index) {
char m = (1 << (index % 8));
array[index / 8] ^= m;
return (array[index / 8] & m) != 0;
}

// Return 1 if bit at position index in array is set to 1
int bit_isset(char *array, int index) {
char b = array[index / 8];
Expand All @@ -58,37 +69,6 @@ void bit_clear(char *array, int index) {
array[index / 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;

last = 1;
lb = 0;
for (int b = 0; b < len; b++) {
if (last == bit_isset(vector, b)) continue;
if (last == 1) printf(" [%d, %d)", lb, b);
lb = b;
last = bit_isset(vector, b);
}
if (lb == 0 || last == 1) {
printf(" [%d, %d)", lb, len);
}
printf("\n");
}

// Print buddy's data structures
void bd_print() {
for (int k = 0; k < nsizes; k++) {
printf("size %d (blksz %ld nblk %d): free list: ", k, BLK_SIZE(k), NBLK(k));
lst_print(&bd_sizes[k].free);
printf(" alloc:");
bd_print_vector(bd_sizes[k].alloc, NBLK(k));
if (k > 0) {
printf(" split:");
bd_print_vector(bd_sizes[k].split, NBLK(k));
}
}
}

// What is the first k such that 2^k >= n?
int firstk(uint64 n) {
Expand Down Expand Up @@ -132,15 +112,17 @@ 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));
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));
lst_push(&bd_sizes[k - 1].free, q);
}

int bi = blk_index(fk, p);
int pi = pair_index(bi);
bit_flip(bd_sizes[k].xor_alloc, pi);
release(&lock);

return p;
Expand All @@ -160,26 +142,47 @@ int size(char *p) {
// bd_malloc.
void bd_free(void *p) {
void *q;
int k;
int k = size(p);

acquire(&lock);
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?
break; // break out of loop
}
// budy is free; merge with buddy
int bi = blk_index(k, p);
int pi = pair_index(bi);
int x = bit_flip(bd_sizes[k].xor_alloc, pi);
if (x == 1) {
// one block in pair is allocated -> no merge
lst_push(&bd_sizes[k].free, p);
release(&lock);
return;
}

// x == 0 -> merge
int buddy = buddy_index(bi);
q = addr(k, buddy);
lst_remove(q);
bit_clear(bd_sizes[k + 1].split, blk_index(k + 1, p));
if (buddy % 2 == 0) {
p = q;
}

for (k = k + 1; k < MAXSIZE; k++) {
bi = blk_index(k, p);
buddy = buddy_index(bi);

q = addr(k, buddy);
lst_remove(q); // remove buddy from free list
if (buddy % 2 == 0) {
p = q;

if (bit_isset(bd_sizes[k].split, buddy) == 1){
break; // buddy is not free
}

lst_remove(q); // remove buddy from free list
// at size k+1, mark that the merged buddy pair isn't split
// anymore
bit_clear(bd_sizes[k + 1].split, blk_index(k + 1, p));
if (buddy % 2 == 0) {
p = q;
}
}

lst_push(&bd_sizes[k].free, p);
release(&lock);
}
Expand All @@ -202,33 +205,60 @@ int _log2(uint64 n) {

// Mark memory from [start, stop), starting at size 0, as allocated.
void bd_mark(void *start, void *stop) {
int bi, bj;

if (((uint64)start % LEAF_SIZE != 0) || ((uint64)stop % LEAF_SIZE != 0))
panic("bd_mark");

for (int k = 0; k < nsizes; k++) {
bi = blk_index(k, start);
bj = blk_index_next(k, stop);
for (; bi < bj; bi++) {
if (k > 0) {
// if a block is allocated at size k, mark it as split too.
bit_set(bd_sizes[k].split, bi);
int bi = blk_index(k, start);
int bj = blk_index_next(k, stop);

if (k > 0) {
for (int i = bi; i < bj; i++) {
bit_set(bd_sizes[k].split, i);
}
bit_set(bd_sizes[k].alloc, bi);
}

if (bi & 1) {
bit_flip(bd_sizes[k].xor_alloc, pair_index(bi));
}
if (bj & 1) {
bit_flip(bd_sizes[k].xor_alloc, pair_index(bj));
}
}
}

// Mark the range [bd_base,p) as allocated
int bd_mark_data_structures(char *p) {
int meta = p - (char *)bd_base;
// printf("bd: %d meta bytes for managing %ld bytes of memory\n", meta,
// BLK_SIZE(MAXSIZE));
bd_mark(bd_base, p);
return meta;
}

// Mark the range [end, HEAPSIZE) as allocated
int bd_mark_unavailable(void *end, void *left) {
int unavailable = BLK_SIZE(MAXSIZE) - (end - bd_base);
if (unavailable > 0) unavailable = ROUNDUP(unavailable, LEAF_SIZE);
// printf("bd: 0x%x bytes unavailable\n", unavailable);

void *bd_end = bd_base + BLK_SIZE(MAXSIZE) - unavailable;
bd_mark(bd_end, bd_base + BLK_SIZE(MAXSIZE));
return unavailable;
}


// 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 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)) {
int pi = pair_index(bi);
if (bit_isset(bd_sizes[k].xor_alloc, pi)) {
// one of the pair is free
free = BLK_SIZE(k);
if (bit_isset(bd_sizes[k].alloc, bi))
// bit_flip(bd_sizes[k].xor_alloc, pi);
if (bit_isset(bd_sizes[k].split, bi))
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 @@ -252,25 +282,6 @@ int bd_initfree(void *bd_left, void *bd_right) {
return free;
}

// Mark the range [bd_base,p) as allocated
int bd_mark_data_structures(char *p) {
int meta = p - (char *)bd_base;
printf("bd: %d meta bytes for managing %ld bytes of memory\n", meta,
BLK_SIZE(MAXSIZE));
bd_mark(bd_base, p);
return meta;
}

// Mark the range [end, HEAPSIZE) as allocated
int bd_mark_unavailable(void *end, void *left) {
int unavailable = BLK_SIZE(MAXSIZE) - (end - bd_base);
if (unavailable > 0) unavailable = ROUNDUP(unavailable, LEAF_SIZE);
printf("bd: 0x%x bytes unavailable\n", unavailable);

void *bd_end = bd_base + BLK_SIZE(MAXSIZE) - unavailable;
bd_mark(bd_end, bd_base + BLK_SIZE(MAXSIZE));
return unavailable;
}

// Initialize the buddy allocator: it manages memory from [base, end).
void bd_init(void *base, void *end) {
Expand All @@ -286,8 +297,8 @@ void bd_init(void *base, void *end) {
nsizes++; // round up to the next power of 2
}

printf("bd: memory sz is %ld bytes; allocate an size array of length %d\n",
(char *)end - p, nsizes);
// printf("bd: memory sz is %ld bytes; allocate an size array of length %d\n",
// (char *)end - p, nsizes);

// allocate bd_sizes array
bd_sizes = (Sz_info *)p;
Expand All @@ -297,10 +308,12 @@ 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;
bd_sizes[k].alloc = p;
memset(bd_sizes[k].alloc, 0, sz);
p += sz;
int nblk = NBLK(k);
int npair = nblk / 2;
int sz_xor = sizeof(char) * ROUNDUP(npair, 8) / 8;
bd_sizes[k].xor_alloc = p;
memset(bd_sizes[k].xor_alloc, 0, sz_xor);
p += sz_xor;
}

// allocate the split array for each size k, except for k = 0, since
Expand Down
17 changes: 5 additions & 12 deletions kernel/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
struct devsw devsw[NDEV];
struct {
struct spinlock lock;
struct file file[NFILE];
} ftable;

void
Expand All @@ -31,16 +30,9 @@ 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;
}
}
release(&ftable.lock);
return 0;
f = bd_malloc(sizeof(*f));
f->ref = 1;
return f;
}

// Increment ref count for file f.
Expand Down Expand Up @@ -80,6 +72,8 @@ fileclose(struct file *f)
iput(ff.ip);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем нам нужен ff?

end_op();
}

bd_free(f);
}

// Get metadata about file f.
Expand Down Expand Up @@ -179,4 +173,3 @@ filewrite(struct file *f, uint64 addr, int n)

return ret;
}

39 changes: 8 additions & 31 deletions kernel/kalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,14 @@ struct run {

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);
void *start = (void*)PGROUNDUP((uint64)end);
void *limit = (void*)PHYSTOP;
bd_init(start, limit);
}

// Free the page of physical memory pointed at by pa,
Expand All @@ -46,20 +37,13 @@ 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 +52,8 @@ 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;
void* addr = bd_malloc(PGSIZE);
if (addr && ((uint64)addr % PGSIZE) != 0)
panic("kalloc: page not alligned");
return addr;
}
Loading