(19)【発行国】日本国特許庁(JP)
(12)【公報種別】特許公報(B2)
(11)【特許番号】
(24)【登録日】2023-01-20
(45)【発行日】2023-01-30
(54)【発明の名称】エポックベースのメモリ収集技法とポインタベースのメモリ収集技法を混合するためのコンピュータシステム、方法および記録媒体
(51)【国際特許分類】
G06F 9/448 20180101AFI20230123BHJP
G06F 9/50 20060101ALI20230123BHJP
G06F 12/00 20060101ALI20230123BHJP
【FI】
G06F9/448
G06F9/50 120A
G06F12/00 590
(21)【出願番号】P 2021098267
(22)【出願日】2021-06-11
【審査請求日】2021-06-11
(31)【優先権主張番号】10-2020-0172853
(32)【優先日】2020-12-11
(33)【優先権主張国・地域又は機関】KR
【新規性喪失の例外の表示】特許法第30条第2項適用 2020年6月11日、41stACM SIGPLAN Conference on Programming Language Design and Implementation,PLDI2020,pp.314-328 (https://doi.org/10.1145/3385412.3385978)において公開
(73)【特許権者】
【識別番号】514260642
【氏名又は名称】コリア アドバンスド インスティチュート オブ サイエンス アンド テクノロジィ
(74)【代理人】
【識別番号】110000408
【氏名又は名称】弁理士法人高橋・林アンドパートナーズ
(72)【発明者】
【氏名】カン ジフン
(72)【発明者】
【氏名】チョン ジェファン
【審査官】多賀 実
(56)【参考文献】
【文献】米国特許出願公開第2018/0253311(US,A1)
【文献】Balmau, Oana et al.,"Fast and Robust Memory Reclamation for Concurrent Data Structures",Proceedings of the 28th ACM Symposium on Parallelism in Algorithms and Architectures [online],米国,Association for Computing Machinery,2016年07月11日,pp.349-359,[令和4年8月8日検索], インターネット:<URL: https://dl.acm.org/doi/abs/10.1145/2935764.2935790>,DOI:10.1145/2935764.2935790
(58)【調査した分野】(Int.Cl.,DB名)
G06F 9/448
G06F 9/50- 9/54
G06F 12/00-12/02
(57)【特許請求の範囲】
【請求項1】
コンピュータシステムの方法であって、
ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、および
前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行する段階
を含
み、
前記ポインタおよびエポックベースのメモリ収集技法を実現する段階は、前記ポインタベースのメモリ収集技法の関数とともに、前記エポックベースメモリ収集技法の関数を利用して前記ポインタおよびエポックベースのメモリ収集技法を実現し、
前記ポインタベースのメモリ収集技法の関数は、
共有メモリに指定されたローカルポインタ(l)がスレッドによって保護されるように、保護されたポインタリストに前記ローカルポインタ(l)を追加するためのprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)を取り除くためのunprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)に対する収集のためのretire(l)、または
前記保護されたポインタリストにないローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含み、
前記エポックベースのメモリ収集技法の関数は、
スレッドがアクティブ状態で前記共有メモリにアクセスするように設定するためのset_active()、
スレッドが非アクティブ状態で前記共有メモリにアクセスしないように設定するためのset_quiescent()、
アクティブ状態にあるスレッドに対して生成されたローカルポインタ(l)に対する収集のためのretire(l)、または
アクティブ状態にあるスレッドに対して廃棄されたローカルポインタに対する収集のためのcollect()のうちの少なくとも1つを含む方法。
【請求項2】
コンピュータシステムの方法であって、
ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、および
前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行する段階
を含み、
前記ポインタおよびエポックベースのメモリ収集技法を実現する段階は、
前記ポインタベースのメモリ収集技法の関数を利用して前記ポインタおよびエポックベースのメモリ収集技法を実現し、
イジェクトする(ejecting)スレッドとイジェクトされる(ejected)スレッドを、前記イジェクトされるスレッドの状態ワードで互いに同期化する段階、および
前記イジェクトするスレッドが前記イジェクトされるスレッドの前記状態ワードを変更する段階を含
み、
前記ポインタベースのメモリ収集技法の関数は、
共有メモリに指定されたローカルポインタ(l)がスレッドによって保護されるように、保護されたポインタリストに前記ローカルポインタ(l)を追加するためのprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)を取り除くためのunprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)に対する収集のためのretire(l)、または
前記保護されたポインタリストにないローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含む方法。
【請求項3】
前記状態ワードを変更する段階は、
前記イジェクトされるスレッドの状態に基づき、前記状態ワードの残りのバイトに前記イジェクトされるスレッドがイジェクトされることを示すフラッグを表示する段階、および
前記イジェクトされるスレッドの保護されたポインタリストに基づき、前記イジェクトされるスレッドの状態をアップデートする段階を含む、
請求項
2に記載の方法。
【請求項4】
コンピュータシステムであって、
メモリ、および
前記メモリに接続され、前記メモリに記録された少なくとも1つの命令を実行するように構成されたプロセッサを含み、
前記プロセッサは、
ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現し、
前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行
し、
前記ポインタベースのメモリ収集技法の関数とともに、前記エポックベースメモリ収集技法の関数を利用して前記ポインタおよびエポックベースのメモリ収集技法を実現し、
前記
ポインタベースのメモリ収集技法の関数は、
共有メモリに指定されたローカルポインタ(l)がスレッドによって保護されるように、保護されたポインタリストに前記ローカルポインタ(l)を追加するためのprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)を取り除くためのunprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)に対する収集のためのretire(l)、または
前記保護されたポインタリストにないローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含み、
前記エポックベースのメモリ収集技法の関数は、
スレッドがアクティブ状態で前記共有メモリにアクセスするように設定するためのset_active()、
スレッドが非アクティブ状態で前記共有メモリにアクセスしないように設定するためのset_quiescent()、
アクティブ状態にあるスレッドに対して生成されたローカルポインタ(l)に対する収集のためのretire(l)、または
アクティブ状態にあるスレッドに対して廃棄されたローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含むように構成される、
コンピュータシステム。
【請求項5】
コンピュータシステムであって、
メモリ、および
前記メモリに接続され、前記メモリに記録された少なくとも1つの命令を実行するように構成されたプロセッサを含み、
前記プロセッサは、
ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現し、
前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行し、
前記ポインタベースのメモリ収集技法の関数を利用して前記ポインタおよびエポックベースのメモリ収集技法を実現し、
イジェクトするスレッドとイジェクトされるスレッドを、前記イジェクトされるスレッドの状態ワードで互いに同期化し、
前記イジェクトするスレッドが前記イジェクトされるスレッドの前記状態ワードを変更するように構成され
、
前記ポインタベースのメモリ収集技法の関数は、
共有メモリに指定されたローカルポインタ(l)がスレッドによって保護されるように、保護されたポインタリストに前記ローカルポインタ(l)を追加するためのprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)を取り除くためのunprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)に対する収集のためのretire(l)、または
前記保護されたポインタリストにないローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含むコンピュータシステム。
【請求項6】
前記プロセッサは、
前記イジェクトされるスレッドの状態に基づき、前記状態ワードの残りのバイトに前記イジェクトされるスレッドがイジェクトされることを示すフラッグを表示し、
前記イジェクトされるスレッドの保護されたポインタリストに基づき、前記イジェクトされるスレッドの状態をアップデートするように構成される、
請求項
5に記載のコンピュータシステム。
【請求項7】
非一時的なコンピュータ読み取り可能な記録媒体であって、
ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、および
前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行する段階
を実行
し、
前記ポインタおよびエポックベースのメモリ収集技法を実現する段階は、前記ポインタベースのメモリ収集技法の関数とともに、前記エポックベースメモリ収集技法の関数を利用して前記ポインタおよびエポックベースのメモリ収集技法を実現し、
前記ポインタベースのメモリ収集技法の関数は、
共有メモリに指定されたローカルポインタ(l)がスレッドによって保護されるように、保護されたポインタリストに前記ローカルポインタ(l)を追加するためのprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)を取り除くためのunprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)に対する収集のためのreti
re(l)、または
前記保護されたポインタリストにないローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含み、
前記エポックベースのメモリ収集技法の関数は、
スレッドがアクティブ状態で前記共有メモリにアクセスするように設定するためのset_active()、
スレッドが非アクティブ状態で前記共有メモリにアクセスしないように設定するためのset_quiescent()、
アクティブ状態にあるスレッドに対して生成されたローカルポインタ(l)に対する収集のためのretire(l)、または
アクティブ状態にあるスレッドに対して廃棄されたローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含む、1つ以上のプログラムを記録
したコンピュータ読み取り可能な記録媒体。
【請求項8】
非一時的なコンピュータ読み取り可能な記録媒体であって、
ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、および
前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行する段階
を実行し、
前記ポインタおよびエポックベースのメモリ収集技法を実現する段階は、
前記ポインタベースのメモリ収集技法の関数を利用して前記ポインタおよびエポックベースのメモリ収集技法を実現する段階、
イジェクトするスレッドとイジェクトされるスレッドを、前記イジェクトされるスレッドの状態ワードで互いに同期化する段階、および
前記イジェクトするスレッドが前記イジェクトされるスレッドの前記状態ワードを変更する段階を含
み、
前記ポインタベースのメモリ収集技法の関数は、
共有メモリに指定されたローカルポインタ(l)がスレッドによって保護されるように、保護されたポインタリストに前記ローカルポインタ(l)を追加するためのprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)を取り除くためのunprotect(l)、
前記保護されたポインタリストにあるローカルポインタ(l)に対する収集のためのreti
re(l)、または
前記保護されたポインタリストにないローカルポインタに対する収集のためのcollect()
のうちの少なくとも1つを含む、1つ以上のプログラムを記録したコンピュータ読み取り可能な記録媒体。
【請求項9】
前記状態ワードを変更する段階は、
前記イジェクトされるスレッドの状態に基づき、前記状態ワードの残りのバイトに前記イジェクトされるスレッドがイジェクトされることを示すフラッグを表示する段階、および
前記イジェクトされるスレッドの保護されたポインタリストに基づき、前記イジェクトされるスレッドの状態をアップデートする段階を含む、
請求項
8に記載のコンピュータ読み取り可能な記録媒体。
【発明の詳細な説明】
【技術分野】
【0001】
多様な実施形態は、エポックベースのメモリ収集技法とポインタベースのメモリ収集技法を混合するためのコンピュータシステムおよびこの方法に関する。
【背景技術】
【0002】
CPUの多くのコアを効率よく利用するためには、多くのコアが同時にアクセスすることのできる同時性データ構造を使用する必要がある。同時性データ構造とは、多数のスレッド(thread)にデータを同時に入れたり抜いたりすることのできるデータ構造を意味する。同時性データ構造では、多数のスレッドの相互作用を一度に考慮して規律しなければならないため、1つのスレッドにアクセスする順次的データ構造よりも遥かに複雑である。特に、メモリ収集のときに複雑さが高まるようになるが、その理由は、同時性データ構造では1つのスレッドがデータを抜いた後でも他のスレッドがデータにアクセスすることができるためである。他のスレッドで絶対にデータにアクセスできないことを確認してからでないと、データを持っていたメモリを収集することができない。
【0003】
同時性データ構造のメモリ収集は極めて難しい問題であり、このような問題だけを解決するための多様な技法が提案されてきた。最も有名な技法は、ポインタベースのメモリ収集技法(pointer-based memory reclamation)とエポックベースのメモリ収集技法(epoch based memory reclamation)である。ポインタベースの収集技法は、メモリ使用量が少なく、メモリを漏れなく収集できるという長所はあるものの、動きが遅く、多くのデータ構造には適用できないという短所がある。この反面、エポックベースの収集技法は、メモリ使用量が少なく、迅速であり、多くのデータ構造に適用可能であるという長所はあるが、メモリを漏れなく収集することができないという短所がある。
【発明の概要】
【発明が解決しようとする課題】
【0004】
多様な実施形態は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合することで、2つの技法の長所をすべて保有した収集技法を提供する。多様な実施形態に係るポインタおよびエポックベースのメモリ収集技法(pointer-and-epoch-based memory reclamation:PEBR)は、2つの技法のアルゴリズムを混合することにより、メモリ使用量が少なく、迅速であり、多くのデータ構造に適用可能であり、メモリを漏れなく収集することができる。
【課題を解決するための手段】
【0005】
多様な実施形態に係るコンピュータシステムによる方法は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、および前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行する段階を含んでよい。
【0006】
多様な実施形態に係るコンピュータシステムは、メモリ、および前記メモリに接続され、前記メモリに記録された少なくとも1つの命令を実行するように構成されたプロセッサを含み、前記プロセッサは、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現し、前記ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行するように構成されてよい。
【0007】
多様な実施形態に係る非一時的なコンピュータ読み取り可能な記録媒体は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、および前記ポインタおよびエポックベースのメモリ収集技法を基づき、同時性データ構造のメモリ収集を実行する段階を実行するための1つ以上のプログラムを記録してよい。
【発明の効果】
【0008】
多様な実施形態は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合したポインタおよびエポックベースのメモリ収集技法を利用することにより、メモリ使用量が少なく、迅速であり、多くのデータ構造に適用可能であり、メモリを漏れなく収集することができる。
【図面の簡単な説明】
【0009】
【
図1】安全なメモリ収集方式がない、Treiberのスタックでのシナリオを示した図である。
【
図2】安全ではない収集を有する、Treiberのスタックを示した図である。
【
図3】エポックコンセンサスの例を示した図である。
【
図4】ハザードエポックコンセンサスの例を示した図である。
【
図5】多様な実施形態における、保護されるTreiberのスタックを示した図である。
【
図6】多様な実施形態における、コンピュータシステムを示した図である。
【
図7】多様な実施形態における、コンピュータシステムによる方法を示した図である。
【発明を実施するための形態】
【0010】
以下、本文書の多様な実施形態について、添付の図面を参照しながら説明する。
【0011】
1.概要
キュー(queues)、B-ツリー(trees)、ハッシュテーブル(hash tables)、ワークスティール(work stealing)デック(deques)、ラデックス(radix)ツリー、およびトライ(tries)を含んだすべてのポインタベースの同時性データ構造は、安全なメモリ収集問題を処理しなければならない。メモリブロックを収集する前に、スレッドが以後に参照解除されるブロックとしてローカルポインタを固定してはならない。したがって、一般的には、データ構造から分離したメモリブロックを即時に収集してはならない。
【0012】
例えば、Treiberのスタックを考えてみよう。このリストは基本的に、ヘッドがスタック上端である要素の、リンクするリストである。
図1のように、スレッドは、(i)ヘッドから最初のブロック(カー(cur)と称する)を横切り、(ii)カーから2番目のブロック(ネクスト(next)と称する)を横切り、(iii)ヘッド上のカーでCAS(compare-and-swap)を実行してカーを分離する。(iv)カーが即時に収集されればどうなるのか?他のスレッドは、ポップ作業の途中にカーおよび参照解除カーの次のポインタのためのローカルポインタを持つようになり、したがって、use-after-free状態が発生するようになる。このようなエラーを防ぐために、スレッドは、他のすべてのスレッドが参照を終えるまでカーの収集を延期しなければならない。メモリ収集を延期する場合には、一般的には、安全なメモリ収集を計画したりメモリブロックを収集したりするために安全な時期を感知するライブラリまたはランタイムシステムによって処理される多数のスレッドの重大な協力が必要となる。このような方式により、データ構造の作成者はその運営に集中することができ、(大部分の)安全メモリ収集の義務を基本方式に任せることができる。
【0013】
従来には、互いに異なる折衷の多様な収集方式が提案されてきた。しかしながら、不幸にも、従来の方式はすべて、次のような願うべき属性を満たすことができなかった。堅固性:非協調的なスレッドは、他のスレッドが無限に多くのブロックを収集することを妨害しない。迅速性:共有メモリに対する各参照に対する高い同期化のために相当な時間オーバヘッドが発生しない。コンパクト:各ブロックのメタデータなどによって相当な空間オーバヘッドが発生しない。自己充足:特殊なハードウェア/OSの支援に依存しなくても実行環境(例:割り込みハンドラの設置)に影響を与えない。広範囲な適用可能:大きな制約なく多様なデータ構造を支援する。
【0014】
トレーシング(tracing)カベージコレクション(gabage collector:GC)は、トレーシングが高くて予測不可な時間(待機時間)と空間(メモリ使用)オーバヘッドを誘発するため、速くもなく小さくもない。特に、メモリが大きいとか、業務量によってリソースが足りないとか、GCランタイム自体を実現しなければならない場合に問題が生じる。さらに、GCが堅固になろうとすれば、対象言語はJava(登録商標)やHaskellのように形式的に安全ではなければならない。
【0015】
ハザードポインタ(hazard pointer:HP)およびパス・ザ・バック(pass-the-buck)のようなポインタベースの収集方式(pointer-based reclamation schemes:PBR)は、共有メモリに対する各参照がリードアフターライト(read-after-write:RAW)の同期化を必要とするため迅速性がない。すなわち、以前の書き取りの後に読み取りを注文するために高いフェンスを挿入しなければならない。Drop-the-anchorは、PBRの同期化の費用を大きく節減できるが、現在はリストにしか適用することができない。さらに、PBRは、HarrisのリストとHarris-Herlihy-Shavitのリストを支援しないという点において広範囲の適用が不可能である。非協調的な(non-cooperative)スレッドがエポックの発展(論理タイムスタンプ)を遮断し、これによって大部分のブロックの再生を防ぐことができるため、エポックベースの収集方式(epoch-based reclamation schemes:EBR)は堅固でない。
【0016】
迅速で堅固に収集するために、HPとEBRの混合が提案された。Hazard Erasとインターバルベースの収集(interval-based reclamation:IBR)は、HPのアイディアを採択して非協調的なスレッドの効果を制限するEBRの変形であるが、ブロックあたりのランタイムメタデータによりコンパクト性がない。QSenseはHPとEBRの混合であり、作業量に応じて互いに切り替わるが、OSスケジューリングの時間的な制御に依存するため自己充足でない。
【0017】
本開示ではPEBRを提示するが、PEBRとは、上述したすべての属性を満たすことのできる、安全なメモリ収集の最初の方案である。PEBRは、SnowflakeのHPとEBRの混合デザインからヒントを得たものであり、その大部分が堅固であり(HPのように)、迅速である(EBRのように)。Snowflakeは、ブロックあたりの空間オーバヘッドが発生しないという点においてコンパクトである。しかしながら、Snowflakeは、デザインがGCと緊密に結合しているという点において自己充足でない。そもそも、Snowflakeの主な動機は、NET CoreのGCランタイムに手動のメモリ収集を選択的に提供することにある。さらに、Snowflakeは、GCとの安全な相互作用によって要求される制限されたプログラミングAPIのために、大部分のポインタベースの非遮断データ構造には適用されない。決定的には、Snowflakeは、メモリブロックに対するポインタエイリアシング(aliasing)を支援しない。さらに、Snowflakeのイジェクション(ejection)アルゴリズムは、そのイジェクションアルゴリズムがロック装置によって保護されるため、厳格な意味において堅固でない。
【0018】
PEBRもHPとEBRの迅速かつコンパクトな混合であるが、上述したSnowflakeの限界がない。PEBRは、GCに依存しない軽量ランタイムを採用し、標準C/C++同時特性とプロセス全般のメモリフェンスだけを必要とするという点において自己充足型であり、このうちの後者は、Linux(登録商標)とWindows(登録商標)のユーザ空間プログラムに広範囲で利用可能である。PEBRは堅固である。特に、本開示は、非遮断イジェクションアルゴリズムを設計する。最も重要なことは、PEBRがポインタエイリアシング、ポインタタグ指定、およびリード・モディファイ・ライト(read-modify-write:RMW)作業(例:CASおよびフェッチ・アンド・アッド(fetch-and-add))のように同時プログラミングに幅広く使用されるポインタ作業を許容するという点において、PEBRが広範囲に適用されるという点にある。さらに、HarrisとHarris-Herlihy-Shavitのリストなどのような多様な非遮断データ構造によって充足されるPEBRの安全な収集要件も特性化する。
【0019】
本開示は、Rustで作成されたEBR実現であるCrossbeam上にPEBRを実現した。本開示の実現は公開的に可能である。PEBRが迅速かつ堅固であるかを実験的に評価するために、本開示は、Harris、Harris-Michael、Harris-Herlihy-Shavit、Michaelのハッシュマップ、Natarajan-Mittalツリーのような多様のデータ構造マイクロベンチマークを使用しながら、性能をEBRおよびNRと比較する実験を行った。この実験において、PEBRは、EBR(処理量の減少が15%未満に減少)とは比べものにならない程に迅速であったし、堅固であった(敵対環境でも成功的にメモリを収集した)。
【0020】
本開示の残りの部分では、PEBRについて詳しく説明して評価する。先ず、PBR、EBR、Snowflakeのような、PEBRの設計にヒントを与えた従来の収集方式を検討し、PEBRの要求事項を提示し、一部の要求事項を自動で保障する高水準のAPIを提示し、非遮断イジェクションアルゴリズムを含んだPEBRのアルゴリズムを説明しながら、PEBRの属性を論議する。
【0021】
2.従来の収集方式
Treiberスタックを実行の例題(2.1)としながら、従来の方式がuse-after-freeエラーを防ぐ方法について説明し、その短所(2.2~2.4)について論議する。
【0022】
2.1.例題:Treiberスタック
図2は、非安全回復をしたTreiberスタックを示している。Treiberスタックは基本的に、スタックのトップであるヘッドが一要素のリンクされたリストであるということについては上で説明した。(ライン1またはL1)構造ノード<T>は、データと次のポインタで構成された、リンクされたリーストノードを示す。(L2-3)スタック<T>は基本的に、ノードに対する原子ポインタであって、初期にはnullptrである。(L4-10)プッシュ方法は、現在のヘッドを次のポインタとして示す新たなノードを生成し、現在のヘッドで新たなノードへのCASを実行する。こうすることにより、参照のためのメモリ共有のためにポインタthis->headのローカルコピーカーを生成する。(L11-22)この反面、pop方法は、現在のヘッドをロードしてローカルポインタカーを制し、nullptrでない場合には次のポインタを読み取り、現在のノードから次のノードにヘッドによってCASを実行する。(L9、20)プッシュ方法およびポップ方法すべて、CASが成功するまでやり直す。
【0023】
上述したように、pop(L18)では、(L16)また他のスレッドが同時にカー->ネクストを読み取ってuse-after-freeエラーを誘発することがあるため、カーを分離した後すぐに収集することは安全でない。このセクションの残りの部分では、収集方法として、ローカルポインタ参照を保護することでこのようなエラーを防ぐ方法について説明する。
【0024】
2.2.ハザード(hazard)ポインタ
先ず、初期および最も基本的なPBR方式の1つである、ハザードポインタ(HP)方式について説明する。
【0025】
API:HPは次のような関数を提供する。
【0026】
・protect(l):共有メモリに指定されたローカルポインタ(l)を保護。保護されたローカルポインタだけが参照解除されなければならない。呼び出しスレッドの保護されたポインタリスト(または、「ハザードポインタ」リスト)にlを追加する。保護後、ユーザはlを読み取る共有位置にlが依然として含まれているかを検証しなければならない。
【0027】
・unprotect(l):保護されたポインタリストからlを取り除いてlの保護を解除する。
【0028】
・retire(l):参照lの収集要請。ユーザは、ポインタが連結されなかったか(アンリンク)、すなわち、ポインタを廃棄する前に共有メモリにこれ以上存在しないかを確認しなければならない。アンリンクの正確な定義については3.3を参照する。呼び出しスレッドのスレッドローカル収集リストにlを追加する。
【0029】
・collect():スレッドによってこれ以上保護されない、すなわち、再生リストのポインタがスレッドの保護されたポインタリストにない廃棄されたブロックを収集。ユーザが呼び出すかランタイム自体で呼び出すことで堅固性を保障することができる。
【0030】
図2に提示したTreiberスタックは、次のように変更される。
【0031】
・L16の前にprotect(cur);if(this->head.load()!=cur)continue;を挿入する。
【0032】
・L16の後にunprotect(cur)を挿入する。
【0033】
・L18ではfree(cur)をretire(cur)に替える。
【0034】
利点:API要件は保護され、事前に検証される場合に限って該当のカーが(L16)逆参照され、(L17、18)カーは廃棄される前に共有メモリから分離する。
【0035】
例えば、protect、retire、およびcollect間の同期化により、カーのuse-after-freeを防ぐ。第一に、protect(cur)は次のように進行する。
【0036】
P1.スレッドの保護されたポインタリストにカーが追加される。
【0037】
P2.ヘッド->ネクストが、APIが要求するカーを依然として含んでいるかを確認する。
【0038】
第二に、廃棄後には、カーは次のように収集する。
【0039】
C1.retire(cur)で要求するとおりに、カーが共有メモリにこれ以上存在しないと仮定する。
【0040】
C2.すべてのスレッドの保護されたポインタリストを読み取る。
【0041】
C3.どんなスレッドであっても、保護されない場合はカーを収集する。
【0042】
実行順によっては、P1がC2よりも先に発生するか、C1がP2よりも先に発生する。前者の場合は、カーは保護されるものと掲示され、C3で収集されない。後者の場合は、カーは共有メモリにこれ以上存在しないため、P2の検証に失敗する。いずれの場合であっても、カーに対してuse-after-freeは絶対に発生しない。
【0043】
短所:直観的ではあるが、HPは高い同期化のため迅速性がない。上述した事例分析に異常がなければ、RAW-同期化フェンスを発行し、P1の書き取り(およびC1)とP2の読み取り(およびC2、それぞれ)の順序を強制しなければならない。特に、各ポインタ保護にしたがい、ポインタ逆参照に対してフェンスが発行されなければならない。さらに、HPは、本開示で論議したように、個別ポインタを保護する能力がHarrisとHarris-HerlihyShavitリストで反復的に支援するのに十分でないという点において、広範囲の適用が不可能である(詳しい内容については3.3を参照)。このような短所は、EBRのような他の収集方式に動機を付与する。
【0044】
2.3.エポックベースの収集
Harrisバージョン、Fraserバージョン、QSBRのようなEBR方式は、一度に複数のローカルポインタを保護して同期化の費用を考慮する。
【0045】
API:EBRは、次のような関数を提供する。
【0046】
・set_active()、set_quiescent():スレッドが共有メモリ(「アクティブ状態」)にアクセスしているかどうか(「非アクティブ状態」):ユーザは、(i)共有メモリがアクティブ状態内だけでアクセスされるかを確認しなければならず、(ii)共有メモリを読み取ることにより、アクティブ状態で生成されたローカルポインタは非アクティブ状態に切り替わらず、同じアクティブ状態だけで逆参照されなければならない。
【0047】
・retire(l):lの参照子収集を要請する。HPと類似の要件をもっている。また、アクティブ状態で呼び出さなければならない。
【0048】
・collect():十分に古いアクティブ状態の廃棄されたブロックを収集する。
【0049】
図2に提示したTreiberのスタックは、次のように変更される。
【0050】
・L6、13の前にset_active();を挿入する。
【0051】
・L9、20の後にset_quiescent();を挿入する。
【0052】
・L18ではfree(cur)をretire(cur)に替える。
【0053】
API要件は、該当のカーが(L7、14)アクティブ状態で再設定され、(L16)同じアクティブ状態で逆参照され、(L17、18)アクティブ状態で廃棄される前に共有メモリから分離する場合に満たされる。
【0054】
利点:(i)活性スレッドがローカルエポックに固定されているスレッド間のエポックコンセンサスの同期化によって事後使用を防ぎ、(ii)同時活性スレッドのローカルエポックは異なることがあるが、極めて多く傾かないように保障し、(iii)十分なエポックで廃棄したポインタだけを収集する。したがって、収集されたブロックは、ここ最近のエポックに固定された活性スレッドにより(逆)参照されることがない。
【0055】
より具体的に、
図3に提示した事例イベントグラフを見てみよう。ここで、ノードはイベントを示し、エッジは発生前の関係を示す。B(e)とE(e)はアクティブ状態の開始と終了を示し、例えば、A(e)はローカルエポックeに固定される。エポックコンセンサスにおいて、スレッドは協力的であり、周期的にグローバルエポックを進展させ、これらのeへの進展はG(e)で表現される。グローバルエポックは、各A(e)に対して(i)G(e)がB(e)よりも先に起こり、(ii)E(e)がG(e+2)よりも先に発生すると保障することにより、ローカルエポックの極めて多くの歪曲を防ぐ。アクティブ状態A(e)では、e-3またはそれ以前に固定されたアクティブ状態で廃棄されたポインタだけを収集する。
【0056】
【0057】
エポックは、RAW同期化が各逆参照するときにだけ発生するのではなく、各アクティブ状態が開始するときにだけ発生するため、同期化費用を大きく節減する。具体的には、HPのP1(2.2)のような方式によってエポックeが保護されているということを掲示するためには、B(e)でRAW同期化が必要となるため、グローバルエポックがe+2に進展しない。
【0058】
短所:EBRは迅速ではあるが、非協調的スレッドがアクティブ状態を脱することができないこともあるという点において堅固でないため、グローバルエポックの進展を遮断するし、新たに廃棄したブロックの収集を防ぐ。本質的に、EBRは、限りなく多くの数のローカルポインタを保護することにより、迅速に堅固性をやり取りする。堅固性が足りないため、長期実行作業の保護(例:オブジェクトキャッシュまたはOLAPワークロード)にEBRを使用することは好ましくない。
【0059】
2.4.Snowflake
Snowflakeは、HPとEBRの混合物である。迅速性があるし、まるで初期のEBRのように動作する。強力であるし、最大メモリ使用量を減らすため、非協調的スレッドをアクティブ状態から非アクティブ状態にイジェクトし、HPのようにそれぞれのローカルポインタを個別に保護する。この後、グローバルエポックを前倒しし、廃棄したブロックを収集して堅固性を保障することができる。
【0060】
API:Snowflakeは、HPとほぼ同じAPIを有しており、特に、ユーザは、エポックコンセンサスに保護されているにもかかわらず、ローカルポインタを廃棄する前にローカルポインタを保護しなければならない。その理由は、エポックコンセンサスがスレッドをイジェクトしてローカルポインタの保護を取り消すことができるし、もしそうなれば、ポインタはHPによって保護されなければならないためである。結果的に、保護要件はHPと類似するが、次のように若干差がある。
【0061】
・アクティブ状態で生成されたローカルポインタは、イジェクトによる非アクティブ状態に切り替えず、同じアクティブ状態だけで保護されなければならない。この要求事項をアクティブ状態で生成されたローカルポインタを同じアクティブ状態で、逆参照しなければならないというEBR要件と比較してみよう。
【0062】
・protect(l)において、保護ポインタリストにlを追加した後、Snowflakeは、スレッドがイジェクトされずに依然としてアクティブ状態であるかを返還する。ユーザは、ポインタがエポックコンセンサスによって実際に保護されるようにするために、protect(l)を廃棄する前にprotect(l)の返還値を検証しなければならない。この要件を、ユーザがlを読み取る共有位置にlが依然として含まれているかを検証するHPと比較してみよう。
【0063】
また、Snowflakeは、イジェクトされるスレッドに再度加入し、エポックコンセンサスのためにset_active()を提供する。Snowflakeはset_quiescent()を提供しないが、APIに関数を追加することは容易であると思われる。
【0064】
図2に提示したTreiberスタックは、次のように変更される。
【0065】
・L16の前にif(!protect(cur)){set_active();
continue;}を挿入する。
【0066】
・L16の後にunprotected(cur);を挿入する。
【0067】
・L18ではfree(cur)をretire(cur)に替える。
【0068】
ユーザがthis->headで再び読む取る代わりにprotected(cur)の返還値を確認して有効性を検証するという点を除けば、HPの変更は同じである。
【0069】
利点:イジェクションがないとき、SnowflakeはEBRのような方法によってuse-after-freeを防ぐ。アクティブ状態の内部で生成されたローカルポインタは、エポックコンセンサスにより、同じアクティブ状態内で(保護および)非参照しても安全である。
【0070】
スレッドがイジェクトされたとしても、(i)保護後の有効性の検査(l)は、アクティブ状態でスレッドの保護ポインタリストにポインタが追加されるように保障し、(ii)Snowflakeのイジェクションアルゴリズムは、アクティブ状態中にリストに追加されたポインタが異なるスレッドに見えるようにし、これらがそれを収集しないようにする。フードの下でスレッドの保護されたポインタはアクティブ状態でのみ追跡され、取り出すときにだけ他のスレッドに掲示される。このアルゴリズムを、protect(l)がポインタを他のスレッドに即時に掲示するHPと比較してみよう。
【0071】
短所:Snowflakeは、Snowflakeの主要な動機、すなわち、NETCore[21]で手動のメモリ収集を選択的に提供するという制約により、大部分の非遮断データ構造への適用が不可能である。より具体的に説明すると、強力な類型安全性に対するNET Coreの要求事項は、次のように非遮断プログラミングと衝突する。
【0072】
先ず、Snowflakeは、固有の所有者条件を要求する。手動で管理されるブロックは、最大で1人の所有者を示さなければならない(各スレッドのローカルポインタは除外)。結果的に、Snowflakeは、同時性データ構造で複数のポインタを別称で指定することを禁止する。この要件は、強力な類型安全性によって動機が付与される。本質的に、この条件では、ブロックがその単一所有者によって放棄されて直ぐに、ブロックはHPのC1(2.2)と類似の廃棄要件を自動で満たす。しかし、最も基本的な非遮断データ構造の1つであるTreiberスタックでも満たすことができず、
図1でCASに成功した後にヘッドとカーの参照子が別称と同時に次を示す。
【0073】
次に、SnowflakeのAPIは、各スレッドのローカルポインタの共有メモリに対する使用に相当な文法制約を付加する。ポインタタギングまたはポインタ定数キャスティング[casting]は支援しない。また、ローカルポインタは、該当のスレッドスタックだけに常在しなければならず、スレッドだけで使用しなければならない。この要件は、さらに強力な類型安全性によって動機が付与される。実際にローカルポインタを制限なく使用すれば、アクティブ状態で寿命が延長し、エポックコンセンサスの仮定が崩れることがある。しかし、(i)ポインタタギングとポインタ定数キャスティングがHarris、Harris-Michael、およびHarris-Michaelのリンクされたリストを含んだ多様なデータ構造で決定的に使用されるという点において極めて制限的である。(iii)暗示的方式の場合、必要なローカルポインタをヒップとして許容しない。(iiii)多重処理非動機作業の実行者に必要な他のスレッドによるローカルポインタの使用を許容しない。
【0074】
さらに、Snowflakeのイジェクションアルゴリズムは、ロック装置とページ欠陷を使用するという点において実際に強力ではあるが、自己充足もしない。イジェクションは次のように実行される。スレッドAがスレッドBをイジェクトするとき、(i)AがBの保護されたローカルポインタを列挙して掲示し、Bの保護されたポインタリストの権限を読み取り専用に変更し、BがBの「イジェクションロック」を止めてイジェクトされることを表示する。(ii)Bは、新たな保護ローカルポインタを追跡するときにページ欠陥の例外によってイジェクトされることを見抜き、(iiii)ページ欠陥ハンドラにおいて、Bはイジェクションロック装置を止めてイジェクションから復旧する。このアルゴリズムは、非協調的スレッドBが、スレッドAがBのイジェクションロック装置を止めた後、にロックするときに排出されないこともあるため堅固でない。また、このアルゴリズムは、ユーザ定義ページエラーハンドラを設置するため独立的でない。
【0075】
3.要件
以下では、先ず、Treiberのスタックを例示(3.1)で使用したPEBRのAPIを紹介し、ユーザが満たさなければならないローカルポインタと廃棄に対する要件を提示し(3.2と3.3)それぞれの適用性について論議する(3.4)。
【0076】
3.1.API
(1)PEBRのAPIは、HPとEBRのAPIを混合してset_active()、protect(l)、unprotect(l)、retire(l)、collect()を提供するが、エポックコンセンサスから脱して自発的に選択するset_quiescent()も提供する。ユーザがアクティブ状態をより短く維持することができるし、エポックの進展とブロック収集をあまり妨害しないため性能が優れる。自発的に取り出したものであるか非自発的に取り出したものであるかに関係なく、スレッドは、保護されるローカルポインタを廃棄しても安全であり、したがって、多様な待機状態にわたって存在する、持続的なポインタを支援する。
図2に提示したTreiberスタックは次のように変更される。
【0077】
(1)L6、L13の前にset_active();を挿入する。
【0078】
(2)L9、L20の後にset_quiescent();を挿入する。
【0079】
(3)L16の前にif(!protect(cur)){set_active();continue;}を挿入する。
【0080】
(4)L16の後にunprotected(cur);を挿入する。
【0081】
(5)L18ではfree(cur)をretire(cur)に替える。
【0082】
その変化は、EBR(1、2、5)のそれとSnowflake(3、4、5)の混合物であるということに注目する必要がある。
【0083】
set_active()とset_quiescent()によってアクティブ状態の寿命を追跡すると同時に、エポックコンセンサスに対するより正確な制御をユーザに提供すると同時に、APIに不可解な複雑性を追加する。複雑性を緩和するために、PEBRは高い水準のAPI(4.1)を提供する。また、ユーザは、スレッドをイジェクトしない限り常にアクティブ状態を維持するように要求することにより複雑性を完全に除去することができ、明示上、アクティブ状態の寿命を追跡しなければならない負担から逃れることができる。
【0084】
制限された数の保護されたローカルポインタスロットだけを支援する大部分のHPの実現とは異なり、PEBRの実現は、固定の長さのスロット配列のリンクされたリストを使用することで、静的に知られていない数のスロットを支援する。これは、Bonsaiツリーのような支援のために必須である。
【0085】
2.4において、Snowflakeがローカルポインタの使用とポインタのエイリアシングに対して極めて厳格な要件を付加して非遮断データ構造に対する適用可能性を制限するという点を念頭に置かなければならない。この反面、PEBRは、次のように安全な収集のためにより緩和された要件を求める。
【0086】
3.2.ローカルポインタの要件
Snowlakeとは異なり、PEBRは、ローカルポインタを自由にタグ指定するか、定数にキャスティングするか、ヒップに記録するか、他のスレッドに使用できるように許容しながら、次の要件を満たす。
【0087】
要件3.1(保護)スレッドが共有メモリを読み取ることにより、lというローカルポインタを生成すると仮定しよう。これにより、(i)以後にスレッドだけを保護することができ、(ii)set_active()はこれらの間で呼び出しがなされない。
【0088】
保護(l)が真(true)に返還される場合、その次には保護時点にスレッドがアクティブ状態にあり、さらに要件3.1が維持される場合、同じアクティブ状態で生成されなければならないという点を念頭に置かなければならない。要件3.1は、RAII類型(4.1と4.2)に基づく高い水準のAPIによって静的に保障される。
【0089】
HPとSnowflakeと同じにように、PEBRは、すべての逆参照が以前に成功的に保護されならなければならないと要求する。
【0090】
要件3.2(逆参照)ローカルポインタlを参照するスレッドを仮定してみよう。これにより、protect(l)がより迅速に呼び出され、真に返還され、protect(l)がunprotect(l)となり、lの保護と逆参照との間に呼び出しがなされない。
【0091】
要件3.2は、より高い水準のAPI(4.1と4.3)によって静的に保障されるであろう。要件3.1と3.2は、ローカルポインタがアクティブ状態で生成されて保護される場合に限り、ローカルポインタが参照解除されるということを意味する。
【0092】
protect(l)が偽を返還したとしても、set_active()を呼び出して該当のスレッドが新たなアクティブ状態に入りながら残りの作業を再開できるという点に留意する必要がある。要件3.1は既存のローカルポインタの保護を禁止するが、要件3.2はスレッドが残りの作業を実行することのできる新たなローカルポインタを生成するため、既に保護されたローカルポインタの廃棄を許容する。
【0093】
3.3.廃棄に関する要件
2.4でSnowflakeの固有の廃棄条件が自動で廃棄要件を満たすが、適用可能性も大きく制限するという点を念頭に置かなければならない。一方、PEBRは、複数のポインタを別称にできるように許容し、その代りに広範囲に適用される次の2つの廃棄要件を付加する。
【0094】
最初の要件は、廃棄前の共有メモリでブロックを連結解除しなければならないというHP/EBR要件と類似する。
【0095】
要件3.3(廃棄)bをブロックとしよう。その後、bは最大で1回廃棄される。さらに、bが廃棄される前に共有メモリで連結しない。または、より具体的に、廃棄イベントR(b)と位置にbのポインタ値を使用するすべてのイベントの場合、例えば、lは次のように維持される。
【0096】
(i)wはR(b)よりも先に発生し、
(ii)wがR(b)に見える場合、R(b)の前に現れるblk(l)があり、ここで、wはR(b)以後とR(b)以前に発生するlに対する書き取りイベントがない場合R(b)に表示され、blk(l)はl位置を含むブロックである。
【0097】
簡単に説明すれば、(i)廃棄したブロックに対するポインタを共有メモリに再び使用してはならないという意味と、(ii)廃棄したブロックを示すすべてのブロックも共有メモリで集団的に連結されないように廃棄しなければならないということを意味する。これは、2で説明した、retire(l)に必要な連結解除およびポインタの存在に対する正確な定義である。HPとEBRにも同じ要件が適用される。しかし、要件3.3は、Harrisのリストの次の例のように、(HPおよび)PEBRに対する安全な収集を保障するのに十分でない。
【0098】
【0099】
スレッドAが論理的に削除された2つのノードを1つのCASによって連続的に分離および収集しており、スレッドBが、現在、1番目のノードを通過および保護していると仮定しよう。要件3.3だけでは現在保護されておらず、収集の対象であるため、2番目のノードに対するuse-after-free使用を防ぐことができないと同時に、1番目のノードでBが横切る最中には逆参照ができる。このような理由により、HPは、本開示で論議したように、HarrisおよびHarris-Herlihy-Shavitのリストと根本的に互換されない。このようなエラーを防ぐために、PEBRは、2番目の廃棄要件を付加する。本質的に廃棄したブロック(例:1番目のノード)を通過させ、新たなアクティブ状態で新たなローカルポインタを生成してはならない。
【0100】
要件3.4(廃棄ブロック保護)bをブロックとし、R(b)をその廃棄イベントとし、P(b)をbの保護イベントとし、aをアクティブ状態にする。R(b)およびP(b)がaよりも先に発生すると仮定し、a内部ではbが逆参照されて新たなローカルポインタlを生成すると仮定し、以後にlは保護されない。
【0101】
PEBRによって保護されるとき、Harrisのリストによって満たされる。(i)廃棄する前に、ノードは論理的に削除されたものと表示される。すなわち、「ネクスト」ポインタはタグが指定され、(ii)論理的に削除されたブロックは以後に通過されないためである。Useafter-freeは実際に防ぐことが可能となる。例えば、2番目のノードを再確保した場合、スレッドBをイジェクトしなければならないため、要件によって2番目のノードを保護して逆参照することができない。
【0102】
EBRが特別にこのような条件を必要とするのはイジェクションをしないためであるという点に留意する必要がある。これに関し、要件3.4をイジェクションが存在する状況で廃棄したブロックの逆参照に対し、EBRのエポック-画期的保護を提供する条件であると考慮することができる。
【0103】
3.4.適用の可能性
4つの要件は、Treiberのスタックによって満たされる。特に、要件3.3は、(i)L9からL14までの解除/収集同期化によってカー廃棄前のL8、9、17ですべてのカー書き取りが発生するため、(ii)すべてのカー書き取りはカーが廃棄前に重ね書きするため、さらに要件3.4はすべての横断が単一アクティブ状態内にいるため、維持される。同じように、これらは、Harris-MichaelのリストとEBRが支援する他の同時性データ構造によって満たされる。具体的に、EBRで実現されたデータ構造は、共有メモリに対する各逆参照を保護することによってPEBRにポーティングされる。特に、EBRの本来の実現が要件3.3を満たす限り、PEBRのポーティングされた実現は、要件3.3と要件3.4を追加で満たしている。
【0104】
PEBRは、大部分のポインタベースの非遮断データ構造によって満たされない、固有の所有者条件を要求するSnowflakeよりも適用の可能性が高い。特に、PEBRは、暗示的ボクシング[boxing]と非同期的作業実行機でポインタ共有パターンを支援する。PEBRは、HarrisとHarris-Herlihy-Shavitのリストを支援しないHPよりも厳格に適用可能である。さらに、要件3.1~3.4は、HarrisとHarris-Herlihy-Shavitのリストに対して検証された収集方式要件の最初の特性である。
【0105】
4.高い水準のAPI
3に提示した4つの要件は、従来の方式に比べて複雑であり、充足が面倒である。このような困難を緩和するために、本開示は、要件3.1と3.2を静的に検証するPEBRの高い水準のAPIを提示する。具体的に、アクティブ状態(4.1)に該当するRAII類型を使用し、ローカルポインタ(4.2)の寿命を追跡するためにラストの所有圏ベースの類型を活用するのにCrossbeamにしたがい、保護されたローカルポインタ(4.3)に該当するRAII類型を取り入れる。本開示は、高い水準のAPIがどのようにTreiberスタックを例示(4.4)で使用し、要件3.1と3.2を静的に保障するのかについて説明する。
【0106】
【0107】
【0108】
【0109】
Rustに表示された寿命’gは静的方式であり、Shared<’g、T>値が寿命’gよりも長く持続せず、ローカルポインタを複数のスレッドでも多くの変数に共有することができる。寿命’gはGuardを意味し、その結果としてアクティブ状態内でロカールポインタ(i)が生成され、(ii)はイジェクトされていない限り、アクティブ状態内だけで存在する。
【0110】
【0111】
【0112】
【0113】
【0114】
この生成子は、呼び出しスレッドの保護されたポインタリストにスロットを予約する。構成された後、シールドは、(i)該当のスロットにローカルポインタを作成してローカルポインタを保護することができ、与えられたガードが依然としてアクティブ(すなわち、イジェクトされていない)であるかを返還するか、(ii)スロットからポインタを消してポインタの保護を解除するか、(iii)保護されたポインタを逆参照することができる。シールドが破壊されるか他のポインタを保護すれば、既存のポインタは自動で保護されない。
【0115】
シールドは、シールドの消滅子では基本のローカルポインタが保護されないため、存在するシールドは逆参照しても安全である。PEBRではRustの所有ベースのタイプシステムによって静的に検証する。適用可能性のためにシールドを複数回、さらにRustのタイプシステムに「Synched」と表示して複数のスレッドによっても参照できるようにする。ローカルポインタが該当のスレッドスタックになければならならず、スレッドだけで使用されなければならないというSnowflakeの厳格な要求事項と比較してみよう。ただし、保護されたポインタリストスロットは独占的であり、スレッドローカルリソースであるため、本開示は、シールドがRust類型システムの他のスレッドに「コピー可能」でも「送信可能」でもないものと表示する。
【0116】
4.4.すべて合わせる
要件:今まで取り入れた高い水準のAPIは、集合的に要件3.1と3.2を静的に保障する。要件3.1は、アクティブ状態内で生成されたローカルポインタが同じアクティブ状態内だけで保護されなければならないことを意味し、要件3.2は、保護されるローカルポインタだけが逆参照されることを意味する。第一に、要件3.1は、(i)AtomicのAPIで要求するとおりにガードの寿命内にローカルポインタを生成しなければならず、(ii)ShieldのAPIで要求するとおりに同じガードの寿命内にローカルポインタを保護しなければならず、(iii)内部の有効性確認保護はガードがアクティブ状態に該当するということを保障しなければならないためである。第二に、要件3.2は、シールドのAPIで直接維持する。保護されるローカルポインタだけを逆参照することができる。
【0117】
適用可能性:高い水準のAPIは広範囲に適用可能である。例えば、本開示は、TreiberのスタックとHarris、Harris-Michael、Harris-Herlihy-Shavitリストを含み、評価に使用したすべてのマイクロベンチマークを実現するためにAPIを使用した。
【0118】
事例:
図5は、今まで紹介されたAPIを使用してPEBRによって保護されるTreiberスタックを示している。(L6-11、16-24)プッシュおよびポップ作業はGuardによって区分され、(L8、10、17、21)ポインタ読み取り作業はGuardを参照し、(L14)シールドが生成され、(L19)シールドはスレッドの保護されたポインタリストにローカルポインタカーソルを記録して保護しようとし、失敗すれば初めからまたやり直す。(L20、25)保護後のローカルポインタはシールドによって逆参照であり、(L26)ポップアップを試した後には保護されない。(L19)ローカルポインタはアクティブ状態内で保護されなければならないが、(L25)該当のシールドはアクティブ状態の外部で安全に逆参照されるという点に留意する必要がある。
【0119】
5.アルゴリズム
このセクションでは、EBRのエポックコンセンサス(5.1)を一般化するハザード-エポックコンセンサスに焦点を合わせながら、PEBRのアルゴリズムについて説明する。PEBRのアルゴリズムは、Snowflakeからヒントを得たものであり、ハザード-エポックコンセンサス、保護およびイジェクションも採択している。本開示は、Snowflakeでどのデザインが採択されたのか、さらにどれが本開示自身のものであるかについて明らかに説明する。
【0120】
5.1.ハザード-エポックコンセンサス
PEBRのハザード-エポックコンセンサスは、保護されるポインタを考慮するためのEBRのエポックコンセンサスを改善したものである。例えば、
図4に提示したハザード-エポックコンセンサス事件グラフを参照してみよう。EBRと同じように、各A(e)に対し、(i)G(e)はB(e)よりも先に発生し、(ii)E(e)はG(e+2)よりも先に発生するように強制される。HPと同じように、3.2で論議したとおり、それぞれ生成されるものと同じアクティブ状態内で保護される保護ローカルポインタの集合は、他のスレッドが掲示されたポインタの収集を抑制するように追跡して強行される。Snowflakeと同じように、ブロックは、(i)e-3またはその前に固定されたアクティブ状態で廃棄された場合、そして(ii)現在どのスレッドによって保護されているか掲示されない場合、eに固定されたアクティブ状態で収集されてよい。
【0121】
【0122】
5.2.エポックの同期化
ハザード-エポックコンセンサス(consensus)は、各A(e)に対して(i)G(e)がB(e)よりも先に発生し、(ii)E(e)がG(e+2)よりも先に発生すると仮定する。これを施行するために、次のようにアクティブ状態とグローバルエポックを実現して同期化する。
【0123】
Gはグローバルエポックを含む共有変数、Liはi番目のスレッドのローカルエポックを含む共有変数であるとする。A(e)というアクティブ状態を生成しようとすれば、本開示は、(B1)グローバルエポックでe値を読み取り、(B2)ローカルエポックで記録し、(B3)RAW同期化フェンスを発行し、(B4)グローバルエポックが依然としてeなのかを確認し、そうではなければ最初からまたやり直す。スレッドが非同期的に中間にイジェクトされないようにするためには、最後の段階が必要となる。アクティブ状態を破壊するために、本開示は、(E1)ローカルエポックとしてセンチネル値を使用する。グローバルエポックを進展させるために、本開示は、(A1)グローバルエポックのe値を読み取り、(A2)RAR同期化(リード-アフター-リード)フェンスを発行し、(A3)各スレッドのローカルエポックがeであるのかセンチネルであるのかを確認し、(A4)その場合に限ってグローバルエポックはCASによってe+1だけ進展させる。
【0124】
G(e)は、A4が解除/収集同期化によってB1よりも先に発生するため、B(e)よりも先に発生するようになる。この反面、E(e)は、次のような理由によってG(e+2)よりも先に発生する。B4はA1よりもGでより古い値を読み取るため、B3はA2よりも先に発生する。したがって、Liに対するB2の書き取りは、A3の読み取りで見ることができる。この後、A4に進むために、Liに対するE(e)の書き取りまたは以後の書き取りをA3で読み取り、解除/収集同期化によってE(e)がG(e+2)以前に発生する。
【0125】
【0126】
また、ブルームフィルタを使用して保護ポインタリストを大略的に圧縮するSnowflakeにしたがい、リスト上の反復回数を減らす。アクティブ状態(例:E(1))の最後で、該当のスレッドの保護ポインタリストは、ブルームフィルタによって近似値を算出した後、該当のローカルエポックとともに掲示され、グローバルエポックが前進すれば(例:G(3))、すべてのスレッドによって発行されたブルームフィルタを収集し、結合によって単一ブルームフィルタとして併合した後に発行される。グローバルエポックとともに、以後のグローバルブルームフィルタはアクティブ状態(例:E(3))の開始部分で検索され、collectで保護ブロック(例:¬F(b))の収集防止のために使用される。付随的な利点として、各スレッドの保護されたポインタリストの大部分はスレッドローカルになるため、キャッシュ隣接性が改善される(以下の説明のようにイジェクトされる場合に限り、他のスレッドによってアクセスされる)。
【0127】
過度な近似値の推定は、廃棄したブロックの収集を妨害するものであるため安全である。PEBRを厳格に堅固にレンダリングすることはないが、保護ポインタが合計128個あり、そのブルームフィルタがハッシュ8個に128バイトである場合、平均的に非保護引退ブロックの2.55%だけが再確保されないという点において確率的に堅固である。実現時に、128バイトMurmurHash3結果のその大きさのブルームフィルタと各ダブルバイトチャンクをハッシュとして使用する。
【0128】
堅固性のために、本開示は、エポックとブルームフィルタを遮断しない方式によって同期化する。本開示のアイディアは、本開示がCASを実行することができるように、ブルームフィルタとエポックにポインタをシングル(single)-ワード(word)の状態で置く。128バイトのブルームフィルタに対し、ポインタはタギングあたり7バイトを許容し、エポックには3バイト(5エポック以上を区分する必要がないため、廃棄ブロックの場合は3個、エポックskewの場合は2個)、ピンには1バイト(スレッドがアクティブ状態中であるかを確認)だけあれば良いため、状態がワードに適合する。その結果、CASを実施することにより、ローカルおよびグローバルエポックのエポック番号とブルームフィルタを同時に発行することができる。状態ワードは、以下の説明により、イジェクションを有する同期化に決定的に使用されるであろう。
【0129】
5.4.非遮断イジェクション
本開示は、堅固性を保障するために、Snowflakeにしたがって非協調的スレッド(すなわち、無意識的にこれらの活動状態を破壊すること)をイジェクトする。自己充足性がないか(ページ欠陥ハンドラに対する依存性のため)厳密な意味で堅固でない(ロック器の使用により)Snowflakeのイジェクションアルゴリズムとは異なり、PEBRイジェクションアルゴリズムは、次のように非遮断的な方式によってハザード-エポックコンセンサスと同期化するため、自己充足性があって堅固である。
【0130】
イジェクトする(ejecting)スレッドとイジェクトされる(ejected)スレッドは、取り出したスレッドの状態ワードにおいて互いに同期化する。このために、状態ワードの残りのバイトに、本開示は、スレッドがイジェクトされるかどうかを示すフラッグを追加で記録する。Epoch、Pin、およびEjectを状態の該当のタグであるとしよう。イジェクトするスレッド(Aと指称)は、イジェクトされるスレッド(Bと指称)の状態ワードを次のように変更する。
【0131】
A1.Bの状態に対してCASを実行してBのEjectを表示する。
A2.Bの保護されたポインタリストを読み取り、ブルームフィルタによって大略的な値を求める。
A3.近似ブルームフィルタ、任意のエポック、表示されないPin、Ejectで表示されたCASを実行しながら、Bの状態を新たな状態にアップデートする。
【0132】
A1の目的は、Bにイジェクトするという意図で通知することであり、A2とA3の目的は、BがイジェクトされたときにBの保護ポインタが発行されるようにすることである。この過程にはロックがない。特に、Cとする他のスレッドがBを同時にイジェクトすることもでき、CがA1のCASで失敗したとしても、Bがイジェクトされているという事実を認識してA2とA3を実行することにより、AがBをイジェクトすることを助ける。
【0133】
イジェクトされるときはスレッドBにイジェクション通知をし、次のように保護、廃棄、および収集作業において品位をもってこれを処理する。
【0134】
保護と同期化:関数保護が指定されたローカルポインタを保護されたポインタリストに追加した後、スレッドが排出されない場合、有効性を3.2から想起しなければならない。具体的な検証は、次のように状態ワードと相互作用する。
【0135】
B1.ローカルポインタを保護されたポインタリストに書き込む。
B2.その状態ワードを読み取る。
B3.Ejectバイトが表示されればスレッドがイジェクトされるため、保護作業は失敗する。
【0136】
イジェクションは、次のような状態ワードによって保護されて同期化される。イジェクトするスレッドをAとし、ローカルポインタを保護しようとするイジェクトされるスレッドをBとする。執行順序により、A1はB2よりも先に発生するか、B1はA1よりも先に発生する。前者の場合、B2はEjectが表示された状態で状態ワードを読み取らなければならず、B3は指定されたローカルポインタを保護することができない。後者の場合、A2はB1として使用されたローカルポインタを読み取らなければならず、A3はその保護装置をブルームフィルタに掲示しなければならない。両者の場合とも、Bで成功的に保護されるローカルポインタは、Bがイジェクトされるかとは関係なく、常にアクティブ状態の最後にブルームフィルタに掲示される。
【0137】
HPと同じように、上述した事例分析は、本開示がRAW-同期化フェンスを発行してA1の書き取り(およびB1)とA2の読み取り(およびB2の読み取り、それぞれ)の順序を強制するときに限って堅固である。RAW同期化フェンスを発行して同期化費用を減らすために、ホット経路にコンパイラフェンス(二進数で示されない)だけ使用するためにDiceにしたがうが、これは、本開示の場合はBである。コールド経路でプロセス全体メモリフェンス同期化費用をより多く負担する場合はAである。
【0138】
廃棄および収去と同期化:ハザードエポックコンセンサスは、廃棄および収去をアクティブ状態で呼び出さなければならないため、高い水準のAPI(4.2)をGuardに参照する。しかし、Guardに対する参照があったとしても、該当のスレッドがイジェクトされてアクティブ状態でないことがある。この関数は、イジェクトされた場合にも進行するため、次のようにイジェクションと同期化される。これらは先ず、スレッドの状態ワードを読み取り、スレッドのEjectバイトが表示されなければローカルエポックを使用し、そうでなければフルバック(fallback)でグローバルエポックを読み取って使用する。グローバルエポックは、このような関数が単に特定のグローバルエポックに到達(すなわち、一部eの場合、G(e)が以前に発生)したという事実だけを認識すれば良いため、安全な使用が可能である。結果的に、このような関数は、スレッドをイジェクトしても常に成功する。
【0139】
6.属性
PEBRは安全である。要求事項を充足する場合、PEBRのハザード-エポックコンセンサスの安全性を立証する。
【0140】
整理6.1(安全)要件3.1~3.4が満たされれば、PEBRで管理するメモリブロックに対してuse-after-freeエラーが発生しない。
【0141】
証明.bをPEBRによって管理されるメモリブロックにし、そのretirementR(b)がエポック2eに固定されたアクティブ状態内で発生すると仮定する。bの保護がG(e+3)、G(e+4)、・・・・・G(f-1)の観点で公表されるが、G(f)の観点では公表されないと仮定すれば、収集F(b)はf以後に固定されたアクティブ状態内で発生することができる。
【0142】
【0143】
【0144】
また、PEBRの安全性は、苛酷なパラメータ(例:すべての8つのアクティブ状態の他のスレッドイジェクトする)とLLVM AddressSanitizerを使用しながら試す。
【0145】
PEBRは堅固である。非協調的スレッドがイジェクトされてエポック進展とブロック収集を保障する。その結果、本開示の実験(7)で非協調的スレッドが存在したとしても、メモリ使用量は大部分がそのまま維持される。
【0146】
【0147】
PEBRはコンパクトである。グローバルおよびスレッドごとのメタデータだけが必要であり、参照カウンタまたはエポックのような場合は、ブロックあたりの空間オーバヘッドが発生しない。
【0148】
PEBRは自己従属である。標準C18/C++17緩和されたメモリ同時性とプロセス全般のメモリフェンスで効率的に実現され、このうち、後者はLinuxとWindowsのユーザ空間プログラムに幅広く利用可能であり、C/C++で標準化されている。本開示は、LinuxおよびWindowsでPEBRを実現してテストを行った。さらに、インターラプトハンドラを設置するなど、実行環境を妨害して影響を及ぼさない。
【0149】
PEBRは広範囲に適用される。3.4で論議したように、PEBRは、HPよりも、少なくともHarrisのリストとHarris-Herlihy-Shavitのリストに対し、さらに少なくともEBRのように適用可能な場合、Snowflakeよりもさらに適用可能である。また、ポインタエイリアシング、ポインタタグ指定、RMW演算などのような同時プログラミングに広く使用されるポインタ演算を許容する。また、静的に未知の数の保護されたポインタを支援し、例えば、Bonsaiツリーに基本的に使用される。
【0150】
図6は、多様な実施形態に係る、コンピュータシステム600を示した図である。
【0151】
図6を参照すると、多様な実施形態に係るコンピュータシステム600は、インタフェースモジュール610、メモリ620、またはプロセッサ630のうちの少なくとも1つを含んでよい。一実施形態において、コンピュータシステム600の構成要素のうちの少なくともいずれか1つが省略されてもよく、少なくとも1つの他の構成要素が追加されてもよい。一実施形態において、コンピュータシステム600の構成要素のうちの少なくともいずれか2つが、1つの統合された回路で実現されてよい。
【0152】
インタフェースモジュール610は、コンピュータシステム600のためのインタフェースを提供してよい。一実施形態によると、インタフェースモジュール610は通信モジュールを含み、通信モジュールは外部装置との通信を実行してよい。通信モジュールは、コンピュータシステム600と外部装置との通信チャネルを樹立し、通信チャネルを介して外部装置との通信を実行してよい。通信モジュールは、有線通信モジュールまたは無線通信モジュールのうちの少なくとも1つを含んでよい。有線通信モジュールは外部装置と有線で接続され、有線で通信してよい。無線通信モジュールは、近距離通信モジュールまたは遠距離通信モジュールのうちの少なくともいずれか1つを含んでよい。近距離通信モジュールは、外部装置と近距離通信方式によって通信してよい。遠距離通信モジュールは、外部装置と遠距離通信方式によって通信してよい。ここで、遠距離通信モジュールは、無線ネットワークを介して外部装置と通信してよい。他の実施形態によると、インタフェースモジュール610は、入力モジュールまたは出力モジュールのうちの少なくとも1つを含んでよい。入力モジュールは、コンピュータシステム600の少なくとも1つの構成要素に使用される信号を入力してよい。入力モジュールは、ユーザがコンピュータシステム600に直接的に信号を入力するように構成される入力装置、周辺環境を感知して信号を発生するように構成されるセンサ装置、または映像を撮影して画像データを生成するように構成されるカメラモジュールのうちの少なくともいずれか1つを含んでよい。出力モジュールは、情報を視覚的に表示するための表示モジュール、または情報をオーディオ信号で出力するためのオーディオモジュールのうちの少なくとも1つを含んでよい。
【0153】
メモリ620は、コンピュータシステム600の少なくとも1つの構成要素によって使用される多様なデータを記録してよい。例えば、メモリ620は、揮発性メモリまたは不揮発性メモリのうちの少なくともいずれか1つを含んでよい。データは、少なくとも1つのプログラム、およびこれと関連する入力データまたは出力データを含んでよい。プログラムは、メモリ620に少なくとも1つの命令を含むソフトウェアとして記録されてよい。
【0154】
プロセッサ630は、メモリ620のプログラムを実行し、コンピュータシステム600の少なくとも1つの構成要素を制御してよい。これにより、プロセッサ630は、データ処理または演算を実行してよい。このとき、プロセッサ630は、メモリ620に記録された命令を実行してよい。
【0155】
プロセッサ630は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現してよい。このとき、プロセッサ630は、ポインタベースのメモリ収集技法の関数とポインタベースのメモリ収集技法の関数とともに、エポックベースのメモリ収集技法の関数を混合し、これにより、ポインタおよびエポックベースのメモリ収集技法を実現してよい。また、プロセッサ630は、上述した要件3.1および3.2を満たすように、ポインタおよびエポックベースメモリ収集技法を実現してよい。また、プロセッサ630は、イジェクションアルゴリズムに基づき、ポインタおよびエポックベースのメモリ収集技法を実現してよい。これにより、プロセッサ630は、ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行してよい。
【0156】
図7は、多様な実施形態における、コンピュータシステム600の方法を示した図である。
【0157】
図7を参照すると、コンピュータシステム600は、710段階で、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現してよい。プロセッサ630は、ポインタベースのメモリ収集技法の関数とポインタベースのメモリ収集技法の関数とともに、エポックベースのメモリ収集技法の関数を混合し、これにより、ポインタおよびエポックベースのメモリ収集技法が実現されてよい。
【0158】
ポインタベースのメモリ収集技法の関数は、共有メモリに指定されたローカルポインタ(I)がスレッドによって保護されるように、保護されたポインタリストにローカルポインタ(I)を追加するためのprotect(I)、保護されたポインタリストにあるローカルポインタ(I)を取り除くためのunprotect(I)、保護されたポインタにあるローカルポインタ(I)に対する収集のためのretire(I)、または保護されたポインタリストにないローカルポインタに対する収集のためのcollect()のうちの少なくとも1つを含んでよい。エポックベースのメモリ収集技法の関数は、スレッドがアクティブ状態で共有メモリにアクセスするように設定するためのset_active()、スレッドが非アクティブ状態で共有メモリにアクセスしないように設定するためのset_quiescent()、アクティブ状態にあるスレッドに対して生成されたローカルポインタ(I)に対する収集のためのretire(I)、またはアクティブ状態にあるスレッドに対して廃棄されたロカールポインタに対する収集のためのcollect()のうちの少なくとも1つを含んでよい。これにより、ポインタおよびエポックベースのメモリ収集技法は、set_active()、set_quiescent()、protect(I)、unprotect(I)、retire(I)、またはcollect()のうちの少なくとも2つで実現されてよい。
【0159】
プロセッサ630は、上述した要件3.1および3.2を満たすように、ポインタおよびエポックベースのメモリ収集技法を実現してよい。要件3.1は、protect(l)が真(true)であるときに、スレッドがアクティブ状態で共有メモリを読み取ることにより、ローカルポインタ(I)が同じアクティブ状態で生成される保護要件を示してよい。要件3.2は、ポインタおよびエポックベースのメモリ収集技法は、protect(l)が真であるときに、unprotect(l)は、生成されたローカルポインタ(l)の保護と逆参照との間に呼び出されない逆参照要件を示してよい。
【0160】
プロセッサ630は、イジェクションアルゴリズムに基づき、ポインタおよびエポックベースのメモリ収集技法を実現してよい。プロセッサ630は、イジェクトするスレッドとイジェクトされるスレッドを、イジェクトされるスレッドの状態ワードで互いに同期化してよい。また、このイジェクトするスレッドがイジェクトされるスレッドの状態ワードを変更するように構成されてよい。具体的に、プロセッサ630は、イジェクトされるスレッドの状態に基づき、状態ワードの残りのバイトにイジェクトされるスレッドがイジェクトされることを示すフラッグを表示してよい。この後、プロセッサ630は、イジェクトされるスレッドの保護されたポインタリストに基づき、イジェクトされるスレッドの状態をアップデートするように構成されてよい。
【0161】
これにより、コンピュータシステム600は、720段階で、ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行してよい。コンピュータシステム600は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合したポインタおよびエポックベースのメモリ収集技法を利用することにより、メモリ使用量が少なく、迅速であり、多くのデータ構造に適用可能であり、メモリを漏れなく収集することができる。ポインタおよびエポックベースのメモリ収集技法を適用することにより、システムおよび高性能ソフトウェアメモリ使用量を減らし、遅延速度(latency)を低め、処理率(throughput)を高めるという最適化を実行することができる。
【0162】
ポインタおよびエポックベースのメモリ収集技法は、同時性データを必要とする大部分のシステムソフトウェアおよび高性能ソフトウェアに適用されてよい。たとえば、オペレーティングシステム内で多数のスレッドが頻繁に同時にアクセスするデータ構造、例えば、ページテーブル、スケジューリングテーブル、b-treeなどに適用可能であり、データベース管理システムでは、タイプスタンプ生成器、同時性コントロール、ハッシュテーブルなどに適用可能であり、ネットワーキングシーステムでは、DNSテーブル、パッケージオフローディングなどに適用可能である。すべてのシステムおよび高性能ソフトウェアは、コーナーケースでも適切に動作しなければならないため、収集技法として必要とする特質をすべて備えたポインタおよびエポックベースのメモリ収集技法を緊要に使用することができるであろう。これにより、ポインタおよびエポックベースのメモリ収集技法をシステムおよび高性能ソフトウェアに適用すれば、高い性能が得られることを期待する。したがって、巨大なクラウドを運用する企業の場合は、莫大な費用節減を達成できることを期待する。
【0163】
多様な実施形態に係るコンピュータシステム600の方法は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースのメモリ収集技法を実現する段階、およびポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行する段階を含んでよい。
【0164】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法を実現する段階は、ポインタベースのメモリ収集技法の関数を利用してポインタおよびエポックベースのメモリ収集技法を実現してよい。
【0165】
多様な実施形態によると、ポインタベースのメモリ収集技法の関数は、共有メモリに指定されたローカルポインタ(I)がスレッドによって保護されるように、保護されたポインタリストにローカルポインタ(I)を追加するためのprotect(I)、保護されたポインタリストにあるローカルポインタ(I)を取り除くためのunprotect(I)、保護されたポインタにあるローカルポインタ(I)に対する収集のためのretire(I)、または保護されたポインタリストにないローカルポインタに対する収集のためのcollect()のうちの少なくとも1つを含んでよい。
【0166】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法を実現する段階は、ポインタベースのメモリ収集技法の関数とともに、エポックベースメモリ収集技法の関数を利用してポインタおよびエポックベースのメモリ収集技法を実現してよい。
【0167】
多様な実施形態によると、エポックベースのメモリ収集技法の関数は、スレッドがアクティブ状態で共有メモリにアクセスするように設定するためのset_active()、スレッドが非アクティブ状態で共有メモリにアクセスしないように設定するためのset_quiescent()、アクティブ状態にあるスレッドに対して生成されたローカルポインタ(I)に対する収集のためのretire(I)、またはアクティブ状態にあるスレッドに対して廃棄されたローカルポインタに対する収集のためのcollect()のうちの少なくとも1つを含んでよい。
【0168】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法は、protect(l)が真(true)であるときに、スレッドがアクティブ状態で共有メモリを読み取ることにより、ローカルポインタ(I)が同じアクティブ状態で生成される保護要件を満たしてよい。
【0169】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法は、protect(l)が真であるときに、unprotect(l)は、生成されたローカルポインタ(l)の保護と逆参照との間に呼び出されない逆参照要件を満たしてよい。
【0170】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法を実現する段階は、イジェクトするスレッドとイジェクトされるスレッドを、イジェクトされるスレッドの状態ワードで互いに同期化する段階、およびイジェクトするスレッドがイジェクトされるスレッドの状態ワードを変更する段階を含んでよい。
【0171】
多様な実施形態によると、状態ワードを変更する段階は、イジェクトされるスレドの状態に基づき、状態ワードの残りのバイトにイジェクトされるスレッドがイジェクトされることを示すフラッグを表示する段階、およびイジェクトされるスレッドの保護されたポインタリストに基づき、イジェクトされるスレッドの状態をアップデートする段階を含んでよい。
【0172】
多様な実施形態に係るコンピュータシステム600は、メモリ620、およびメモリ620に接続され、メモリ620に記録された少なくとも1つの命令を実行するように構成されたプロセッサ630を含んでよい。
【0173】
多様な実施形態によると、プロセッサ630は、ポインタベースのメモリ収集技法とエポックベースのメモリ収集技法を混合してポインタおよびエポックベースメモリ収集技法を実現し、ポインタおよびエポックベースのメモリ収集技法に基づき、同時性データ構造のメモリ収集を実行するように構成されてよい。
【0174】
多様な実施形態によると、プロセッサ630は、ポインタベースのメモリ収集技法の関数を利用してポインタおよびエポックベースのメモリ収集技法を実現してよい。
【0175】
多様な実施形態によると、ポインタベースのメモリ収集技法の関数は、共有メモリに指定されたローカルポインタ(I)がスレッドによって保護されるように、保護されたポインタリストにローカルポインタ(I)を追加するためのprotect(I)、保護されたポインタリストにあるローカルポインタ(I)を取り除くためのunprotect(I)、保護されたポインタにあるローカルポインタ(I)に対する収集のためのretire(I)、または保護されたポインタリストにないローカルポインタに対する収集のためのcollect()のうちの少なくとも1つを含んでよい。
【0176】
多様な実施形態によると、プロセッサ630は、ポインタベースのメモリ収集技法の関数とともに、エポックベースのメモリ収集技法の関数を利用してポインタおよびエポックベースのメモリ収集技法を実現してよい。
【0177】
多様な実施形態によると、エポックベースのメモリ収集技法の関数は、スレッドがアクティブ状態で共有メモリにアクセスするように設定するためのset_active()、スレッドが非アクティブ状態で共有メモリにアクセスしないように設定するためのset_quiescent()、アクティブ状態にあるスレッドに対して生成されたローカルポインタ(I)に対する収集のためのretire(I)、またはアクティブ状態にあるスレッドに対して廃棄されたローカルポインタに対する収集のためのcollect()のうちの少なくとも1つを含んでよい。
【0178】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法は、protect(l)が真(true)であるときに、スレッドがアクティブ状態で共有メモリを読み取ることにより、ローカルポインタ(I)が同じアクティブ状態で生成される保護要件を満たしてよい。
【0179】
多様な実施形態によると、ポインタおよびエポックベースのメモリ収集技法は、protect(l)が真であるときに、unprotect(l)は、生成されたローカルポインタ(l)の保護と逆参照との間に呼び出されない逆参照要件を満たしてよい。
【0180】
多様な実施形態によると、プロセッサ630は、イジェクトするスレッドとイジェクトされるスレッドを、イジェクトされるスレッドの状態ワードで互いに同期化し、イジェクトするスレッドがイジェクトされるスレッドの状態ワードを変更するように構成されてよい。
【0181】
多様な実施形態によると、プロセッサ630は、イジェクトされるスレッドの状態に基づき、状態ワードの残りのバイトにイジェクトされるスレッドがイジェクトされることを示すフラッグを表示し、イジェクトされるスレッドの保護されたポインタリストに基づき、イジェクトされるスレッドの状態をアップデートするように構成されてよい。
【0182】
上述した装置は、ハードウェア構成要素、ソフトウェア構成要素、および/またはハードウェア構成要素とソフトウェア構成要素との組み合わせによって実現されてよい。例えば、実施形態で説明された装置および構成要素は、プロセッサ、コントローラ、ALU(arithmetic logic unit)、デジタル信号プロセッサ、マイクロコンピュータ、FPGA(field programmable gate array)、PLU(programmable logic unit)、マイクロプロセッサ、または命令を実行して応答することができる様々な装置のように、1つ以上の汎用コンピュータまたは特殊目的コンピュータを利用して実現されてよい。処理装置は、オペレーティングシステム(OS)および前記OS上で実行される1つ以上のソフトウェアアプリケーションを実行してよい。また、処理装置は、ソフトウェアの実行に応答し、データにアクセスし、データを格納、操作、処理、および生成してもよい。理解の便宜のために、1つの処理装置が使用されるとして説明される場合もあるが、当業者は、処理装置が複数個の処理要素および/または複数種類の処理要素を含んでもよいことが理解できるであろう。例えば、処理装置は、複数個のプロセッサまたは1つのプロセッサおよび1つのコントローラを含んでよい。また、並列プロセッサのような、他の処理構成も可能である。
【0183】
ソフトウェアは、コンピュータプログラム、コード、命令、またはこれらのうちの1つ以上の組み合わせを含んでもよく、思うままに動作するように処理装置を構成したり、独立的または集合的に処理装置に命令したりしてよい。ソフトウェアおよび/またはデータは、処理装置に基づいて解釈されたり、処理装置に命令またはデータを提供したりするために、いかなる種類の機械、コンポーネント、物理装置、コンピュータ格納媒体または装置に具現化されてよい。ソフトウェアは、ネットワークによって接続されたコンピュータシステム上に分散され、分散された状態で格納されても実行されてもよい。ソフトウェアおよびデータは、1つ以上のコンピュータ読み取り可能な記録媒体に格納されてよい。
【0184】
多様な実施形態に係る方法は、多様なコンピュータ手段によって実行可能なプログラム命令の形態で実現されてコンピュータ読み取り可能な媒体に記録されてよい。このとき、媒体は、コンピュータ実行可能なプログラムを継続して記録するものであっても、実行またはダウンロードのために一時記録するものであってもよい。また、媒体は、単一または複数のハードウェアが結合した形態の多様な格納手段または格納手段であってよく、あるコンピュータシステムに直接接続する媒体に限定されることはなく、ネットワーク上に分散して存在するものであってもよい。媒体の例としては、ハードディスク、フロッピー(登録商標)ディスク、および磁気テープのような磁気媒体、CD-ROMおよびDVDのような光媒体、フロプティカルディスク(floptical disk)のような光磁気媒体、およびROM、RAM、フラッシュメモリなどを含み、プログラム命令語が記録されるように構成されたものであってよい。また、媒体の他の例として、アプリケーションを配布するアプリケーションストアやその他の多様なソフトウェアを供給または配布するサイト、サーバなどで管理する記録媒体または格納媒体が挙げられる。
【0185】
本文書の多様な実施形態およびこれに使用された用語は、本文書に記載された技術を特定の実施形態だけに対して限定するためのものではなく、該当の実施例の多様な変更、均等物、および/または代替物を含むものと理解されなければならない。図面の説明と関連し、類似する構成要素に対しては類似する参照符号を付与した。単数の表現は、文脈上で明らかに異なるように意味していない限り、複数の表現を含んでよい。本文書において、「AまたはB」、「Aおよび/またはBのうちの少なくとも1つ」、「A、B、またはC」、または「A、B、および/またはCのうちの少なくとも1つ」などの表現は、ともに羅列される項目のすべての可能な組み合わせを含んでよい。「第1」、「第2」、「1番目」、または「2番目」などの表現は、該当の構成要素を順序または重要度とは関係なく修飾するものであり、ある構成要素を他の構成要素と区分するために使用されるものに過ぎず、該当の構成要素を限定するためのものではない。ある(例:第1)構成要素が他の(例:第2)構成要素に「(機能的にまたは通信的に)連結されて」いるか「接続されて」いると記載されるときには、前記ある構成要素が前記他の構成要素に直接に連結されているのはもちろん、他の構成要素(例:第3構成要素)を介して連結されている場合も含まれる。
【0186】
本文書で使用される用語「モジュール」は、ハードウェア、ソフトウェア、またはファームウェアで構成されたユニットを含み、例えば、ロジック、論理ブロック、部品、または回路などの用語と互換的に使用されてよい。モジュールは、一体で構成された部品、または1つまたはそれ以上の機能を実行する最小単位またはその一部であってよい。例えば、モジュールは、ASIC(application-specific integrated circuit)で構成されてよい。
【0187】
多様な実施形態によると、記載した構成要素のそれぞれの構成要素(例:モジュールまたはプログラム)は、単数または複数の個体を含んでよい。多様な実施形態によると、上述した該当の構成要素のうちの1つ以上の構成要素または段階が省略されてもよいし、1つ以上の他の構成要素または段階が追加されてもよい。大体的にまたは追加的に、複数の構成要素(例:モジュールまたはプログラム)は、1つの構成要素として統合されてよい。このような場合、統合された構成要素は、複数の構成要素それぞれの構成要素の1つ以上の機能を、統合される前に複数の構成要素のうちの該当の構成要素によって実行されるときと同一または類似するように実行してよい。多様な実施形態によると、モジュール、プログラム、または他の構成要素によって実行される段階は、順次的に、並列的に、反復的に、または発見的に実行されても、段階のうちの1つ以上が他の順序で実行されても、省略されても、または1つ以上の他の段階が追加されてもよい。
【符号の説明】
【0188】
600:コンピュータシステム
610:インタフェースモジュール
620:メモリ
630:プロセッサ