Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lock那个实验的第二个buffer cache解法有问题,会有死锁问题出现 #21

Open
jieqiyue opened this issue Dec 1, 2023 · 0 comments

Comments

@jieqiyue
Copy link

jieqiyue commented Dec 1, 2023

你用的是holding判断,但是去看holding的实现,只有当前线程持有了传入的锁,才会返回1.
所以,用holding判断其实没什么用。
你的那个能够通过测试的原因是因为你优先从当前槽位开始搜索空闲buf,就像博客里面说的,这样会降低死锁的概率。
所以,测试用例就没有测到这种情况。
如果把你的实现改为从第0个槽位开始搜索空闲buf的话,那么就不会通过测试用例了。

另外,我觉得可以把holding函数换一下,自己新写一个函数,去掉后面的判断当前cpu是不是持有锁的cpu。然后使用这个函数。

int
islock(struct spinlock *lk)
{
  int r;
  r = (lk->locked);
  return r;
}

static struct buf*
bget(uint dev, uint blockno)
{
    struct buf *b;

    int index = hash(blockno);
    acquire(&bcache[index].lock);

    // Is the block already cached?
    for(b = bcache[index].head; b != 0; b = b->next){
        if(b->dev == dev && b->blockno == blockno){
            //printf("block num:%d,increcse++\n",blockno);
            b->refcnt++;
            release(&bcache[index].lock);
            acquiresleep(&b->lock);
            return b;
        }
    }

    // printf("inner\n");
    for(int i = 0;i < HASHLEN;i++){
        // 由于在这里的时候,还是持有index这个位置的锁的。所以当当前的i跟index不同的时候,才需要去尝试获取锁。
        if(i != index){
            if(islock(&bcache[i].lock)){
                continue;
            }
            acquire(&bcache[i].lock);
        }

        struct buf *temp = bcache[i].head;
        struct buf *pre = 0;
        while (temp){
            if(temp->refcnt == 0)  {
                // 找到一个空闲的buf,就把它设置好各种参数
                temp->dev = dev;
                temp->blockno = blockno;
                temp->valid = 0;
                temp->refcnt = 1;
                // 开始移动这个buf
                if(i == index){
                    // 如果就是在哈希目标的位置上找到的buf,那就不用移动
                    release(&bcache[i].lock);
                }else{
                    // 不然需要将该buf移动到哈希目标的位置上,在这个分支中,此时已经获取到了两个锁,一个是index,一个是i
                    //  i是找到的空闲buf的位置,index是目标下标位置
                    if(pre != 0){
                        pre->next = temp->next;
                    }else{
                        bcache[i].head = temp->next;
                    }
                    // 将i位置的temp节点从单链表中移除之后,就能够释放i位置的锁了。
                    release(&bcache[i].lock);
                    // 此时还是有index位置的锁,此时将temp加入到index的单链表中
                    temp->next = bcache[index].head;
                    bcache[index].head = temp;
                    release(&bcache[index].lock);
                }

                acquiresleep(&temp->lock);
                //printf("新分配,block num:%d,ref count:%d\n",temp->blockno,temp->refcnt);
                return temp;
            }
            pre = temp;
            temp = temp->next;
        }
        if(i != index){
            release(&bcache[i].lock);
        }

    }

    panic("bget: no buffers");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant