bio.c void brelse(struct buf *b)

トップページ
jupiteroak.hatenablog.com


bio.c
https://github.com/mit-pdos/xv6-public/blob/master/bio.c#L120

void brelse(struct buf *b)
{
  if(!holdingsleep(&b->lock))
    panic("brelse");

  releasesleep(&b->lock);

  acquire(&bcache.lock);
  b->refcnt--;
  if (b->refcnt == 0) {
    // 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;
  }
  
  release(&bcache.lock);
}

brelse関数は、バッファbに関連しているスリープロックを解放します。
スリープロックを解放することで、他のプロセスがバッファbを利用できるようになります。

引数 struct buf *b
スリープロックした状態のバッファを指定するアドレスです。


処理の内容

現在実行中のプロセスがスリープロックを保持していることを確認する

if(!holdingsleep(&b->lock))
    panic("brelse");

holdingsleep関数を呼び出して、現在実行中のプロセスがスリープロックを保持しているかを確認します。!holdingsleep(&b->lock)が真となる場合→holdingsleep関数の戻り値が0となる場合→スリープロックを保持していない場合は、panic関数を呼び出してメッセージを出力します。

スリープロックを解放する

releasesleep(&b->lock);

releasesleep関数を呼び出して、バッファbに関連しているスリープロックを解放します。

クリティカルセクションの入口を定める

acquire(&bcache.lock);

バッファキャッシュを排他制御するために、acquire関数を呼び出してロックを取得し、クリティカルセクションの入口とします。

バッファの参照回数を減らす

b->refcnt--;

バッファの参照回数をディクリメントします。

バッファの参照回数が0になった場合

b->refcnt == 0 が真となる場合→バッファの参照回数が0になった場合は、そのバッファをバッファキャッシュの第2要素として追加します(ヘッダーであるbcache.headの次の位置へ移動させます)。バッファキャッシュは、buf構造体の変数head(bcache構造体のメンバ)とbuf構造体変数の配列buf[NBUF](bcache構造体のメンバ)からなる双方向リストです。

引数で渡されたバッファ(b)を一度バッファキャッシュから取り除く

b->next->prev = b->prev;
b->prev->next = b->next;

引数で渡されたバッファ(b)の次にあるバッファ(b->next)のprevメンバが、引数で渡されたバッファ(b)の前にあるバッファ(b->prev)を参照するようにします。
引数で渡されたバッファ(b)の前にあるバッファ(b->prev)のnextメンバが、引数で渡されたバッファの次にあるバッファ(b->next)を参照するようにします。

引数で渡されたバッファ(b)をバッファキャッシュの新しい第2要素として追加する

b->next = bcache.head.next;
b->prev = &bcache.head;

引数で渡されたバッファ(b)のnextメンバが、第2要素のバッファ(これから第3要素になるバッファ bcache.head.next)を参照するようにします。
引数で渡されたバッファ(b)のprevメンバが、ヘッダー(bcache.head)を参照するようにします。

新しく第3要素になったバッファの参照を更新する

bcache.head.next->prev = b;

新しく第3要素になったバッファ(第2要素だったバッファ bcache.head.next)のprevメンバが、引数で渡されたバッファ(b)を参照するようにします。

ヘッダーの参照を更新する

bcache.head.next = b;

ヘッダー(bcache.head)のnextメンバが、引数で渡されたバッファ(b)を参照するようにします。

クリティカルセクションの出口を定める

release(&bcache.lock);

release関数を呼び出して取得していたロックを解放し、クリティカルセクションの出口とします。