MIT 6.S081 Lab9 Lock

 Memory Allocator

struct {
  struct spinlock lock;
  struct run *freelist;
  int num;//当前freelist中数量
} kmem[NCPU];
const int name_size = sizeof("kmem cpu 0");
char kmem_lk_name[NCPU][sizeof("kmem cpu 0")];

void
kinit()
{
  initlock(&stealLock, "stealLock");
  for(int i = 0;i < NCPU; i++){
    snprintf(kmem_lk_name[i], name_size, "kmem cpu %d", i);
    initlock(&kmem[i].lock, kmem_lk_name[i]);
    kmem[i].num = 0;
  }
  freerange(end, (void*)PHYSTOP);
}
void
kfree(void *pa)
{
  struct run *r;

  push_off();
  int cpu_id = cpuid();
  pop_off();
  
  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[cpu_id].lock);
  r->next = kmem[cpu_id].freelist;
  kmem[cpu_id].freelist = r;
  kmem[cpu_id].num++;
  release(&kmem[cpu_id].lock);
}

只有一个cpu能进行steal

struct spinlock stealLock;
void *
kalloc(void)
{
  struct run *r;

  push_off();
  int cpu_id = cpuid();
  pop_off();
  
  acquire(&kmem[cpu_id].lock);
  r = kmem[cpu_id].freelist;
  if(!r){
    acquire(&stealLock);
    int maxMem_id = -1;
    int maxMem = 0;
    //找到剩余最多内存cpu
    for(int i = 0; i < NCPU; i++){
        if(kmem[i].num > maxMem){
          maxMem_id = i;
          maxMem = kmem[i].num;
        }
    }
    //steal
    if(maxMem_id != -1){
      acquire(&kmem[maxMem_id].lock);
      struct run* temp = kmem[cpu_id].freelist;
      kmem[cpu_id].freelist = kmem[maxMem_id].freelist;
      kmem[maxMem_id].freelist = kmem[maxMem_id].freelist->next;
      kmem[cpu_id].freelist->next = temp;
      kmem[cpu_id].num++;
      kmem[maxMem_id].num--;
      release(&kmem[maxMem_id].lock);
    }
    release(&stealLock);

    r = kmem[cpu_id].freelist;
  }
  
  if(r){
    kmem[cpu_id].freelist = r->next;
    kmem[cpu_id].num--;
  }
  release(&kmem[cpu_id].lock);

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

$ kalloctest
start test1
test1 results:
--- lock kmem/bcache stats
lock: kmem cpu 0: #test-and-set 0 #acquire() 88387
lock: kmem cpu 1: #test-and-set 0 #acquire() 169542
lock: kmem cpu 2: #test-and-set 0 #acquire() 175017
lock: bcache.bucket: #test-and-set 0 #acquire() 3
lock: bcache.bucket: #test-and-set 0 #acquire() 17
lock: bcache.bucket: #test-and-set 0 #acquire() 11
lock: bcache.bucket: #test-and-set 0 #acquire() 8
lock: bcache.bucket: #test-and-set 0 #acquire() 3
lock: bcache.bucket: #test-and-set 0 #acquire() 7
lock: bcache.bucket: #test-and-set 0 #acquire() 284
lock: bcache.bucket: #test-and-set 0 #acquire() 11
lock: bcache.bucket: #test-and-set 0 #acquire() 3
lock: bcache.bucket: #test-and-set 0 #acquire() 3
lock: bcache.bucket: #test-and-set 0 #acquire() 3
lock: bcache.bucket: #test-and-set 0 #acquire() 11
lock: bcache: #test-and-set 0 #acquire() 18
--- top 5 contended locks:
lock: proc: #test-and-set 71279 #acquire() 270072
lock: proc: #test-and-set 68672 #acquire() 270072
lock: proc: #test-and-set 65642 #acquire() 270072
lock: proc: #test-and-set 51996 #acquire() 270072
lock: proc: #test-and-set 51493 #acquire() 270072
tot= 0
test1 OK

Buffer cache(有问题)

struct {
  struct spinlock lock;
  struct buf head;
} hash[BUCKET];
void
binit(void)
{
  // struct buf *b;

  for(int i = 0; i < BUCKET; i++){
    snprintf(hash_lk_name[i], name_size2, "bcache.bucket %d", i);
    initlock(&hash[i].lock, hash_lk_name[i]);
  }

  initlock(&bcache.lock, "bcache");   
}
static struct buf*
bget(uint dev, uint blockno)
{
  struct buf *b;
  int index = HASH(dev, blockno);//获取索引号
  acquire(&hash[index].lock);

  //是否已经在缓存区
  for(b = hash[index].head.next; b; b = b->next){
    if(b->dev == dev && b->blockno == blockno){
      b->refcnt++;
      acquire(&tickslock);
      b->ticks = ticks;
      release(&tickslock);

      release(&hash[index].lock);
      acquiresleep(&b->lock);
      return b;
    }
  }
  //不在缓存区
  release(&hash[index].lock); //释放自己的锁
  acquire(&bcache.lock);
  acquire(&hash[index].lock);
  // 这时候另一个进程调用了 bget() 函数,并且 blockno 还是同一个。
  // 在两个进程都找到了空闲缓存后,它们会把两个缓存都加到当前 blockno 的桶中,
  // 这样一个 blockno 对应的缓存就有了两个。
  for(b = hash[index].head.next; b; b = b->next){
    if(b->dev == dev && b->blockno == blockno){
      b->refcnt++;
      acquire(&tickslock);
      b->ticks = ticks;
      release(&tickslock);

      release(&hash[index].lock);
      release(&bcache.lock);
      acquiresleep(&b->lock);
      return b;
    }
  }
  for(int i = 0; i < NBUF; i++){
    if(bcache.buf[i].ticks == 0 && bcache.buf[i].refcnt == 0){
      b = &bcache.buf[i];
      //未使用块缓存
      b->dev = dev;
      b->blockno = blockno;
      b->valid = 0;
      b->refcnt = 1;
      acquire(&tickslock);
      b->ticks = ticks;
      release(&tickslock);

      struct buf *temp = hash[index].head.next;
      hash[index].head.next = b;
      b->prev = &hash[index].head;
      b->next = temp;
      if(temp){
        temp->prev = b;  
      }
      release(&hash[index].lock);
      release(&bcache.lock);
      acquiresleep(&b->lock);
      return b;
    }
  }
  //无空闲:驱逐
  acquire(&tickslock);
  uint ticks_now = ticks;
  release(&tickslock);
  int time = -1;
  int targetBuf = -1;
  int targetBucket = -1;
  for(int i = 0; i < NBUF; i++){
    int index_now = HASH(bcache.buf[i].dev, bcache.buf[i].blockno);
    
    // if(bcache.buf[i].refcnt != 0 )
    //   continue;

    // if(index_now != index && index_now != targetBucket){
    //   acquire(&hash[index_now].lock);
    // }
    if(index_now != index && index_now != targetBucket){
      acquire(&hash[index_now].lock);
    }

    if(bcache.buf[i].refcnt != 0){
      if(index_now != index && index_now != targetBucket){
        release(&hash[index_now].lock);
      }
      continue;
    }
    int interval = ticks_now - bcache.buf[i].ticks;

    if(interval > time){
      if(targetBucket != -1 && targetBucket != index_now && targetBucket != index){
        release(&hash[targetBucket].lock);
      }
      targetBuf = i;
      targetBucket = index_now;
      time = interval;
    }
    else{
      if(index_now != index && index_now != targetBucket){
        release(&hash[index_now].lock);
      }
    }
  }
    if(targetBuf == -1 || targetBucket == -1){
      panic("bget: no buffers");
    }
    
    //获得要变换的锁
    if(targetBucket == index){
        b = &bcache.buf[targetBuf];
        //未使用块缓存
        b->dev = dev;
        b->blockno = blockno;
        b->valid = 0;
        b->refcnt = 1;
        acquire(&tickslock);
        b->ticks = ticks;
        release(&tickslock);

        release(&hash[targetBucket].lock);
        release(&bcache.lock);
        acquiresleep(&b->lock);
        return b;
    }
    else{
      b = &bcache.buf[targetBuf];
      //将b逐出原来bucket
      b->prev->next = b->next;
      if(b->next)
        b->next->prev = b->prev;
      release(&hash[targetBucket].lock);

      //将b放入当前bucket
        b->dev = dev;
        b->blockno = blockno;
        b->valid = 0;
        b->refcnt = 1;
        acquire(&tickslock);
        b->ticks = ticks;
        release(&tickslock);

        struct buf *temp = hash[index].head.next;
        hash[index].head.next = b;
        b->prev = &hash[index].head;
        b->next = temp;
        if(temp){
          temp->prev = b;
        }
        release(&hash[index].lock);
        release(&bcache.lock);
        acquiresleep(&b->lock);
        return b;
    }
  panic("bget: no buffers");
}
void
brelse(struct buf *b)
{
  if(!holdingsleep(&b->lock))
    panic("brelse");

  releasesleep(&b->lock);

  int index = HASH(b->dev, b->blockno);//获取索引号
  acquire(&hash[index].lock);

  b->refcnt--;
  if (b->refcnt == 0) {
    acquire(&tickslock);
    b->ticks = ticks;
    release(&tickslock);
  }
  
  release(&hash[index].lock);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值