linuxのメモ

Linux kernelの実装を解説していきます (対象ver 4.5)

バッファ操作 - rb_handle_head_page()

概要

バッファのヘッダを更新する

詳細

この関数では以下の引数を受け取る

  • CPUごとのバッファへのポインタ : cpu_buffer
  • バッファの最後のページへのポインタ : tail_page
  • バッファの次のページへのポインタ : next_page

rb_head_page_set_update()RB_PAGE_HEADを渡してnext_pageのフラグ_RB_PAGE_UPDATEに変更するが、この返り値によって以下のように処理が異なる

  • 返り値がRB_PAGE_HEADの場合
    • 元のフラグがRB_PAGE_HEADであるため変更に成功しており、local_add()cpu_bufferoverrunメンバにrb_page_entries()で取得したnext_pageのエントリ数を加算し、cpu_bufferentries_bytesメンバからBUF_PAGE_SIZEの値を減算する
  • 返り値がRB_PAGE_UPDATEの場合
    • 元のフラグがRB_PAGE_UPDATEであるため変更に失敗しており、特に処理を行わない
  • 返り値がRB_PAGE_NORMALの場合
    • 元のフラグがRB_PAGE_NORMALであるため変更に失敗しており、1を返して処理を中断する
  • 返り値がRB_PAGE_MOVEDの場合
    • 実行中に他のスレッドにより処理されているため、1を返して処理を中断する
  • 上記以外の場合
    • 予期せぬフラグが設定されているため、RB_WARN_ON()cpu_bufferと1を渡すことで必ずエラーを出力し、-1を返して処理を中断する

ここまでの処理はnext_pageのフラグをRB_PAGE_HEADからRB_PAGE_UPDATEに変更する処理のため変更に成功するか既にRB_PAGE_UPDATE_である場合は処理を継続する

next_pageをローカル変数であるnew_headに代入しrb_inc_page()を実行することでnew_headの参照先をnext_pageの次のバッファに変更する

その後rb_head_page_set_head()RB_PAGE_NORMALを渡してnew_headのフラグをBR_PAGE_HEADに変更するため、変更に成功するか既にBR_PAGE_HEADがセットされている場合は処理を継続するが、それ以外の場合は予期せぬフラグが設定されているため、RB_WARN_ON()cpu_bufferと1を渡すことで必ずエラーを出力し、-1を返して処理を中断する

処理を継続する場合は変更に成功した場合と、既にセット済みであった場合で以下のように処理が異なる

  • 変更に成功した場合
    • rb_head_page_set_normal()RB_PAGE_UPDATEを渡してnext_pageのフラグをRB_PAGE_NORMALに変更する
    • 変更に失敗した場合はRB_WARN_ON()でエラーを表示し、-1を返して処理を中断する
  • 既にセット済みの場合
    • READ_ONCE()cpu_buffertail_pageメンバを取得し、取得した値がtail_pagenext_pageのいずれにも一致しない場合はnew_headは通常のバッファであると判断しrb_head_page_set_normal()RB_PAGE_HEADを渡してnew_headのフラグをRB_PAGE_NORMALに変更する

途中で処理が中断されなかった場合は0を返して処理を終了する

以上の内容から返り値によって以下の状態が判別できる

  • 返り値 1
    • next_pageのフラグがRB_PAGE_NORMALかリストの入れ替え後に他のスレッドで移動された場合
  • 返り値 0
    • next_pageのフラグをRB_PAGE_UPDATEに変更(既にセットしている場合も含む)し、new_headのフラグが既にRB_PAGE_HEADがセットされていた場合
    • next_pageのフラグをRB_PAGE_UPDATEに変更(既にセットしている場合も含む)し、new_headのフラグにRB_PAGE_HEADをセットした後にnext_pageのフラグをRB_PAGE_NORMALに変更できた場合
  • 返り値 -1
    • エラー

となる