From c8587aba916110198cc58b8d6a8c0fdfbd0f8998 Mon Sep 17 00:00:00 2001 From: whatever Date: Mon, 25 Nov 2024 14:20:37 +0800 Subject: [PATCH] debugging lock lab without LRU --- fs.img.bk | Bin 2048000 -> 2048000 bytes kernel/bio.c | 180 +++++++++++++++++++++++++++++++++++++----------- kernel/buf.h | 4 +- kernel/defs.h | 1 + kernel/kalloc.c | 76 +++++++++++--------- 5 files changed, 186 insertions(+), 75 deletions(-) diff --git a/fs.img.bk b/fs.img.bk index 2bd36abdf7391e9934afe18266bdd074a4a0bd7e..b97eba1216ecb8de4e8e2abfa6c0d6aac99809a3 100644 GIT binary patch delta 265 zcmci5%MAfh06@`T9)t1!e>WOX0-Y#83zNKv+y*pYW$l;P+#)of7cE%Xob8D*k1@X{ z>1(~s-sOL|Pad1N39r>Q`}`1|!u`1mw{R{V!~zzvgb4;LV+B*JVh!t;U7*c(u@Ai?4l z9>I=^f&+L5h?J7(D_*|l{TMScW;D0Gc-|JaXvE`PBANGQ<*Nvm8-AeRWE}Q04t?zwzn_fTo?$;k4 z>DNP|>6{$?U6AONSiE&c diff --git a/kernel/bio.c b/kernel/bio.c index 60d91a6..bc4c3db 100644 --- a/kernel/bio.c +++ b/kernel/bio.c @@ -23,32 +23,98 @@ #include "fs.h" #include "buf.h" + +// TODO: use sleeplock instead of spinlock + struct { struct spinlock lock; struct buf buf[NBUF]; - + #define NHASH 233 + // struct hash_t{ + // uint pos; + // struct hash_t *nxt; + // }hash[NHASH]; + uint hash_head[NHASH]; + uint nxt[NBUF]; + struct spinlock hashlock[NHASH]; + uint freelist_head; // Linked list of all buffers, through prev/next. // Sorted by how recently the buffer was used. // head.next is most recent, head.prev is least. - struct buf head; + // struct buf head; + struct spinlock freelistlock; } bcache; +uint hasher(uint dev,uint blockno){ + return blockno%NHASH; +} + +int hash_get(uint dev,uint blockno){ + const uint hash_pos=hasher(dev, blockno); + int pos=-1; + acquire(&bcache.hashlock[hash_pos]); + for(int cur=bcache.hash_head[hash_pos];cur!=-1;cur=bcache.nxt[cur]) + if(bcache.buf[cur].dev==dev && bcache.buf[cur].blockno==blockno){ + pos=cur; + goto RET; + } + + RET: + release(&bcache.hashlock[hash_pos]); + // printf("%u\n",pos); + return pos; +} + +void hash_add(uint dev,uint blockno,uint buf_pos){ + const uint hash_pos=hasher(dev, blockno); + acquire(&bcache.hashlock[hash_pos]); + bcache.nxt[buf_pos]=bcache.hash_head[hash_pos]; + bcache.hash_head[hash_pos]=buf_pos; + release(&bcache.hashlock[hash_pos]); +} + +void hash_del(uint dev,uint blockno){ + const uint hash_pos=hasher(dev, blockno); + acquire(&bcache.hashlock[hash_pos]); + for(int cur=bcache.hash_head[hash_pos],pre=-2;cur!=-1;cur=bcache.nxt[cur]){ + if(bcache.buf[cur].dev==dev && bcache.buf[cur].blockno==blockno){ + if(pre==-2){// the head is what we are looking for + bcache.hash_head[hash_pos]=bcache.nxt[cur]; + }else{ + bcache.nxt[pre]=bcache.nxt[cur]; + } + bcache.nxt[cur]=-1; + break; + } + pre=cur; + } + release(&bcache.hashlock[hash_pos]); +} + void binit(void) { struct buf *b; initlock(&bcache.lock, "bcache"); - + initlock(&bcache.freelistlock, "bcache_freelist"); + for(int i=0;inext = bcache.head.next; - b->prev = &bcache.head; + // b->next = bcache.head.next; + // b->prev = &bcache.head; initsleeplock(&b->lock, "buffer"); - bcache.head.next->prev = b; - bcache.head.next = b; + const uint cur=b-bcache.buf; + bcache.nxt[cur]=bcache.freelist_head; + bcache.freelist_head=cur; + // bcache.head.next->prev = b; + // bcache.head.next = b; } } @@ -60,31 +126,51 @@ bget(uint dev, uint blockno) { struct buf *b; - acquire(&bcache.lock); - + int pos=hash_get(dev, blockno); // Is the block already cached? - for(b = bcache.head.next; b != &bcache.head; b = b->next){ - if(b->dev == dev && b->blockno == blockno){ - b->refcnt++; - release(&bcache.lock); - acquiresleep(&b->lock); - return b; - } + // for(b = bcache.head.next; b != &bcache.head; b = b->next){ + // if(b->dev == dev && b->blockno == blockno){ + // b->refcnt++; + // release(&bcache.lock); + // acquiresleep(&b->lock); + // return b; + // } + // } + if(pos>=0){ + b=&bcache.buf[pos]; + ++b->refcnt; + acquiresleep(&b->lock); + return b; } - // Not cached. // Recycle the least recently used (LRU) unused buffer. - 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; - release(&bcache.lock); - acquiresleep(&b->lock); - return b; - } - } + acquire(&bcache.freelistlock); + // for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ + // if(b->refcnt == 0) { + // hash_add(dev, blockno, b-bcache.buf); + // b->dev = dev; + // b->blockno = blockno; + // b->valid = 0; + // b->refcnt = 1; + // release(&bcache.lock); + // acquiresleep(&b->lock); + // return b; + // } + // } + // for(uint cur=bcache.freelist_head;cur!=-1;cur=bcache.nxt[cur]) + // DEBUG(); + // printf("%u\n",bcache.freelist_head); + + b=&bcache.buf[bcache.freelist_head]; + hash_add(dev,blockno,bcache.freelist_head); + b->dev=dev; + b->blockno=blockno; + b->valid=0; + b->refcnt=1; + bcache.freelist_head=bcache.nxt[bcache.freelist_head]; + release(&bcache.freelistlock); + acquiresleep(&b->lock); + return b; panic("bget: no buffers"); } @@ -121,33 +207,43 @@ brelse(struct buf *b) releasesleep(&b->lock); - acquire(&bcache.lock); + // acquire(&bcache.lock); b->refcnt--; if (b->refcnt == 0) { + hash_del(b->dev, b->blockno); // no one is waiting for it. - 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; + // 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;gi + acquire(&bcache.freelistlock); + const int pos=b-bcache.buf; + bcache.nxt[pos]=bcache.freelist_head; + bcache.freelist_head=pos; + + // DEBUG(); + // printf("%u\n",bcache.freelist_head); + + release(&bcache.freelistlock); } - release(&bcache.lock); + // release(&bcache.lock); } void bpin(struct buf *b) { - acquire(&bcache.lock); + // acquire(&bcache.lock); b->refcnt++; - release(&bcache.lock); + // release(&bcache.lock); } void bunpin(struct buf *b) { - acquire(&bcache.lock); + // acquire(&bcache.lock); b->refcnt--; - release(&bcache.lock); + // release(&bcache.lock); } diff --git a/kernel/buf.h b/kernel/buf.h index 4616e9e..0a660a4 100644 --- a/kernel/buf.h +++ b/kernel/buf.h @@ -5,8 +5,8 @@ struct buf { uint blockno; struct sleeplock lock; uint refcnt; - struct buf *prev; // LRU cache list - struct buf *next; + // struct buf *prev; // LRU cache list + // struct buf *next; uchar data[BSIZE]; }; diff --git a/kernel/defs.h b/kernel/defs.h index d133cd3..60e5a8c 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -237,3 +237,4 @@ void netinit(void); void net_rx(char *buf, int len); #endif +#define DEBUG() printf("File: %s, Line: %d, Function: %s\n", __FILE__, __LINE__, __func__) \ No newline at end of file diff --git a/kernel/kalloc.c b/kernel/kalloc.c index 7a09849..1d36381 100644 --- a/kernel/kalloc.c +++ b/kernel/kalloc.c @@ -46,10 +46,9 @@ freerange(void *pa_start, void *pa_end) // initializing the allocator; see kinit above.) void kfree(void *pa) -{ - push_off(); - const int cpu=cpuid(); +{ struct run *r; + int id; if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP) panic("kfree"); @@ -58,11 +57,20 @@ kfree(void *pa) memset(pa, 1, PGSIZE); r = (struct run*)pa; - acquire(&kmem[cpu].lock); - r->next = kmem[cpu].freelist; - kmem[cpu].freelist = r; - release(&kmem[cpu].lock); + + push_off(); + id = cpuid(); pop_off(); + + acquire(&kmem[id].lock); + r->next = kmem[id].freelist; + kmem[id].freelist = r; + release(&kmem[id].lock); + + /*acquire(&kmem.lock); + r->next = kmem.freelist; + kmem.freelist = r; + release(&kmem.lock);*/ } // Allocate one 4096-byte page of physical memory. @@ -71,33 +79,39 @@ kfree(void *pa) void * kalloc(void) { - push_off(); struct run *r; - const int cpu=cpuid(); - acquire(&kmem[cpu].lock); - r = kmem[cpu].freelist; + int id; + + push_off(); + id = cpuid(); + pop_off(); + + acquire(&kmem[id].lock); + r = kmem[id].freelist; + if (r) + kmem[id].freelist = r->next; + release(&kmem[id].lock); + if (r) + goto kallocinit; + + for (int i=(id+1)%NCPU; i!=id; i=(i+1)%NCPU) { + acquire(&kmem[i].lock); + r = kmem[i].freelist; + if (r) + kmem[i].freelist = r->next; + release(&kmem[i].lock); + if (r) + goto kallocinit; + } + + /*acquire(&kmem.lock); + r = kmem.freelist; if(r) - kmem[cpu].freelist = r->next; - while(!r) - for(int i=0;inext; - goto fine; - } - release(&kmem[i].lock); - continue; - fine: - break; - } - release(&kmem[cpu].lock); + kmem.freelist = r->next; + release(&kmem.lock);*/ + +kallocinit: if(r) memset((char*)r, 5, PGSIZE); // fill with junk - pop_off(); return (void*)r; }