diff --git a/fs.img.bk b/fs.img.bk index b97eba1..9dc0c65 100644 Binary files a/fs.img.bk and b/fs.img.bk differ diff --git a/gradelib.py b/gradelib.py index f0d4934..21dd2bc 100644 --- a/gradelib.py +++ b/gradelib.py @@ -238,7 +238,7 @@ def make(*target): post_make() def show_command(cmd): - from pipes import quote + from shlex import quote print("\n$", " ".join(map(quote, cmd))) def maybe_unlink(*paths): diff --git a/kernel/bio.c b/kernel/bio.c index bc4c3db..ede3a10 100644 --- a/kernel/bio.c +++ b/kernel/bio.c @@ -37,16 +37,16 @@ struct { uint hash_head[NHASH]; uint nxt[NBUF]; struct spinlock hashlock[NHASH]; - uint freelist_head; + uint freelist_head[NCPU]; // 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 spinlock freelistlock; + struct spinlock freelistlock[NCPU]; } bcache; uint hasher(uint dev,uint blockno){ - return blockno%NHASH; + return ((uint64)dev<<32|blockno)%NHASH; } int hash_get(uint dev,uint blockno){ @@ -60,6 +60,7 @@ int hash_get(uint dev,uint blockno){ } RET: + release(&bcache.hashlock[hash_pos]); // printf("%u\n",pos); return pos; @@ -75,16 +76,42 @@ void hash_add(uint dev,uint blockno,uint buf_pos){ void hash_del(uint dev,uint blockno){ const uint hash_pos=hasher(dev, blockno); + push_off(); + const uint cpu=cpuid(); + pop_off(); 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]; + struct buf *b=&bcache.buf[cur]; + --b->refcnt; + if (b->refcnt == 0) { + 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; + for(int i=cpu;;i=(i+1)%NCPU){ + push_off(); + if(holding(&bcache.freelistlock[i])){ + pop_off(); + continue; + } + pop_off(); + acquire(&bcache.freelistlock[i]); + const int pos=b-bcache.buf; + // printf("%d\n",pos); + bcache.nxt[pos]=bcache.freelist_head[i]; + bcache.freelist_head[i]=pos; + + // DEBUG(); + // printf("%u\n",bcache.freelist_head); + + release(&bcache.freelistlock[i]); + break; + } + break; } - bcache.nxt[cur]=-1; - break; } pre=cur; } @@ -97,22 +124,26 @@ 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; initsleeplock(&b->lock, "buffer"); const uint cur=b-bcache.buf; - bcache.nxt[cur]=bcache.freelist_head; - bcache.freelist_head=cur; + bcache.nxt[cur]=bcache.freelist_head[which]; + bcache.freelist_head[which]=cur; + which=(which+1)%NCPU; // bcache.head.next->prev = b; // bcache.head.next = b; } @@ -125,8 +156,8 @@ static struct buf* bget(uint dev, uint blockno) { struct buf *b; - - int pos=hash_get(dev, blockno); + // acquire(&bcache.lock); + const 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){ @@ -138,39 +169,60 @@ bget(uint dev, uint blockno) // } if(pos>=0){ b=&bcache.buf[pos]; - ++b->refcnt; + const uint hash_pos=hasher(dev, blockno); + acquire(&bcache.hashlock[hash_pos]); + ++bcache.buf[pos].refcnt; + release(&bcache.hashlock[hash_pos]); acquiresleep(&b->lock); + // release(&bcache.lock); return b; } + push_off(); + const uint cpu=cpuid(); + pop_off(); // Not cached. // Recycle the least recently used (LRU) unused buffer. - 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; + for(int i=cpu;;i=(i+1)%NCPU){ + push_off(); + if(holding(&bcache.freelistlock[i])){ + pop_off(); + continue; + } + pop_off(); + acquire(&bcache.freelistlock[i]); + if(bcache.freelist_head[i]==-1){ + release(&bcache.freelistlock[i]); + continue; + } + // DEBUG(); + // 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[i]]; + const int ori=bcache.freelist_head[i]; + bcache.freelist_head[i]=bcache.nxt[bcache.freelist_head[i]]; + hash_add(dev,blockno,ori); + b->dev=dev; + b->blockno=blockno; + b->valid=0; + b->refcnt=1; + release(&bcache.freelistlock[i]); + acquiresleep(&b->lock); + // release(&bcache.lock); + return b; + } panic("bget: no buffers"); } @@ -202,15 +254,15 @@ bwrite(struct buf *b) void brelse(struct buf *b) { + if(!holdingsleep(&b->lock)) panic("brelse"); releasesleep(&b->lock); // acquire(&bcache.lock); - b->refcnt--; - if (b->refcnt == 0) { - hash_del(b->dev, b->blockno); + + hash_del(b->dev, b->blockno); // no one is waiting for it. // b->next->prev = b->prev; // b->prev->next = b->next; @@ -218,16 +270,8 @@ brelse(struct buf *b) // 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); } @@ -235,14 +279,20 @@ brelse(struct buf *b) void bpin(struct buf *b) { // acquire(&bcache.lock); + const uint hash_pos=hasher(b->dev, b->blockno); + acquire(&bcache.hashlock[hash_pos]); b->refcnt++; + release(&bcache.hashlock[hash_pos]); // release(&bcache.lock); } void bunpin(struct buf *b) { // acquire(&bcache.lock); + const uint hash_pos=hasher(b->dev, b->blockno); + acquire(&bcache.hashlock[hash_pos]); b->refcnt--; + release(&bcache.hashlock[hash_pos]); // release(&bcache.lock); } diff --git a/kernel/fs.c b/kernel/fs.c index 6c4079e..7200462 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -93,12 +93,14 @@ bfree(int dev, uint b) { struct buf *bp; int bi, m; - + DEBUG(); + printf("%d %d\n",dev,b); bp = bread(dev, BBLOCK(b, sb)); bi = b % BPB; m = 1 << (bi % 8); - if((bp->data[bi/8] & m) == 0) + if((bp->data[bi/8] & m) == 0){ panic("freeing free block"); + } bp->data[bi/8] &= ~m; log_write(bp); brelse(bp); diff --git a/time.txt b/time.txt new file mode 100644 index 0000000..62f9457 --- /dev/null +++ b/time.txt @@ -0,0 +1 @@ +6 \ No newline at end of file