Mercurial > hg > Document > Growi
changeset 2:b6c284fd5ae4
backup 2020-12-16
line wrap: on
line diff
--- a/.md Wed Dec 16 15:04:03 2020 +0900 +++ b/.md Wed Dec 16 15:11:16 2020 +0900 @@ -13,17 +13,40 @@ <div class="clearfix"></div> + +HackMD +==== +http://hackmd.cr.ie.u-ryukyu.ac.jp/ + +[[/611/HackMD]] + +CbC +===== + +$lsx(/CbC/) + +[GearsOS](/Gears) +===== + +$lsx(/Gears) + +[研究室情報](/611) +===== + +$lsx(/611) + +[Agda](/Agda) +===== +$lsx(/Agda) + +[[Software]] +===== +$lsx(/software) + Contents ========= -|All Pages|[/Sandbox]| -| --- | --- | -| $lsx(/) | <div class="alert alert-success"><span style="font-size: x-large;"><i class="icon-check"></i> [Sandboxをチェック](/Sandbox)</span></div> $lsx(/Sandbox)| -Slack -===== - -<a href="https://growi-slackin.weseek.co.jp/"><img src="https://growi-slackin.weseek.co.jp/badge.svg"></a> - -GROWI をより良いものにするために、是非 Slack に参加してください。 -開発に関する議論を行っている他、導入時の質問等も受け付けています。 \ No newline at end of file +|All Pages| +| --- | +| $lsx(/) |
--- a/611.md Wed Dec 16 15:04:03 2020 +0900 +++ b/611.md Wed Dec 16 15:11:16 2020 +0900 @@ -6,3 +6,5 @@ - 琉球大学工学部1号館611(河野研) - 差し入れを送るときは上の宛名に書いておくと便利 +## Contents +$lsx(./) \ No newline at end of file
--- a/611/README.md Wed Dec 16 15:04:03 2020 +0900 +++ b/611/README.md Wed Dec 16 15:11:16 2020 +0900 @@ -14,6 +14,7 @@ ## grep系 ### grep +- だいたいのOSに最初から入っている - 使いこなせるように... ### ag/pt/ripgrep @@ -26,4 +27,12 @@ ### ripgrep - rustで書かれたgrep -- https://github.com/BurntSushi/ripgrep \ No newline at end of file +- https://github.com/BurntSushi/ripgrep + +## シェル + +### zsh +- 特に理由がなければzshを使おう + +### fish +- 最近っぽい \ No newline at end of file
--- a/611/Water.md Wed Dec 16 15:04:03 2020 +0900 +++ b/611/Water.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,2 +1,11 @@ # 水です +- 遅刻魔さんのとこから買っている水 +- 河野研、名嘉村研、國田研で共同で買っている + +## 注文方法 + +- 学科のslackの水チャンネルで他の研究室にお伺いを立てる +- ウォーターサーバーの水のボトルにかかれている電話番号に電話をすれば届く + - 「琉大工学部」と言えば大体通じる +
--- a/611/growi.md Wed Dec 16 15:04:03 2020 +0900 +++ b/611/growi.md Wed Dec 16 15:11:16 2020 +0900 @@ -2,6 +2,11 @@ - Growi(これ)に関する情報 +# かんたんに +- 学科の貸し出しVMで借りたubuntuの上でうごいているよ +- グローバルIPを持っててDNSも設定しているよ +- 動かしているのは[このリポジトリ](https://github.com/weseek/growi-docker-compose)のdocker-composeだよ + # 動いているサーバー - 学科の基幹サーバーの1つ`balvenie`上で貸し出しVMの1つとして動いている - 他には僕らが使っているdalmoreとかがあるタイプ @@ -11,4 +16,18 @@ - global ipを持って元気に配信している - 一応長田先生(+総合情報センター)の許可はとった - 学科のDNSで`growi.cr`と`hackmd.cr`を設定している - - `growi`はAレコードで、`hackmd`はgrowiに対するCNAME \ No newline at end of file + - `growi`はAレコードで、`hackmd`はgrowiに対するCNAME +- どのドメインでアクセスしたかをnginx側で判断して、それぞれのサービスポートにリバースプロキシしてる + +# 使っているもの +- nginx + - aptでいれて動かしている +- docker-compose + - このなかでgrowiのnode.jsやmongo db, hackmdのmariadb, elasticsearchとかが動いている + +# サーバーログイン +- 鍵認証限定にしているので、 [/user/anatofuz]経由で鍵を送ればログインできる + +# growiの更新 +- [growiのdocker-composeのリポジトリ](https://github.com/weseek/growi-docker-compose)自体が更新されない限りは、growiのdocker imageを更新するだけでいい +- 具体的には`update.sh`を実行すると大体勝手にやってくれる \ No newline at end of file
--- a/611/marp.md Wed Dec 16 15:04:03 2020 +0900 +++ b/611/marp.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,10 +5,23 @@ - 日本人が開発している - cliベースのものとvscodeベースのものがある - electronベースのものは旧バージョン +- 詳しい記法は[このあたり](https://marpit.marp.app/markdown)を見る + +# install +- cliベースのものならバイナリが配布されているので、それを取得してPATHを通すのが楽 + - node.jsの環境があれば自前でビルド可能 +- cliベースのもののリリースページ + - https://github.com/marp-team/marp-cli/releases + - macOSのものをdonwloadする # 研究室のスライド - リポジトリ - http://www.cr.ie.u-ryukyu.ac.jp/hg/Members/anatofuz/marp-cr/ - 雑に背景にロゴをあてただけのもの - cssよくわからないので... - - デフォルトテーマを使っている \ No newline at end of file + - デフォルトテーマを使っている + +## 使い方 +- makefileがあるので + - `make`すればだいたい出来る + - pdf出力はまだMakefile書いてない \ No newline at end of file
--- a/611/slideshow.md Wed Dec 16 15:04:03 2020 +0900 +++ b/611/slideshow.md Wed Dec 16 15:11:16 2020 +0900 @@ -11,8 +11,8 @@ slideshow (2.4.1) slideshow-models (2.5.0) slideshow-templates (3.0.0) - $ mkdir -p /.slideshow/templates - $cd /.slideshow/templates (無かったら作る) + $ mkdir -p ~/.slideshow/templates + $cd ~/.slideshow/templates (無かったら作る) $hg clone http://www.cr.ie.u-ryukyu.ac.jp/hg/Members/atton/slideshow-s6cr/ ``` @@ -23,8 +23,8 @@ ```sh $gem install slideshow - $ mkdir -p /.slideshow/templates - $cd /.slideshow/templates (無かったら作る) + $ mkdir -p ~/.slideshow/templates + $cd ~/.slideshow/templates (無かったら作る) $hg clone http://www.cr.ie.u-ryukyu.ac.jp/hg/Members/anatofuz/slideshow-s6cr/ ``` @@ -33,7 +33,7 @@ ## Example ```sh - $cd /example # 適当にディレクトリ作って + $cd ~/example # 適当にディレクトリ作って $vi example.md ```
--- a/Agda.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Agda.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,3 @@ # Agda +Agda は依存型をもつ純粋関数型の言語である。 +定理証明支援器でもある。 \ No newline at end of file
--- a/Agda/debug_build.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Agda/debug_build.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,4 +1,3 @@ -# author("2019-03-14T07:10:48+00:00","game","game") # Agda の Debug Build ## インストール方法 @@ -8,11 +7,8 @@ - brew であらかじめ `cabal-install` と `agda` を入れておいたほうがいい?(cabal に関しては source から build しないとだめかも?) -- clone してきた agda ディレクトリに Makefile があるので make - -``` - % make install-debug CABAL_OPTS='--extra-lib-dirs=/usr/local/opt/icu4c/lib --extra-include-dirs=/usr/local/opt/icu4c/include' -``` +- clone してきた agda ディレクトリに Makefile があるので make + - `% make install-debug CABAL_OPTS='--extra-lib-dirs=/usr/local/opt/icu4c/lib --extra-include-dirs=/usr/local/opt/icu4c/include'` - stdlib もupdate する - `% https://github.com/agda/agda-stdlib.git`
--- a/Agda/tutorial.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Agda/tutorial.md Wed Dec 16 15:11:16 2020 +0900 @@ -31,12 +31,130 @@ - その中でC-c C-, すると引数に何が格納されているのか見ることができる。 - また、C-c C-a するとAuto (proof search)ができ、自動でできるならAgdaが自動的に補完をしてくれる。 +関数を実行したい際にはC-c C-n で実行することができる。 + コマンド群は[ここ](https://agda.wiki.fc2.com/wiki/コマンド一覧)にも記載されている。 +特殊文字などもみんなのagdaに記載されている。 ## 関数定義 +関数定義の際に基本となる記述を記載しておく。 +```agda:func.agda +test2 : (A : Set) → Set +test2 a = a + +-- 引数を増やすこともできる。 +test3 : (A B : Set) → Set +test3 a b = b + +-- ()ではなく{}で方を定義することもできる。その場合{}で定義した部分の変数を隠すことができる。 +test4 : {A B : Set} → A → (A → B) → B +test4 a x = x a + +-- {}で定義した部分を取得することも可能 +test5 : {A B : Set} → A → (A → B) → B +test5 {A} {B} a x = x a + +-- 上記の{}で定義した物を()で書き換えると以下のようになる +test6 : (A B : Set) → A → (A → B) → B +test6 A B a x = x a +-- あまりスマートではないし定義の意味が{}で記述した場合と違う +``` ## data型 +```agda:data.agda +-- 次はdata型とrecord型の説明 +-- 記号などはみんなのagdaにほとんど載っていたり、普通にググっても出る。 -## record型 \ No newline at end of file +data _∨_ (A B : Set) : Set where + front : A → A ∨ B + back : B → A ∨ B +-- 関数名として_∨_を定義しているが、これで中置演算子を定義することができる。 +-- 実際にやっていることは下記に定義している関数と同じ + +data or (A B : Set) : Set where + front : A → or A B + back : B → or A B +``` +data型というのは分岐のことであり、「どちらか一方が必ず動作する。」ということになる。 + +わかり易い例としてBool型の定義がある。 +``` +data Bool : Set where + true : Bool + false : Bool +``` +data型を使用した例としてジャンケンを定義してみる。 +```agda:rps.agda +data hand : Set where + r : hand + p : hand + s : hand + +-- 「手」を二つ受け取って勝った方の手を返すように設計すると +-- 定義は「handを2つ受け取る。最終的にhandを返す」となり、以下のようになる。 +rps : (A B : hand) → hand +-- rps : hand → hand → hand これでも良い +-- rps : (_ _ : hand) → hand これでもできるかもしれない +rps r r = r +rps r p = p +rps r s = r +rps p r = p +rps p p = p +rps p s = s +rps s r = r +rps s p = s +rps s s = s +``` +場合分けの数が足りない場合、agdaが親切に怒ってくれる。 + + +## record型 +data型とは違い、 +オブジェクトあるいは構造体のようなもの。 +以下の関数はAND。p1で前方部分が取得でき、p2で後方部分が取得できる。 + +``` agda:record.agda +record _∧_ (A B : Set) : Set where + field + p1 : A + p2 : B + +-- 普通にANDの後ろの方を取得することもできる +datatest1 : {A B C : Set} → (A ∧ (B → C )) → (B → C) +datatest1 x b = _∧_.p2 x b + + +-- ANDの後ろの方を取得した結果を使用することもできる。 +datatest : {A B C : Set} → B → (A ∧ (B → C )) → C +datatest b x = _∧_.p2 x b +``` + +これらを使用して三段論法を定義することができる。 +定義は「AならばB」かつ「BならばC」なら「AならばC」となる。 +``` +syllogism : {A B C : Set} → ((A → B) ∧ (B → C)) → (A → C) +syllogism x a = _∧_.p2 x (_∧_.p1 x a) +``` + + + + + + + + + + + + + + + + + + + + +
--- a/CbC.md Wed Dec 16 15:04:03 2020 +0900 +++ b/CbC.md Wed Dec 16 15:11:16 2020 +0900 @@ -6,4 +6,8 @@ - GCC - http://www.cr.ie.u-ryukyu.ac.jp/hg/CbC/CbC_gcc/ - LLVM/clang - - http://www.cr.ie.u-ryukyu.ac.jp/hg/CbC/CbC_llvm/ \ No newline at end of file + - http://www.cr.ie.u-ryukyu.ac.jp/hg/CbC/CbC_llvm/ + +## Contents + +$lsx(./) \ No newline at end of file
--- a/CbC/GCC/homebrew.md Wed Dec 16 15:04:03 2020 +0900 +++ b/CbC/GCC/homebrew.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,7 +4,7 @@ それを hoge ユーザでやるとします。 -cbcgcc.rb をみると作り方が書いてある +cbcgcc.rb をみると作り方が書いてあります。 ``` def install @@ -17,10 +17,10 @@ end ``` -ここのconfigure makeを適当に直す。 +ここのconfigure makeを適当に直します。 ``` - brew install hoge/ie/cbcgcc --interactive + brew install ie-developers/ie/cbclang --debug ``` で手元で debug できます。 @@ -32,7 +32,7 @@ brew bottle cbcgcc ``` -とすると sha (hash) 表示されます。これを cbcgcc.rb に書き込みます。 +とすると sha (hash) が表示されます。これを cbcgcc.rb に書き込みます。 ``` bottle do @@ -54,6 +54,28 @@ ``` にコピーします。この時に rebuild 番号を合わせること。動くなら、すでにある物を消しても良いです。 +これをやると、~/Libary/Cache/Homebrew に巨大なdirectoryができるので消すのを忘れないように。 + +ちゃんと動いたら、ie-developper にpullreq します。 + + + +## Catalina + +- `/usr/include`が消えているので`--with-sysroot`でsdkを指定するといい +- Catalinaの場合は`libstd`を作るとコンパイルエラーが発生する + +``` ruby + if MacOS.version >= 10.15 + args << "--disable-libstdcxx " + system "cd #{buildpath};#{buildpath}/contrib/download_prerequisites" + sdk_path = `xcrun --sdk macosx --show-sdk-path` + #sdk_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" + args << "--with-sysroot=#{sdk_path} " + end +``` + +- catalinaのバージョン以降の場合はsdkのパスの指定と、`libsdtd`の作成をスキップする @@ -62,7 +84,3 @@ - - - -
--- a/CbC/LLVM.md Wed Dec 16 15:04:03 2020 +0900 +++ b/CbC/LLVM.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,6 @@ # LLVMを利用してCbCコンパイラを開発した時のメモ -##インストール +## インストール - まずLLVMを取得する。 - [[llvm.org:http://llvm.org]]から純粋なLLVMを取ってくる場合 (この場合clangも) @@ -20,32 +20,6 @@ % cd (↑でつくったとこ) ``` -## 今は古い!! - - configureを実行する。この時、インストール先のディレクトリに移動済みであることを確認すること。 -``` - % (llvmとってきた場所)/configure --prefix=$PWD --disable-optimized --enable-debug-runtime\ - % --enable-debug-symbols --enable-assertions -``` - - 各オプションについて - - --prefix=dir -インストール先のディレクトリ指定 - - --disable-optimized -最適化無効化 - - --enable-debug-symbols -デバッグ情報を含めてコンパイルする。 - - --enable-debug-runtime -実行時に使用するライブラリのデバッグ情報を含めてコンパイルする。 - - --enable-assertions -assertionを有効化する。 - - -- makeする -``` - % make -j -``` -オプションjをつけてうまくいかないときは -jなしで試す。 - -※jは並列にビルドするオプション。速度は上がるがときどき上手くいかないことがある。 ## Cmakeを使う方法 詳しくはcross compilerのとこ @@ -53,8 +27,15 @@ - cmakeする このときにビルドするディレクトリに移動すること. +llvm-project の直下に llvm と clang がある。llvm の下で cmake する。 + ``` - %cmake3 -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/cbclang --sysroot=/usr/arm-linux-gnu/sys-root /src/CbC_llvm + + export CC=/usr/local/llvm/bin/clang + export CXX=/usr/local/llvm/bin/clang++ + export LLVM_DIR=CbC_llvm + export PATH=$PATH:usr/local/llvm/bin + %cmake3 -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/cbclang -DLLVM_ENABLE_PROJECTS=clang;lld" --sysroot=/usr/arm-linux-gnu/sys-root /src/CbC_llvm ``` インストールパスは$PWDで良い @@ -65,8 +46,21 @@ ``` ちなみにubuntuで行う場合はninja-buildでいれないとaptに登録されているninjaが古いという問題がある +## LLVM 10 on macOS -- インストールされたかチェックする。 +元から入っているclangではcompileできないので、brew install llvm で入れたものを使う。 +``` + export CC=/usr/local/llvm/bin/clang + export CXX=/usr/local/llvm/bin/clang++ + cmake ... .../clang +``` +ninja で build すれば良いが MRT.appという macOS のmulware検出システムが暴走してしまう。 +``` + sudo launchctl stop com.apple.MRTd +``` +で止めてから build する。 + +## インストールされたかチェックする。 ``` % (インストールした場所)/Debug+Asserts/bin/clang -v ``` @@ -85,6 +79,8 @@ ``` これで実際に実行されるコマンドと引数が取れるので引数だけコピーする。 +debug buildであれば SEGV した時に再現用のscriptが生成されるので、それを編集して実行して良い。この時に、include の様子をdebugしたければ Original command の方を用いる。 + - gdbを動かす ``` % gdb --args (さっきコピーしたものを貼る) @@ -245,3 +241,41 @@ ``` l main で main が表示されれば Ok 。 + + +# 最近のLLVMのビルド + +- dalmoreでstdlibが古いと文句を付けられる + - cmakeの実行時にrpathとLのオプションビルドしたgcc9に指定する + +``` +$cmake3 -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/llvm -DLLVM_ENABLE_PROJECTS="clang;libgcc;libcxx;libcxxabi" -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,/usr/local/gcc9/lib64 -L$HOME/usr/local/gcc9/lib64" ~/src/LLVM_original/llvm + +``` + +# テクニック + +## helpをもっと表示する + +`../bin/clang --help-hidden |less` + +## 実行フェーズを確認する + + +``` +$ ../bin/clang -ccc-print-phases fact-e.c + +- 0: input, "fact-e.c", c + +- 1: preprocessor, {0}, cpp-output + +- 2: compiler, {1}, ir + +- 3: backend, {2}, assembler ++- 4: assembler, {3}, object +5: linker, {4}, image +``` + +## debug-pass + +``` +../bin/clang -O -mllvm -debug-pass=Arguments fact-e.c +../bin/clang -O -mllvm -debug-pass=Structure fact-e.c +-mllvm -debug-pass=Executions +``` \ No newline at end of file
--- a/CbC/introduction.md Wed Dec 16 15:04:03 2020 +0900 +++ b/CbC/introduction.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,11 @@ -# CbC 入門 \ No newline at end of file +# CbC 入門 + +- ここはContinuation Based Cの入門ページです +- CbCを使ったOSプロジェクト「[[Gears OS>/Gears]]」については別ページに切り分けています + +# 軽量継続 +T.B.D... + +# goto + +T.B.D... \ No newline at end of file
--- a/CbC/onJupyter.md Wed Dec 16 15:04:03 2020 +0900 +++ b/CbC/onJupyter.md Wed Dec 16 15:11:16 2020 +0900 @@ -3,10 +3,13 @@ ## Install docker docker環境が必要です. - hg clone http://www.cr.ie.u-ryukyu.ac.jp/hg/Members/aka/jupyter_CbC_kernel - cd jupyter_CbC_kernel - docker build -t aka/jupyter_cbc_kernel . - docker run -p 8888:8888 --name jupyter_cbc_kernel aka/jupyter_cbc_kernel start-notebook.sh + +``` +$ hg clone http://www.cr.ie.u-ryukyu.ac.jp/hg/Members/aka/jupyter_CbC_kernel +$ cd jupyter_CbC_kernel +$ docker build -t aka/jupyter_cbc_kernel . +$ docker run -p 8888:8888 --name jupyter_cbc_kernel aka/jupyter_cbc_kernel start-notebook.sh +``` すると, 次のlogが出ると思います.
--- a/Christie.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Christie.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,33 @@ -tsts \ No newline at end of file +# Christie + + +| Contents| +|---| +|$lsx(/Christie)| + + +# Christieの概要 +当研究室で独自開発している分散フレームワーク。同Aliceの後続機にあたる。 + +同じく本研究室で開発しているGearsOSのファイルシステムとして組み込む予定があるため、 +GearsOSを構成している独自言語Continuation based C(CbC言語)と同様にGearという概念が存在する。 + +Mercurial : http://www.cr.ie.u-ryukyu.ac.jp/hg/Database/Christie/ + +# インストール方法 +~~おそらくこれでいけるはず...~~ + +- Mercurialからcloneしてくる。 + +`% hg clone ssh://one@www.cr.ie.u-ryukyu.ac.jp/hg/Database/Christie/ (保存先。指定しない場合./Chrisitieになる)` + +- InteliJを開き、Import ProjectでChristieを選択。 +- Import project from external modelにチェックし、Gradleを選択。 + +` Gradle home:は gradle/「バージョンNumber」/libexecを選択。「バージョンNumber」は6.1など。` + +- Projectが開いたら、画面右端に横向きになったGradleがあるはず、▼Christie/▼Tasks/▼build/buildをダブルクリックでbuildを実行。 + +buildが成功したら動作が問題なくできるか確認しよう。 + +Christie/src/test/java/christie/example/HelloWorld/StartHelloWorldあたりを実行するのが早い。
--- a/Christie/Christieあれこれ.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Christie/Christieあれこれ.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,19 @@ -tsts \ No newline at end of file +# Christie雑記 +Christieの解説や構成など解説。 +ほぼ個人的なメモなのであしからず。 + +# ChristieのGear概念 +ChristieにはGearというプログラミング概念が存在する。Gearには四種類が存在し、 +- CodeGear + +いわゆるスレッドに相当し、プログラマが主に記述する必要があるプログラミング部分である。CodeGearにはプログラム部分とDataGearが含まれており、プログラム部分からはDataGearに入力 + + +- DataGear + +- CodeGearManager(CGM) + +いわゆるノードに相当し、ポート番号を指定して任意の数を作成することができる。複数のCGMにCodeGearを実行させることによって分散処理を実現している。 + +- DataGearManager +が存在する。
--- a/Christie/Paxos.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Christie/Paxos.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,7 +5,7 @@ ## What Paxos 論文はこちら. -[[paxos made simple:https://lamport.azurewebsites.net/pubs/paxos-simple.pdf]] +[paxos made simple](https://lamport.azurewebsites.net/pubs/paxos-simple.pdf) ## 3つの役割 - proposers @@ -14,12 +14,12 @@ ## 参考サイト -- [[Paxos Made Simple - Leslie Lamport:https://lamport.azurewebsites.net/pubs/paxos-simple.pdf]] -- [[分散型コンセンサス・アルゴリズム プロトコル まとめ:http://block-chain.jp/blockchain/distributed-consensus-algorithm-protocol/]] -- [[Paxos, Raftなど分散合意プロトコルを概観する(1):http://sharply.hatenablog.com/entry/2016/06/13/230552]] -- [[今度こそ絶対あなたに理解させるPaxos:https://qiita.com/kumagi/items/535c9b7a761d2ed52bc0]] -- [[普通の人でもわかる Paxos:https://www.slideshare.net/tyonekura/paxos-63835103]] -- [[Paxos:https://www.slideshare.net/pfi/paxos-13615514]] -- [[Multi PaxosをJavaで実装してみた:https://blog.riywo.com/2017/09/implemented-multi-paxos-in-java/]] -- [[ざっくり理解するPaxos:http://matope.hatenablog.com/entry/2018/05/13/204749]] -- [[Understanding Paxos:https://www.cs.rutgers.edu/ pxk/417/notes/paxos.html]] +- [Paxos Made Simple - Leslie Lamport](https://lamport.azurewebsites.net/pubs/paxos-simple.pdf) +- [分散型コンセンサス・アルゴリズム プロトコル まとめ](http://block-chain.jp/blockchain/distributed-consensus-algorithm-protocol/) +- [Paxos, Raftなど分散合意プロトコルを概観する(1)](http://sharply.hatenablog.com/entry/2016/06/13/230552) +- [今度こそ絶対あなたに理解させるPaxos](https://qiita.com/kumagi/items/535c9b7a761d2ed52bc0) +- [普通の人でもわかる Paxos](https://www.slideshare.net/tyonekura/paxos-63835103) +- [Paxos](https://www.slideshare.net/pfi/paxos-13615514) +- [Multi PaxosをJavaで実装してみた](https://blog.riywo.com/2017/09/implemented-multi-paxos-in-java/) +- [ざっくり理解するPaxos](http://matope.hatenablog.com/entry/2018/05/13/204749) +- [Understanding Paxos](https://www.cs.rutgers.edu/~pxk/417/notes/paxos.html)
--- a/Christie/RemoteEditorWithChristie/メモ書き.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Christie/RemoteEditorWithChristie/メモ書き.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,18 @@ -tsts \ No newline at end of file +先行研究のhgリンク: +http://www.cr.ie.u-ryukyu.ac.jp/hg/RemoteEditor/REPSessionManager + +セッションマネージャーはChristieにて実装するので、エディタとの通信をどのように実装していたかを参考として掘り出したい。 +ReadMeより +- rep.channel + - socket/socket simulator の切り替えを行うpackage +とあるのでこの辺を中心に調査する。 + - どうやら実際に使ったソケットとsimulatorを用いたテストがあるらしい。 + +**メモ書き** +- 過去論文は新垣さん(2000)、宮里さん(2003)、安村さん(2010)などが作成 + - 新垣さんの論文(Emacs上のリモートエディタ)ではREPがまだない + - 一部の論文がps(postscript)ファイルで残っていてpdf変換に失敗する。2000年ごろ +- SVGをリモートエディタを利用して編集するらしい論文。ちょい気になる→ http://ie.u-ryukyu.ac.jp/%7Ekono/papers/kono/2002/jsst-shinobu.pdf + +- 読むファイルの目星 + - \ No newline at end of file
--- a/Christie/for.NET.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Christie/for.NET.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,8 +1,57 @@ -## ChristieのC#への書き換えログ +# ChristieのC#への書き換えログ + +## メソッド等の置換一覧 +java ConcurrentHashMap<> → C# ConcurrentDictionary<> +java map<> → C# Dictionary<> +java getClass() → C# GetType() +java getGenericSuperclass() → C# type.BaseType 補足あり +java ClassCastException → C# InvalidCastException +java ByteBuffer → C# MemoryStream +``` +java +T data = null; +Class<T> clazz = null; +byte[] messsagePack = null; +MessagePack packer = new MessagePack(); +// write read +messagePack = packer.write(data); +packer.read(messagePack, clazz); + -Christie C#書き換え +C# +T data; +Type clazz = null; +byte[] messagePack = null; +// write read +messagePack = MessagePackSerializer.Serialize(data); +MessagePackSerializer.Deserialize<T>(messagePack); +``` +java TreeMap<> → C# SortedDictionary<> +java HashMap<> → C# Dictionary<> +java Class clazz → C# Type clazz +java LinkedBlockingQueue<> → C# ConcurrentQueue<> +java socket.getInetAddress().getHostName() → C# Dns.GetHostEntry(((IPEndPoint) socket.RemoteEndPoint).Address.ToString()).HostName +java clazz.getName() → C# `type.Name` +java socket.getInputStream().read() → C# socket.Receive([格納する配列]) (intの長さが返る) +java ClassNotFoundException → C# TypeLoadException -atomicintagerはc#に存在しない +--- + +## MessagePackが使用されていたクラス +* MessagePackDataGear +* RemoteMessage + + + +--- +## Tips +C# +object → 全ての継承元クラス +Type → 型情報 +T → ジェネリクス + +--- +javaのatomicintagerはc#に存在しない intを読む, 代入するくらいは原始的が保証されているらしい 一度実装してみてダメなら @@ -13,17 +62,255 @@ intのインクリメントとかはこのメソッドを使ったほうがいいかも https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=netcore-3.1 - -java ConcurrentHashMap → C# ConcurrentDictionary +--- java -public static <T> Class<T> -→ Class<T> は返り値の型 -→その前の<T>は汎用型を返さない場合の汎用型関数に付けられる +```public static <T> Class<T> [関数名] () { }``` +→ Class<T> は返り値の型 +→その前の<T>はジェネリスクメソッドの型を表す + +C# +```public static Type [関数名]<T> () { }``` +→Typeは返り値の型 +→関数名の直後の<T>はジェネックメソッドの型を表す + + +java +int.class vs Intager.class +javaは独自でそれぞれの型についてプリミティブ型とクラス型が用意されているらしい… +https://stackoverflow.com/questions/22470985/integer-class-vs-int-class/22471247 + + +java側のdatagear/WrapperClassいらないかも... +もうちょい調べる + +--- +javaでは +```T typeJava = null;``` +はできるがC#では初期化でT型にnullを代入できない + +T型の初期化は +```T typeCs = default(T);``` +とする。(T)は省略可能 + + +--- +java getGenericSuperclass() → type.BaseTypeについて +どちらも直接のスーパクラス、直接の継承元のTypeを返す + + +javaの場合 +Object クラス、インタフェース、プリミティブ型、または void を表す場合、null が返され、配列の場合はClassが帰ってくる + + +C#の場合 +直接の継承しているTypeを返す、もし現在のTypeがobjectかインターフェースならnullが返る + +--- +javaの場合 +ジェネリスククラスの宣言時にジェネリスクの型宣言は省略できる +ex:``` Datagear dg;``` + + +C#の場合 +ジェネリッククラス宣言時にジェネリックの型宣言は省略できない +ex: ```Datagear<Type> dg; ``` + +--- + +~~MessagePackはjavaではread,writeにはジェネリックを使用できるが、 +C#ではジェネリスクを使用することができない +→ラッパーか何かを挟んで型判断してread,writeするしかない?~~ +C#で関数名が全然異なっていた... + +javaリファレンス +http://msgpack.org/javadoc/current/org/msgpack/MessagePack.html#read(byte[],%20java.lang.Class) + + +C#README +https://github.com/neuecc/MessagePack-CSharp#quick-start + +--- +C#のenumの扱いについて + +C#のenumではstringは許容されていない +また、enum内でフィールド変数や関数を含めることはできないので、ヘルパークラスを実装してそちらを利用する必要がある + +enum内でfor文などは使えないので、今回は別途関数を作成した +コンストラクタで使用するとか...? + +--- +java HashMapとC# Dictionaryの違いについて +https://stackoverflow.com/questions/1273139/c-sharp-java-hashmap-equivalent +null周りなど違いがあるので注意 + +--- +~~C#のBlockingCollectionは既定ではConcurrentQueue、つまりFIFOになっているが、特に使う理由はないのでConcurrentQueueを最初から利用することに~~ +→いやブロッキングどうするねん +→やっぱり使う +https://www.atmarkit.co.jp/ait/articles/1802/07/news019.html +→使用後にDisposeしないといけない +→無理...? +→もしかしたらずっとBlockingCollection利用してるかも +→Getするところでlengthが0になったもしくは +破棄をしていたらdisposeする + +##### BlockingQueue使用箇所(Dispoes処理) +* Connection +* DataGears → fin +* WaitList → fin +--- +C#だとsynchronized修飾子がないので +``` +private object syncObject = new object(); + +public void Function(){ + lock (syncObject) { + + } +} +``` +でロックをかける必要がある + +--- +javaだとジェネリッククラスを型として変数宣言する際にはジェネリックの型宣言は必要ないが、 +c#では変数宣言する際に型宣言が必須なので、今回はとりあえずobject型で宣言している。 + +DataGearの宣言は基本的にDataGear<object>で + +--- +java側で出力されるsocket.getInetAddress().getHostName() +localhost:3333 + +~~これと同様の結果をC#でも欲しい感じ~~ + +javaはSocketクラスが割となんでもしてくれる感じがあるが、 +C#はSocket, Dns, IPAdress, IPEndPointとかなり役割が分散されているので注意 + +--- +daemon/Connection + +Close()について +socket.shutdownでSocketShutdown.Bothで本当にあっているか + +--- java -int.class vs Intager.class -javaは独自でそれぞれの型についてプリミティブ型とクラス型が用意されているらしい… -https://stackoverflow.com/questions/22470985/integer-class-vs-int-class/22471247 +socket.getChannel().write(buffer);について + +javaのChannelではwrite(), read()などをByteBufferなどと一緒に使ってデータの送受信ができる。 +Channelの開き方は、socketとは別にopenする必要があるので注意。 + +--- +christleに導入されているMessagePackのバージョンは0.6以前のもの +そのため、シリアライズするクラスには@Messageが必要になる +https://github.com/msgpack/msgpack-java/wiki/QuickStart-for-msgpack-java-0.6.x-(obsolete) + +java版は0.7.xから仕様がかなり変わっているため注意が必要 + + + +C#版のMassagePackには日本人が作成したものを利用している(Unityとかでもサポートされているらしい) +https://github.com/neuecc/MessagePack-CSharp#quick-start + + +--- +javaとC#のenumの仕様はかなり異なっており +C#ではenumにメソッドを生やすことができない + +~~最初はヘルパークラスを実装することで対応しようとしたが、挙動的にenum各要素を初期化する必要があるとわかったため、独自にenumの挙動をするクラスを作成した~~ + +https://qiita.com/lilacs/items/167a73fbbfedf83eb51a +https://bleis-tift.hatenablog.com/entry/20080808/1218133517 + +必要なのはenumをintにする変換なので、C#ではenumをintにcastできるので廃止 + +--- +protected internalについて + +--- +LinkedBlockingQueueとConcurrentQueueの特徴について + +* LinkedBlockingQueue + * FIFO + * boolean contains(Object o): 要素の確認 + * peek(): 先頭取得、削除しない + * poll(): 先頭取得、削除 + * put(): 末尾に追加 完了するまでブロック + * add(): 末尾に追加 失敗時例外 + * put, addの違いについては:https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/BlockingQueue.html#add-E- + +* ConcurrentQueue + * FIFO + * スレッドセーフ + * Enqueue(): 末尾に追加 + * + +--- +Socketはaccept()するとその返り値にacceptされたsocketが返る +よってそれを変数に入れて利用する + + +--- +javaのThreadはThreadを継承して作成をする。 + + +c#は +`Task task = Task.Run(() => MethodThread()); +task.Run();` + +--- +IncommingTcpConnectionなどのスレッドはAcceptThreadで一括でTask.Runする + +--- +IncomingTcpConnetion + +送られてくるデータ長がわからないので +とりあえず4096と置いている + +--- +TCPで送受信するデータは、Remotemessage(Command), length, dataの順で入っている + +PutCommand +Command +IncomingTcpConnection +を参照 + + + +--- +## TODO +* annotation → fin +* daemon + * connection → cgm要実装 + * ChristieDaemon → AcceptThread要実装 + * AcceptThread → IncomingTcpConnection要実装 + * IncomingTcpConnection → CodeGearManager要実装 + * OutboundTcpConnection → fin +* codegear + * CodeGear → InputDataGear要実装 + * InputDataGear + * DataGear周りができないと書け無さそう + * CodeGearManager + * IncomingTcpConnection要実装 + * ChristieDeamon要実装 + * ThreadPoolExecutorとは +* datagear + * command + * Command → fin + * CommandType → fin + * CommandBuilder → fin + * TakeCommand → CodeGear要実装 + * その他のcommand → fin + * dg → fin + * DataGearManager → fin + * DataGears → fin + * WaitList → fin + * LocalDataGearManager → fin + * RemoteDataGearManager → cgm要実装 + + + +
--- a/Events/srcread/compiler/2020.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Events/srcread/compiler/2020.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,11 +1,13 @@ # 2020年 2月 13日 コンパイラ読み回 -# 環境構築 +今回はGCCとLLVMを読んでいきます + +## 環境構築 mercurialのoriginalのソースコードをそれぞれ最新版にする - GCC - LLVM -## コンパイラのバージョンアップ方法 +### コンパイラのバージョンアップ方法 1. とりあえず古いリポジトリにあるファイルを`rm -rf`する - 最新版を持ってきたときに競合する @@ -20,4 +22,1687 @@ 6. !がついてたファイルを削除する - vimで`%s/..//`とかすると便利 -7. hg commit してpushする \ No newline at end of file +7. hg commit してpushする + +### gccの最新版 + +なんかGitになったらしい +- https://gcc.gnu.org/git.html + +```sh +$ git clone git://gcc.gnu.org/git/gcc.git +``` + + +### llvmの最新版 + +これはGitHubになったみたい +- https://github.com/llvm/llvm-project + +```sh +$ git clone https://github.com/llvm/llvm-project +``` + +### gccのビルド + +あたたかみのあるConfigure + +```sh +$ ~/src/CbC_gcc/configure CFLAGS="-g3 -O0" --prefix=$PWD \ + --disable-nls --disable-bootstrap --enable-languages=c \ + --enable-checking=tree,rtl,assert,types +``` + +### llvmのビルド + +cmake+ninjaを使う +- libstd関連でエラーが出るのでrpathを指定しておく + +``` +$cmake3 -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/llvm -DLLVM_ENABLE_PROJECTS="clang;libgcc;libcxx;libcxxabi" -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,/usr/local/gcc9/lib64 -L/usr/local/gcc9/lib64" ~/src/LLVM_original/llvm +``` + + +## LLVMのデバッグをするとき + +起動する + +``` +lldb -- "/mnt/dalmore-home/one/build/build_llvm_origin/bin/clang-11" -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -main-file-name hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fdenormal-fp-math=ieee,ieee -fdenormal-fp-math-f32=ieee,ieee -ffp-contract=on -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /mnt/dalmore-home/one/build/build_llvm_origin -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o hello.s -x c /mnt/dalmore-home//one/src/test/hello.c +``` + +なんかlldbだとおもすぎて駄目なのでgdbにした + +例えばこういうコードををデバッグしたい時 + +`//clang/lib/Parse/ParseStmt.cpp` + +```c++ +/// Parse an expression statement. +StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) { + // If a case keyword is missing, this is where it should be inserted. + Token OldToken = Tok; + + ExprStatementTokLoc = Tok.getLocation(); + + // expression[opt] ';' + ExprResult Expr(ParseExpression()); + if (Expr.isInvalid()) { + // If the expression is invalid, skip ahead to the next semicolon or '}'. + // Not doing this opens us up to the possibility of infinite loops if + // ParseExpression does not consume any tokens. + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); + if (Tok.is(tok::semi)) + ConsumeToken(); + return Actions.ActOnExprStmtError(); +``` + +何故か `Parser::ParseExpr...`ではbreak pointに設定出来ない。 + + +この`Parser::ParseExprStatement`をbreakpointにしたい場合は`clang::Parser::ParseExprStatement`をbreak pointにする + +``` +#0 clang::Parser::ParseExprStatement (this=0xe696330, StmtCtx=clang::Parser::Compound) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:428 +#1 0x0000000005a39e80 in clang::Parser::ParseStatementOrDeclarationAfterAttributes (this=0xe696330, Stmts=..., StmtCtx=clang::Parser::Compound, + TrailingElseLoc=0x0, Attrs=...) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:233 +#2 0x0000000005a3965c in clang::Parser::ParseStatementOrDeclaration (this=0xe696330, Stmts=..., StmtCtx=clang::Parser::Compound, TrailingElseLoc=0x0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:107 +#3 0x0000000005a3cec9 in clang::Parser::ParseCompoundStatementBody (this=0xe696330, isStmtExpr=false) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:1079 +#4 0x0000000005a411fb in clang::Parser::ParseFunctionStatementBody (this=0xe696330, Decl=0xe6bda30, BodyScope=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseStmt.cpp:2204 +#5 0x0000000005977d9f in clang::Parser::ParseFunctionDefinition (this=0xe696330, D=..., TemplateInfo=..., LateParsedAttrs=0x7fffffff9a80) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:1349 +#6 0x00000000059941d8 in clang::Parser::ParseDeclGroup (this=0xe696330, DS=..., Context=clang::FileContext, DeclEnd=0x0, FRI=0x0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseDecl.cpp:2068 +#7 0x0000000005976df4 in clang::Parser::ParseDeclOrFunctionDefInternal (this=0xe696330, attrs=..., DS=..., AS=clang::AS_none) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:1109 +#8 0x0000000005976eae in clang::Parser::ParseDeclarationOrFunctionDefinition (this=0xe696330, attrs=..., DS=0x0, AS=clang::AS_none) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:1125 +#9 0x0000000005976391 in clang::Parser::ParseExternalDeclaration (this=0xe696330, attrs=..., DS=0x0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:945 +#10 0x0000000005975419 in clang::Parser::ParseTopLevelDecl (this=0xe696330, Result=..., IsFirstDecl=false) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/Parser.cpp:696 +#11 0x0000000005970f3a in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseAST.cpp:158 +#12 0x0000000003ce5a91 in clang::ASTFrontendAction::ExecuteAction (this=0xe63c1a0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:1047 +#13 0x0000000004572303 in clang::CodeGenAction::ExecuteAction (this=0xe63c1a0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenAction.cpp:1176 +#14 0x0000000003ce53fd in clang::FrontendAction::Execute (this=0xe63c1a0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:940 +#15 0x0000000003c7db31 in clang::CompilerInstance::ExecuteAction (this=0xe6381d0, Act=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/CompilerInstance.cpp:969 +#16 0x0000000003e40b1d in clang::ExecuteCompilerInvocation (Clang=0xe6381d0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:292 +``` + + +## GCC + +`c_parser_expr_no_commas`で止めてみる +- この関数自体は再帰下降でパースが実行されている最中に呼び出される +- テストコードがexternから始まっていたので、`c_parser_external_declaration`から呼び出されているみたい + +``` +(gdb) bt +#0 c_parser_expr_no_commas (parser=parser@entry=0x7ffff7ff8ab0, + after=after@entry=0x0, omp_atomic_lhs=omp_atomic_lhs@entry=0x0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:7557 +#1 0x000000000083fc05 in c_parser_expression ( + parser=parser@entry=0x7ffff7ff8ab0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:10630 +#2 0x000000000084046c in c_parser_expression_conv ( + parser=parser@entry=0x7ffff7ff8ab0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:10663 +#3 0x000000000085b72a in c_parser_statement_after_labels ( + parser=parser@entry=0x7ffff7ff8ab0, if_p=if_p@entry=0x0, + chain=chain@entry=0x0) +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:6294 +#4 0x0000000000856d04 in c_parser_compound_statement_nostart ( +parser=parser@entry=0x7ffff7ff8ab0) +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:5800 +#5 0x00000000008572d7 in c_parser_compound_statement ( +parser=parser@entry=0x7ffff7ff8ab0) +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:5616 +#6 0x0000000000858c56 in c_parser_declaration_or_fndef ( +parser=parser@entry=0x7ffff7ff8ab0, fndef_ok=fndef_ok@entry=true, +static_assert_ok=static_assert_ok@entry=true, +empty_ok=empty_ok@entry=true, nested=nested@entry=false, +start_attr_ok=start_attr_ok@entry=true, +objc_foreach_object_declaration=objc_foreach_object_declaration@entry=0x0, omp_declare_simd_clauses=..., omp_declare_simd_clauses@entry=..., +have_attrs=<optimized out>, have_attrs@entry=false, +attrs=attrs@entry=0x0, oacc_routine_data=oacc_routine_data@entry=0x0, +fallthru_attr_p=fallthru_attr_p@entry=0x0) +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:2504 +#7 0x0000000000861c81 in c_parser_external_declaration ( +parser=0x7ffff7ff8ab0) +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:1747 +#8 0x0000000000862872 in c_parser_translation_unit ( +parser=0x7ffff7ff8ab0) +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:1619 +#9 c_parse_file () +---Type <return> to continue, or q <return> to quit--- +at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:21710 +#10 0x00000000008c708b in c_common_parse_file () +at /mnt/dalmore-home//one/src/GCC_original/gcc/c-family/c-opts.c:1186 +#11 0x0000000000ebad8f in compile_file () +at /mnt/dalmore-home//one/src/GCC_original/gcc/toplev.c:458 +#12 0x0000000000742efd in do_compile () +at /mnt/dalmore-home//one/src/GCC_original/gcc/toplev.c:2273 +#13 toplev::main (this=this@entry=0x7fffffffde70, argc=argc@entry=2, +argv=argv@entry=0x7fffffffdf78) +at /mnt/dalmore-home//one/src/GCC_original/gcc/toplev.c:2412 +#14 0x00000000007c1527 in main (argc=2, argv=0x7fffffffdf78) +at /mnt/dalmore-home//one/src/GCC_original/gcc/main.c:39 +``` + +# 2020/02/14 (2日目) + +午前中はgccから + +## テストコード + +```c +extern int printf(const char*, ...); + +extern void g(int* p); + +int f(int arg) { + int loq; + g(&loq); +} + +int main() { + f(3); + return 0; +} +``` + +## gcc + +build したディレクトリに移動 + +### gdb起動 + +``` +$ gdb --args gcc/cc1 ~/src/test/hello.c +``` + +### break point + +昨日と同じところから + +``` +#0 c_parser_expr_no_commas (parser=parser@entry=0x7ffff7ff8ab0, +``` + +- ソースコード的には`gcc/c/c-parser.c`を読んでいく世界観 + +### C言語のおさらい + +C言語でstaticがついている関数は自分自身のファイルだけからしか参照できない関数 + +`c_parser`がGCCのパース関連の色々入っている構造体っぽい + +- `lhs` + - 代入される側 +- `rhs` + - 代入する側 + +### parser 構造体 + +- なんかtokensのアドレスとか、tokenのbufとかが入っている +- この時点でソースコードのlocationが知りたい + +https://gcc.gnu.org/onlinedocs/gccint/Guidelines-for-Diagnostics.html#Location-Information +- このドキュメント読んだけど微妙だった + +### c_parser_conditional_expression +- なんか途中で`gcc_assert`とかしている + - 多分抜けそう + +### c_parser_binary_expression +- 引数は`parser`,` after`,` omp_atomic_lhs` +- 今は `extern void g();` の`g()`を見てそう + +```c +static struct c_expr +c_parser_binary_expression (c_parser *parser, struct c_expr *after, + tree omp_atomic_lhs) +{ + /* A binary expression is parsed using operator-precedence parsing, + with the operands being cast expressions. All the binary + operators are left-associative. Thus a binary expression is of + form: + + E0 op1 E1 op2 E2 ... + + which we represent on a stack. On the stack, the precedence + levels are strictly increasing. When a new operator is + encountered of higher precedence than that at the top of the + stack, it is pushed; its LHS is the top expression, and its RHS + is everything parsed until it is popped. When a new operator is + encountered with precedence less than or equal to that at the top + of the stack, triples E[i-1] op[i] E[i] are popped and replaced + by the result of the operation until the operator at the top of + the stack has lower precedence than the new operator or there is + only one element on the stack; then the top expression is the LHS + of the new operator. In the case of logical AND and OR + expressions, we also need to adjust c_inhibit_evaluation_warnings + as appropriate when the operators are pushed and popped. */ + + struct { + /* The expression at this stack level. */ + struct c_expr expr; + /* The precedence of the operator on its left, PREC_NONE at the + bottom of the stack. */ + enum c_parser_prec prec; + /* The operation on its left. */ + enum tree_code op; + /* The source location of this operation. */ + location_t loc; + /* The sizeof argument if expr.original_code == SIZEOF_EXPR. */ + tree sizeof_arg; + } stack[NUM_PRECS]; + int sp; + /* Location of the binary operator. */ + location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ +``` + +left-associative +- `1+2+3`と来た場合 +- `(1+2)+3`に変換するやつ +- 再帰下降と相性が悪い(無限ループするので), whileに書き直すオペレーションが入る + +`#define POP` +- 最近GCCはマクロに書く方針でやり始めたらしい +``` +#define POP \ + do { \ + switch (stack[sp].op) \ + { \ + case TRUTH_ANDIF_EXPR: \ + c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ + == truthvalue_false_node); \ +.... + & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \ + | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \ + && stack[sp].op != TRUNC_MOD_EXPR \ + && stack[0].expr.value != error_mark_node \ + && stack[1].expr.value != error_mark_node \ + && (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \ + || c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \ + stack[0].expr.value \ + = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ + stack[0].expr.value, stack[1].expr.value); \ + else \ + stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ + stack[sp].op, \ + stack[sp - 1].expr, \ + stack[sp].expr); \ + sp--; \ + } while (0) +``` + +stackに代入するタイミングで`c_parser_cast_expression`が呼ばれていそう + + +```c +/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER + is not NULL then it is an Objective-C message expression which is the + primary-expression starting the expression as an initializer. + + cast-expression: + unary-expression + ( type-name ) unary-expression +*/ + +static struct c_expr +c_parser_cast_expression (c_parser *parser, struct c_expr *after) +{ + location_t cast_loc = c_parser_peek_token (parser)->location; + gcc_assert (!after || c_dialect_objc ()); + if (after) + return c_parser_postfix_expression_after_primary (parser, + cast_loc, *after); + ``` + +下のifで処理されるのは次のケースみたい +- `(int )0.1` + - キャスト +- `j = ({ i = 1;})` + - compound literal + + ``` + /* If the expression begins with a parenthesized type name, it may + be either a cast or a compound literal; we need to see whether + the next character is '{' to tell the difference. If not, it is + an unary expression. Full detection of unknown typenames here + would require a 3-token lookahead. */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) + && c_token_starts_typename (c_parser_peek_2nd_token (parser))) + { +``` + +次にここを読む + +```c +/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3). + + unary-expression: + postfix-expression + ++ unary-expression + -- unary-expression + unary-operator cast-expression + sizeof unary-expression + sizeof ( type-name ) + + unary-operator: one of + & * + - ~ ! + + GNU extensions: + + unary-expression: + __alignof__ unary-expression + __alignof__ ( type-name ) + && identifier + + (C11 permits _Alignof with type names only.) + + unary-operator: one of + __extension__ __real__ __imag__ + + Transactional Memory: + + unary-expression: + transaction-expression + + In addition, the GNU syntax treats ++ and -- as unary operators, so + they may be applied to cast expressions with errors for non-lvalues + given later. */ + +static struct c_expr +c_parser_unary_expression (c_parser *parser) +{ + int ext; + struct c_expr ret, op; + location_t op_loc = c_parser_peek_token (parser)->location; + location_t exp_loc; + location_t finish; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + switch (c_parser_peek_token (parser)->type) + ``` + + 例えばこのcaseは`++i`のとき + + ```c + switch (c_parser_peek_token (parser)->type) + { + case CPP_PLUS_PLUS: + c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; + op = c_parser_cast_expression (parser, NULL); + + op = default_function_array_read_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); + ``` + +### c_parser_peek_token(parser)をgdbで読む + +`p c_parser_peek_token(parser)`するとポインタが返ってくる + +`p *c_parser_peek_token(parser)`とかすると中身が見れる + +このあたりのデバッグサポートライブラリはConfigureで指定するとリンクされて使えるようになるらしい + +`p *c_parser_peek_token(parser)`したところ、fieldに`value`がある +- 多分unionっぽい + + +### c_parser_postfix_expression + +8983行目くらい + +```c + +static struct c_expr +c_parser_postfix_expression (c_parser *parser) +{ + struct c_expr expr, e1; + struct c_type_name *t1, *t2; + location_t loc = c_parser_peek_token (parser)->location; + source_range tok_range = c_parser_peek_token (parser)->get_range (); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + switch (c_parser_peek_token (parser)->type) + { + case CPP_NUMBER: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (TREE_CODE (expr.value) == FIXED_CST + && !targetm.fixed_point_supported_p ()) + { + error_at (loc, "fixed-point types not supported for this target"); + expr.set_error (); + } + break; + case CPP_CHAR: + case CPP_CHAR16: + case CPP_CHAR32: + case CPP_UTF8CHAR: + case CPP_WCHAR: +``` +```c + case CPP_NAME: + switch (c_parser_peek_token (parser)->id_kind) + { + case C_ID_ID: + { + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + expr.value = build_external_ref (loc, id, + (c_parser_peek_token (parser)->type + == CPP_OPEN_PAREN), + &expr.original_type); + set_c_expr_source_range (&expr, tok_range); + break; + } + case C_ID_CLASSNAME: + { + /* Here we parse the Objective-C 2.0 Class.name dot + syntax. */ + tree class_name = c_parser_peek_token (parser)->value; + tree component; + c_parser_consume_token (parser); + gcc_assert (c_dialect_objc ()); + if (!c_parser_require (parser, CPP_DOT, "expected %<.%>")) + { + expr.set_error (); + break; + } + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + expr.set_error (); + break; + } + ``` + +C言語だとreturnで値がコピーされるので、ローカル変数の構造体をそのまま返すことができる + + +### build_external_ref (location_t loc, tree id, bool fun, tree *type) + +```c +/* Build an external reference to identifier ID. FUN indicates + whether this will be used for a function call. LOC is the source + location of the identifier. This sets *TYPE to the type of the + identifier, which is not the same as the type of the returned value + for CONST_DECLs defined as enum constants. If the type of the + identifier is not available, *TYPE is set to NULL. */ +tree +build_external_ref (location_t loc, tree id, bool fun, tree *type) +{ + tree ref; + tree decl = lookup_name (id); + + /* In Objective-C, an instance variable (ivar) may be preferred to + whatever lookup_name() found. */ + decl = objc_lookup_ivar (decl, id); + + *type = NULL; + if (decl && decl != error_mark_node) + { + ref = decl; + *type = TREE_TYPE (ref); + } + else if (fun) + /* Implicit function declaration. */ + ref = implicitly_declare (loc, id); + else if (decl == error_mark_node) + /* Don't complain about something that's already been + complained about. */ + return error_mark_node; + else + { + undeclared_variable (loc, id); + return error_mark_node; + } + + if (TREE_TYPE (ref) == error_mark_node) + return error_mark_node; + + if (TREE_DEPRECATED (ref)) + warn_deprecated_use (ref, NULL_TREE); + + /* Recursive call does not count as usage. */ + if (ref != current_function_decl) + { + TREE_USED (ref) = 1; + ``` + + 昔のCは型を定義しないで名前を定義して、後から型を定義できるようになっていた + - その名残? + + ここまではIDが来ていて、具体的にすでに登録されているかの確認はしていない +- `tree decl = lookup_name (id);`で確認していそう + +```log + #0 build_external_ref (loc=loc@entry=184896, id=id@entry=0x7ffff64518c0, + fun=<optimized out>, type=type@entry=0x7fffffffd010) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-typeck.c:2744 +#1 0x0000000000830a63 in c_parser_postfix_expression ( + parser=parser@entry=0x7ffff7ff8ab0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:9043 +#2 0x000000000083c8d3 in c_parser_unary_expression ( + parser=parser@entry=0x7ffff7ff8ab0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:8269 +#3 0x000000000083db87 in c_parser_cast_expression ( + parser=parser@entry=0x7ffff7ff8ab0, after=0x0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:8108 +#4 0x000000000083de3d in c_parser_binary_expression ( + parser=parser@entry=0x7ffff7ff8ab0, after=<optimized out>, + omp_atomic_lhs=0x0) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:7911 +#5 0x000000000083f186 in c_parser_conditional_expression ( + parser=parser@entry=0x7ffff7ff8ab0, after=<optimized out>, + omp_atomic_lhs=<optimized out>) + at /mnt/dalmore-home//one/src/GCC_original/gcc/c/c-parser.c:7645 +#6 0x000000000083f971 in c_parser_expr_no_commas ( + parser=parser@entry=0x7ffff7ff8ab0, after=after@entry=0x0, + omp_atomic_lhs=omp_atomic_lhs@entry=0x0) +``` + + + ## 午後 + + 午後はCbCのupgradeをしていきます + + ### CbC_gccのupgrade + + + ```sh + $ cd ~/src/CbC_gcc + $ hg pull ../GCC_original + ``` + + ``` + $hg updat -C 145 + $hg resolve + ``` + + conflictしたやつ + + ```log + merging gcc/c-family/c-common.c +merging gcc/c/c-decl.c +merging gcc/c/c-parser.c +merging gcc/calls.c +merging gcc/config/i386/i386.c +merging gcc/gimple.c +merging gcc/ipa-inline.c +3 files to edit +merging gcc/c-family/c-common.c failed! +3 files to edit +merging gcc/c/c-decl.c failed! +3 files to edit +merging gcc/c/c-parser.c failed! +3 files to edit +merging gcc/calls.c failed! +3 files to edit +merging gcc/config/i386/i386.c failed! +3 files to edit +merging gcc/gimple.c failed! +3 files to edit +merging gcc/ipa-inline.c failed! +``` + +変更点を探して、中のCbCの記述を探す + +```shell +$hg diff gcc/c-family/c-common.c -r -1 +$grep CbC gcc/c-family/c-common.c +$hg cat -r 145 gcc/c-family/c-common.c > gcc/c-family/c-common.c +$hg diff gcc/c-family/c-common.c +``` + +あとはvimを使っていい感じに修正する + +```shelle +$hg resolve -m gcc/c-family/c-common.c +``` + +なんか直前のcommitが最新になっていて、今のcommitが古いやつになっていた。 +なので一回`pull`して`update -r 145`して、直前の古い状態に戻しておく + + +#### なおしたところ +- `__code` -> `void` への関数型の変換部分(function declaration) + +### LLVM側のupdate +新しいのをpullしてきて、新しい方にupdateする +- 古い方をmergeする + +vimdiffが起動したら`:cq`で抜けられるらしい +- 今回はファイルに`>>>>` `====` `<<<<`は書き出さない + +```shell +$cd ~/CbC_llvm +$hg log | less +$hg pull ../LLVM_original +$hg log | less +$hg update -r 150 -C +$hg merge -r 149 +``` + +> was deleted in local + +これみたいなエラーが出たら、 d で消しちゃっていい + + +## llvm側で変数の寿命を管理しているとこを見てみる + +`clang/lib/Parse/ParseExpr.cpp`を見ていく +- とりあえず`func`とかでgrep + +llvmのcppはまぁ正気なcppらしい + +```cpp + // Function designators are allowed to be undeclared (C99 6.5.1p2), so we + // need to know whether or not this identifier is a function designator or + // not. + UnqualifiedId Name; + CXXScopeSpec ScopeSpec; + SourceLocation TemplateKWLoc; + Token Replacement; + CastExpressionIdValidator Validator( + /*Next=*/Tok, + /*AllowTypes=*/isTypeCast != NotTypeCast, + /*AllowNonTypes=*/isTypeCast != IsTypeCast); + Validator.IsAddressOfOperand = isAddressOfOperand; + if (Tok.isOneOf(tok::periodstar, tok::arrowstar)) { + Validator.WantExpressionKeywords = false; + Validator.WantRemainingKeywords = false; + } else { +``` + +```cpp +/// Once the leading part of a postfix-expression is parsed, this +/// method parses any suffixes that apply. +/// +/// \verbatim +/// postfix-expression: [C99 6.5.2] +/// primary-expression +/// postfix-expression '[' expression ']' +/// postfix-expression '[' braced-init-list ']' +/// postfix-expression '(' argument-expression-list[opt] ')' +/// postfix-expression '.' identifier +/// postfix-expression '->' identifier +/// postfix-expression '++' +/// postfix-expression '--' +/// '(' type-name ')' '{' initializer-list '}' +/// '(' type-name ')' '{' initializer-list ',' '}' +/// +/// argument-expression-list: [C99 6.5.2] +/// argument-expression ...[opt] +/// argument-expression-list ',' assignment-expression ...[opt] +/// \endverbatim +ExprResult +Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { + // Now that the primary-expression piece of the postfix-expression has been + // parsed, see if there are any postfix-expression pieces here. + SourceLocation Loc; + auto SavedType = PreferredType; + while (1) { + // Each iteration relies on preferred type for the whole expression. + PreferredType = SavedType; + switch (Tok.getKind()) { + case tok::code_completion: + if (InMessageExpression) + return LHS; + + Actions.CodeCompletePostfixExpression( + getCurScope(), LHS, PreferredType.get(Tok.getLocation())); + cutOffParsing(); + return ExprError(); + ``` + + - 大文字`Tok`が先読み部分っぽい + - さらに大域変数? + - debug traceしたらインスタンス変数だった + +```cpp + + case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')' + case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>' + // '(' argument-expression-list[opt] ')' + tok::TokenKind OpKind = Tok.getKind(); + InMessageExpressionRAIIObject InMessage(*this, false); + + Expr *ExecConfig = nullptr; + + BalancedDelimiterTracker PT(*this, tok::l_paren); + + if (OpKind == tok::lesslessless) { + ExprVector ExecConfigExprs; + CommaLocsTy ExecConfigCommaLocs; + SourceLocation OpenLoc = ConsumeToken(); + + if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) { + (void)Actions.CorrectDelayedTyposInExpr(LHS); + LHS = ExprError(); + } + + SourceLocation CloseLoc; + if (TryConsumeToken(tok::greatergreatergreater, CloseLoc)) { + } else if (LHS.isInvalid()) { + SkipUntil(tok::greatergreatergreater, StopAtSemi); + } else { + // There was an error closing the brackets + Diag(Tok, diag::err_expected) << tok::greatergreatergreater; + Diag(OpenLoc, diag::note_matching) << tok::lesslessless; + SkipUntil(tok::greatergreatergreater, StopAtSemi); + LHS = ExprError(); + } + + if (!LHS.isInvalid()) { + if (ExpectAndConsume(tok::l_paren)) + LHS = ExprError(); + else +``` + +たぶん上のが関数呼び出し部分っぽい気がする +- というわけで `Parser::ParsePostfixExpressionSuffix(ExprResult LHS) `をbreak pointに設定する + +### Parser::ParsePostfixExpressionSuffix(ExprResult LHS) + +- `b clang::Parser::ParsePostfixExpressionSuffix`でbreak point設定 +- llvmは`this`が色々入っている環境っぽい +- この関数自体は関数化なんなのかをチェックしているので、必ずしも関数の場合に突入してない + +```cpp +1895 ExprVector ArgExprs; +1896 CommaLocsTy CommaLocs; +1897 auto RunSignatureHelp = [&]() -> QualType { +1898 QualType PreferredType = Actions.ProduceCallSignatureHelp( +1899 getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation()); +1900 CalledSignatureHelp = true; +1901 return PreferredType; +1902 }; +1903 if (OpKind == tok::l_paren || !LHS.isInvalid()) { +1904 if (Tok.isNot(tok::r_paren)) { +1905 if (ParseExpressionList(ArgExprs, CommaLocs, [&] { +1906 PreferredType.enterFunctionArgument(Tok.getLocation(), +1907 RunSignatureHelp); +1908 })) { +1909 (void)Actions.CorrectDelayedTyposInExpr(LHS); +1910 // If we got an error when parsing expression list, we don't call +1911 // the CodeCompleteCall handler inside the parser. So call it here +1912 // to make sure we get overload suggestions even when we are in the +1913 // middle of a parameter. +1914 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) +1915 RunSignatureHelp(); +1916 LHS = ExprError(); +1917 } else if (LHS.isInvalid()) { +1918 for (auto &E : ArgExprs) +1919 Actions.CorrectDelayedTyposInExpr(E); +1920 } +1921 } +1922 } +1923 +``` + +このあたりで引数を設定していそうだが… + + +``` +1905 if (ParseExpressionList(ArgExprs, CommaLocs, [&] { +1906 PreferredType.enterFunctionArgument(Tok.getLocation(), +1907 RunSignatureHelp); +1908 })) { +``` + +- このParseExpressionListが`,`区切りの引数のリストがきていそう + + +### llvmIRを出力してみる + +```shell= +$clang -S -emit-llvm hello.c +``` + +- IRレベルでは変数の寿命は入ってない? + + +# 2020/02/15(3日目) + +今日は変数のライフタイム/コード生成を追っていきます + +## LLVMのselectionと呼ばれるところ +- clangレベルでIRを出力しているところ +- IRからnativeを吐き出しているところ + + コード生成を追うことに + + ## clangレベルのコード生成っぽいところを探す + + `clang/lib/CodeGen`がそれっぽい + - `*selection`を探す + - なさそう? +- `./lib/CodeGen/CGExpr.cpp`を読んで見る + - `194:RValue CodeGenFunction::EmitAnyExpr(const Expr *E,`をbreak pointにする + +### LLVMのdebug + +こういうシェルスクリプトが生まれたので使う + +```shell +gdb --args "/mnt/dalmore-home/one/build/build_llvm_origin/bin/clang-11" -cc1 -triple x86_64-unknown-linux-gnu -S -disable-free -main-file-name hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fdenormal-fp-math=ieee,ieee -fdenormal-fp-math-f32=ieee,ieee -ffp-contract=on -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem /mnt/dalmore-home/one/build/build_llvm_origin/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /mnt/dalmore-home/one/build/build_llvm_origin -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o hello.s -x c /mnt/dalmore-home//one/src/test/hello.c +``` + +### CodeGenFunction::EmitAnyExpr + +`clang::CodeGen::CodeGenFunction::EmitAnyExpr`をbreak pointにする +- `CGExpr.cpp`の先頭にnamespaceが切られているので、これの通りに先頭につける必要があるらしい +``` +using namespace clang; +using namespace CodeGen; +``` +上の場合は `clang::CodeGen` + +EmitAnyExprで止まったのでback traceを確認してみる + +CodeGenはAbstractFactoryパターンで書かれているので、`CodeGeneratorImpl::HandleTopLevelDecl`を経由して呼び出されている +- これはclangレベルなのでIRの出力のみしている +- Nativeは多分あまりなにもしてない + +この関数は`clang::ParseAST`から呼び出される + +### ParseAST.cpp + +```cpp +//===----------------------------------------------------------------------===// +// Public interface to the file +//===----------------------------------------------------------------------===// + +/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as +/// the file is parsed. This inserts the parsed decls into the translation unit +/// held by Ctx. +/// +void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, + ASTContext &Ctx, bool PrintStats, + TranslationUnitKind TUKind, + CodeCompleteConsumer *CompletionConsumer, + bool SkipFunctionBodies) { + + std::unique_ptr<Sema> S( + new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); + + ParseAST(*S.get(), PrintStats, SkipFunctionBodies); +} + +void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { + // Collect global stats on Decls/Stmts (until we have a module streamer). + if (PrintStats) { + Decl::EnableStatistics(); + Stmt::EnableStatistics(); + } + + // Also turn on collection of stats inside of the Sema object. + ``` + +Interfaceに対応するpublic APIのじっそう +- 上の`void clang::Parse((Preprocessor &PP, ASTConsumer *Consumer,)`はコンスタクタでなくてただのメソッドっぽい +- 実際に呼び出されているのは下のParseASTみたい + +### Consumerで呼び出されているGen + +`Gen`とかいうオブジェクトがあった。定義はこれ +- `std::unique_ptr<CodeGenerator> Gen;` + - スマートポインタみたい + - `Get.get()`で中身が取れる + - `clang::CodeGenerator`だった + +```cpp + ASTConsumer *Consumer = &S.getASTConsumer(); + + std::unique_ptr<Parser> ParseOP( + new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); + Parser &P = *ParseOP.get(); + + llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> + CleanupPrettyStack(llvm::SavePrettyStackState()); + PrettyStackTraceParserEntry CrashInfo(P); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar<Parser> + CleanupParser(ParseOP.get()); + + S.getPreprocessor().EnterMainSourceFile(); + ExternalASTSource *External = S.getASTContext().getExternalSource(); + if (External) + External->StartTranslationUnit(Consumer); + + // If a PCH through header is specified that does not have an include in + // the source, or a PCH is being created with #pragma hdrstop with nothing + // after the pragma, there won't be any tokens or a Lexer. + bool HaveLexer = S.getPreprocessor().getCurrentLexer(); + + if (HaveLexer) { + llvm::TimeTraceScope TimeScope("Frontend"); + P.Initialize(); + Parser::DeclGroupPtrTy ADecl; + for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; + AtEOF = P.ParseTopLevelDecl(ADecl)) { + // If we got a null return and something *was* parsed, ignore it. This + // is due to a top-level semicolon, an action override, or a parse error + // skipping something. + if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) + return; + } + } +``` + +Sema経由でConsumerとかを取ってきてそう + +for分の中に出てきている`Adecl`は参照になっていて、順次updateされていくらしい + +### Semaを見に行く + +`lib/Sema/Sema.cpp`を見る + +```cpp +// This file implements the actions class which performs semantic analysis and +// builds an AST out of a parse stream. +``` + +よくわからんのでヘッダファイルを見に行く +`include/clang/Sema/Sema.h` + +Parseは構文解析をしてパースするだけ +- ASTを作りたい +- このASTにセマンティクスをつける必要がある +- ASTのFactoryが必要になる +- これがSemaっぽい + +なのでAST Factoryっぽい + +336行目に書かれてる + +```cpp +/// Sema - This implements semantic analysis and AST building for C. +class Sema final { + Sema(const Sema &) = delete; + void operator=(const Sema &) = delete; + + /// A key method to reduce duplicate debug info from Sema. + virtual void anchor(); + + ///Source of additional semantic information. + ExternalSemaSource *ExternalSource; + + ///Whether Sema has generated a multiplexer and has to delete it. + bool isMultiplexExternalSource; + + static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); + ``` + + - finalは virtual function のoverrideの防止らしい + - `(const Sema &) = delete`とは一体? + - https://cpprefjp.github.io/lang/cpp11/defaulted_and_deleted_functions.html + - >= deleteは、特殊関数の暗黙定義を明示的に禁止するための機能である。これは、コピーを禁止するクラスを定義するような場合に使用する + - イディオム的な使い方らしい + +### 試しにソートしてみた + +```log + 14 43 527 include/clang/Frontend/PCHContainerOperations.h + 14 43 545 include/clang/Serialization/SerializationDiagnostic.h + 14 43 610 include/clang/Tooling/Refactoring/RefactoringDiagnostic.h + 14 44 496 include/clang/Lex/LexDiagnostic.h + 14 44 501 include/clang/Sema/SemaDiagnostic.h + 14 44 506 include/clang/Parse/ParseDiagnostic.h + 14 44 511 include/clang/Driver/DriverDiagnostic.h + 14 44 521 include/clang/Analysis/AnalysisDiagnostic.h + 14 44 521 include/clang/Frontend/FrontendDiagnostic.h + 14 47 558 include/clang/CrossTU/CrossTUDiagnostic.h + 15 46 509 include/clang/AST/CommentDiagnostic.h + 23 62 770 include/clang/Tooling/ToolExecutorPluginRegistry.h + 24 66 662 include/clang/Basic/CapturedStmt.h + 24 69 749 include/clang/Basic/BitmaskEnum.h + 25 66 717 include/clang/Basic/ExpressionTraits.h + 25 73 757 include/clang/Basic/DiagnosticCategories.h + 26 68 877 include/clang/Frontend/FrontendPluginRegistry.h + 26 103 963 include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h + 27 82 907 include/clang/AST/AST.h + 27 87 875 include/clang/StaticAnalyzer/Checkers/LocalCheckers.h + 28 82 951 include/clang/Basic/DiagnosticRefactoring.h + 28 84 962 include/clang/Basic/DiagnosticSerialization.h + 28 85 903 include/clang/Basic/DiagnosticLex.h + 28 85 909 include/clang/Basic/DiagnosticSema.h + 28 85 915 include/clang/Basic/DiagnosticParse.h + 28 85 921 include/clang/Basic/DiagnosticDriver.h + 28 85 933 include/clang/Basic/DiagnosticAnalysis.h + 28 85 933 include/clang/Basic/DiagnosticFrontend.h + 28 86 927 include/clang/Basic/DiagnosticCrossTU.h + 28 87 903 include/clang/Basic/DiagnosticAST.h + 28 87 927 include/clang/Basic/DiagnosticComment.h + 30 86 877 include/clang/Frontend/MigratorOptions.h + 30 90 868 include/clang/Basic/PragmaKinds.h + 31 91 922 include/clang/AST/AbstractTypeReader.h + 31 93 957 include/clang/Basic/AttrSubjectMatchRules.h + 31 100 896 include/clang/Driver/Util.h + 31 100 924 include/clang/Basic/FileSystemOptions.h + 31 117 1268 include/clang/Lex/PreprocessorExcludedConditionalDirectiveSkipMapping.h + 32 93 944 include/clang/AST/AbstractTypeWriter.h + 32 111 1266 include/clang-c/FatalErrorHandler.h + 33 102 929 include/clang/Basic/AttrKinds.h + 33 104 980 include/clang/Edit/EditsReceiver.h + 33 110 1270 include/clang/Tooling/Syntax/BuildTree.h + 34 108 1208 include/clang/Rewrite/Frontend/Rewriters.h + 35 143 1379 include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h + 36 97 1031 include/clang/AST/ASTFwd.h + 36 105 1226 include/clang/Analysis/SelectorExtras.h + 36 142 1369 include/clang/AST/ASTDiagnostic.h + 37 108 895 include/clang/Driver/Phases.h + 37 137 1293 include/clang/Basic/PrettyStackTrace.h + 37 151 1367 include/clang/AST/ASTContextAllocate.h + 37 162 1506 include/clang/Tooling/Syntax/Mutations.h + 38 91 1103 include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h + 38 113 1124 include/clang/Basic/CommentOptions.h + 38 124 1653 include/clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h + 38 139 1290 include/clang/FrontendTool/Utils.h + 39 100 1166 include/clang/Edit/Rewriters.h + 39 112 2007 include/clang-c/ExternC.h + 39 139 1315 include/clang/Sema/SemaLambda.h + ... + 2456 6337 72088 include/clang/AST/TypeLoc.h + 2518 9954 84357 include/clang/Format/Format.h + 2562 11342 93946 include/clang/AST/DeclBase.h + 2702 10276 100082 include/clang/Sema/DeclSpec.h + 2922 10503 104051 include/clang/AST/DeclObjC.h + 3103 13260 122386 include/clang/AST/ASTContext.h + 3175 11308 130885 include/clang/Parse/Parser.h + 3283 12371 124927 include/clang/AST/DeclTemplate.h + 3495 9816 126411 include/clang/AST/RecursiveASTVisitor.h + 3594 12701 114449 include/clang/AST/Stmt.h + 3981 16688 151945 include/clang/AST/DeclCXX.h + 4525 19376 170110 include/clang/AST/Decl.h + 4599 18407 181669 include/clang/AST/StmtOpenMP.h + 4840 18045 175567 include/clang/AST/ExprCXX.h + 6009 25804 230882 include/clang/AST/Expr.h + 6663 25974 244789 include/clang/AST/OpenMPClause.h + 6782 28711 220435 include/clang-c/Index.h + 7107 28644 251058 include/clang/AST/Type.h + 7108 25250 212553 include/clang/ASTMatchers/ASTMatchers.h + 12190 48469 560994 include/clang/Sema/Sema.h + 217079 840657 7819915 total +``` + +- Semaだけ1万2千行!!!!! + +### lib/CodeGen/CGExprScalar.cpp + +```cpp +/// Emit the computation of the specified expression of scalar type, ignoring +/// the result. +Value *CodeGenFunction::EmitScalarExpr(const Expr *E, bool IgnoreResultAssign) { + assert(E && hasScalarEvaluationKind(E->getType()) && + "Invalid scalar expression to emit"); + + return ScalarExprEmitter(*this, IgnoreResultAssign) + .Visit(const_cast<Expr *>(E)); +} +``` + +- Expressionを受け取って、これからLLVM IRを生成する + - Eはなんかが入ってそう + +``` +p E->getType() +(gdb) { Value = { Value = 2415319184 }} +``` + +- なんかのポインタ? + +`ScalarExprEmitter` +- Exprを付けとって、それをたどっていく +- `.Visit`はvisitor patternっぽい + +### C++ の( ...) + +...はthree dot operatorとかいうらしい + +https://stackoverflow.com/questions/23485643/understanding-the-dots-in-variadic-template-function + +## 午後 + +直前のvisitor パターンがなんであるかを見に行きます + +### clang::CodeGen::CodeGenFunction::EmitScalarExpr + +`b clang::CodeGen::CodeGenFunction::EmitScalarExpr` してbreak pointをかけておく + +`lib/CodeGen/CGExprScalar.cpp`の中っぽい + +```cpp + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + Value *Visit(Expr *E) { + ApplyDebugLocation DL(CGF, E); + return StmtVisitor<ScalarExprEmitter, Value*>::Visit(E); + } + + Value *VisitStmt(Stmt *S) { +``` + +- nする + +### include/clang/AST/StmtVisitor.h + +```cpp +namespace clang { +/// StmtVisitorBase - This class implements a simple visitor for Stmt +/// subclasses. Since Expr derives from Stmt, this also includes support for +/// visiting Exprs. +template<template <typename> class Ptr, typename ImplClass, typename RetTy=void, + class... ParamTys> +class StmtVisitorBase { +public: +#define PTR(CLASS) typename Ptr<CLASS>::type +#define DISPATCH(NAME, CLASS) \ + return static_cast<ImplClass*>(this)->Visit ## NAME( \ + static_cast<PTR(CLASS)>(S), std::forward<ParamTys>(P)...) + + + + RetTy Visit(PTR(Stmt) S, ParamTys... P) { + // If we have a binary expr, dispatch to the subcode of the binop. A smart + // optimizer (e.g. LLVM) will fold this comparison into the switch stmt + // below. + if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) { + switch (BinOp->getOpcode()) { + case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); + case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); + case BO_Mul: DISPATCH(BinMul, BinaryOperator); + case BO_Div: DISPATCH(BinDiv, BinaryOperator); + case BO_Rem: DISPATCH(BinRem, BinaryOperator); + case BO_Add: DISPATCH(BinAdd, BinaryOperator); + case BO_Sub: DISPATCH(BinSub, BinaryOperator); +``` + +- DISPATCHみたいなマクロ... + - 型によって呼ばれるVisitorが異なりそう + +実際に飛ばされたのはこれ(105行目) + +```cpp + // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + switch (S->getStmtClass()) { + default: llvm_unreachable("Unknown stmt kind!"); +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS); +#include "clang/AST/StmtNodes.inc" + } + ``` + + - StmtNodes.incはclang/include/clang/Basic/StmtNodes.tdを元にビルド時に生成される + - build側のディレクトリをfindして見つける + + + ### 実際に呼ばれた箇所 + + ```cpp + return VisitCastExpr(E); + } + Value *VisitCastExpr(CastExpr *E); + + Value *VisitCallExpr(const CallExpr *E) { + if (E->getCallReturnType(CGF.getContext())->isReferenceType()) + return EmitLoadOfLValue(E); + + Value *V = CGF.EmitCallExpr(E).getScalarVal(); + + EmitLValueAlignmentAssumption(E, V); + return V; + } + ``` + + - Visitorパターンなので、`VisitCallExpr`を実装すれば、マクロで解決されてこれが呼び出される + - ここでコード生成が行われている + - コード生成している箇所を見るには`VisitCall*`をみること!!! + +### back trace + +```log +#0 (anonymous namespace)::ScalarExprEmitter::VisitCallExpr (this=0x7fffffff76e0, E=0xe6bdc10) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:580 +#1 0x00000000039f9b02 in clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit (this=0x7fffffff76e0, S=0xe6bdc10) at tools/clang/include/clang/AST/StmtNodes.inc:801 +#2 0x00000000039e1bf2 in (anonymous namespace)::ScalarExprEmitter::Visit (this=0x7fffffff76e0, E=0xe6bdc10) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:426 +#3 0x00000000039f71c2 in clang::CodeGen::CodeGenFunction::EmitScalarExpr (this=0x7fffffff7bc0, E=0xe6bdc10, + IgnoreResultAssign=true) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:4572 +#4 0x00000000039955ec in clang::CodeGen::CodeGenFunction::EmitAnyExpr (this=0x7fffffff7bc0, E=0xe6bdc10, + aggSlot=..., ignoreResult=true) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:199 +#5 0x000000000399556b in clang::CodeGen::CodeGenFunction::EmitIgnoredExpr (this=0x7fffffff7bc0, E=0xe6bdc10) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:184 +#6 0x00000000035f731d in clang::CodeGen::CodeGenFunction::EmitStmt (this=0x7fffffff7bc0, S=0xe6bdc10, Attrs=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGStmt.cpp:113 +#7 0x00000000035f8398 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope (this=0x7fffffff7bc0, + S=..., GetLast=false, AggSlot=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGStmt.cpp:444 +#8 0x000000000367eddc in clang::CodeGen::CodeGenFunction::EmitFunctionBody (this=0x7fffffff7bc0, Body=0xe6bdc38) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenFunction.cpp:1170 +#9 0x000000000367f976 in clang::CodeGen::CodeGenFunction::GenerateCode (this=0x7fffffff7bc0, GD=..., + Fn=0xe69af68, FnInfo=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenFunction.cpp:1335 +#10 0x00000000036a5adc in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition (this=0xe65b7a0, GD=..., + GV=0xe69af68) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:4484 +#11 0x000000000369f182 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition (this=0xe65b7a0, GD=..., GV=0x0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:2874 +#12 0x000000000369de1e in clang::CodeGen::CodeGenModule::EmitGlobal (this=0xe65b7a0, GD=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:2577 +#13 0x00000000036a96e6 in clang::CodeGen::CodeGenModule::EmitTopLevelDecl (this=0xe65b7a0, D=0xe6bda30) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenModule.cpp:5289 +#14 0x000000000457a4f6 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl (this=0xe65ad70, DG=...) +---Type <return> to continue, or q <return> to quit--- + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/ModuleBuilder.cpp:170 +#15 0x0000000004574165 in clang::BackendConsumer::HandleTopLevelDecl (this=0xe65aba0, D=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenAction.cpp:214 +#16 0x0000000005970f01 in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Parse/ParseAST.cpp:162 +#17 0x0000000003ce5a91 in clang::ASTFrontendAction::ExecuteAction (this=0xe63c1a0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:1047 +#18 0x0000000004572303 in clang::CodeGenAction::ExecuteAction (this=0xe63c1a0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CodeGenAction.cpp:1176 +#19 0x0000000003ce53fd in clang::FrontendAction::Execute (this=0xe63c1a0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/FrontendAction.cpp:940 +#20 0x0000000003c7db31 in clang::CompilerInstance::ExecuteAction (this=0xe6381d0, Act=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/Frontend/CompilerInstance.cpp:969 +#21 0x0000000003e40b1d in clang::ExecuteCompilerInvocation (Clang=0xe6381d0) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:292 +#22 0x0000000000a586fb in cc1_main (Argv=..., + Argv0=0x7fffffffde32 "/mnt/dalmore-home/one/build/build_llvm_origin/bin/clang-11", + MainAddr=0xa4ce20 <GetExecutablePath[abi:cxx11](char const*, bool)>) + at /mnt/dalmore-home/one/src/LLVM_original/clang/tools/driver/cc1_main.cpp:240 +#23 0x0000000000a4e4c9 in ExecuteCC1Tool (ArgV=...) + at /mnt/dalmore-home/one/src/LLVM_original/clang/tools/driver/driver.cpp:328 +#24 0x0000000000a4ebc3 in main (argc_=53, argv_=0x7fffffffd9c8) +at /mnt/dalmore-home/one/src/LLVM_original/clang/tools/driver/driver.cpp:402 +``` + +### 中身の確認 + +``` + if (E->getCallReturnType(CGF.getContext())->isReferenceType()) +``` + +- だいたいこれはfalseになるはず +- stepして中身をおっていく + - smart pointer関連の処理がわりと続く + + +- そのあと北場所 + +```cpp +//===--------------------------------------------------------------------===// +// Expression Emission +//===--------------------------------------------------------------------===// + +RValue CodeGenFunction::EmitCallExpr(const CallExpr *E, + ReturnValueSlot ReturnValue) { + // Builtins never have block type. + if (E->getCallee()->getType()->isBlockPointerType()) + return EmitBlockCallExpr(E, ReturnValue); + + if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E)) + return EmitCXXMemberCallExpr(CE, ReturnValue); + + if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E)) + return EmitCUDAKernelCallExpr(CE, ReturnValue); + + if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E)) + if (const CXXMethodDecl *MD = + dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl())) + return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue); + + CGCallee callee = EmitCallee(E->getCallee()); + + if (callee.isBuiltin()) { + return EmitBuiltinExpr(callee.getBuiltinDecl(), callee.getBuiltinID(), + E, ReturnValue); + } + +``` +- 呼び出す関数を計算しないと行けない可能性があるのでEmitCalle + - Calleは呼び出す方 + +``` + CGCallee callee = EmitCallee(E->getCallee()); +``` + +- callするfunctionはcalleeが戻ってくるっぽい + +```cpp +RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee, + const CallExpr *E, ReturnValueSlot ReturnValue, + llvm::Value *Chain) { + // Get the actual function type. The callee type will always be a pointer to + // function type or a block pointer type. + assert(CalleeType->isFunctionPointerType() && + "Call must have function pointer type!"); + + const Decl *TargetDecl = + OrigCallee.getAbstractInfo().getCalleeDecl().getDecl(); + + CalleeType = getContext().getCanonicalType(CalleeType); + + auto PointeeType = cast<PointerType>(CalleeType)->getPointeeType(); + + CGCallee Callee = OrigCallee; + + if (getLangOpts().CPlusPlus && SanOpts.has(SanitizerKind::Function) && + (!TargetDecl || !isa<FunctionDecl>(TargetDecl))) { + if (llvm::Constant *PrefixSig = + CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { + SanitizerScope SanScope(this); + // Remove any (C++17) exception specifications, to allow calling e.g. a + // noexcept function through a non-noexcept pointer. + auto ProtoTy = + ``` + + + ### back trace + + ```log + #0 clang::CodeGen::CodeGenFunction::EmitCall (this=0x7fffffff7bc0, CalleeType=..., OrigCallee=..., E=0xe6bdc10, + ReturnValue=..., Chain=0x0) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:4881 +#1 0x00000000039ae87e in clang::CodeGen::CodeGenFunction::EmitCallExpr (this=0x7fffffff7bc0, E=0xe6bdc10, + ReturnValue=...) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:4630 +#2 0x00000000039e282e in (anonymous namespace)::ScalarExprEmitter::VisitCallExpr (this=0x7fffffff76e0, + E=0xe6bdc10) at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExprScalar.cpp:583 +#3 0x00000000039f9b02 in clang::StmtVisitorBase<std::add_pointer, (anonymous namespace)::ScalarExprEmitter, llvm::Value*>::Visit (this=0x7fffffff76e0, S=0xe6bdc10) at tools/clang/include/clang/AST/StmtNodes.inc:801 +``` + +### emi call + +`./clang/lib/CodeGen/CodeGenFunction.h`っぽい + +```cpp + //===--------------------------------------------------------------------===// + // Scalar Expression Emission + //===--------------------------------------------------------------------===// + /// EmitCall - Generate a call of the given function, expecting the given + /// result type, and using the given argument list which specifies both the + /// LLVM arguments and the types they were derived from. + RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, + ReturnValueSlot ReturnValue, const CallArgList &Args, + llvm::CallBase **callOrInvoke, SourceLocation Loc); + RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, + ReturnValueSlot ReturnValue, const CallArgList &Args, + llvm::CallBase **callOrInvoke = nullptr) { + return EmitCall(CallInfo, Callee, ReturnValue, Args, callOrInvoke, + SourceLocation()); + } + RValue EmitCall(QualType FnType, const CGCallee &Callee, const CallExpr *E, + ReturnValueSlot ReturnValue, llvm::Value *Chain = nullptr); + RValue EmitCallExpr(const CallExpr *E, + ``` + +### EmitCall + +- ` ./clang/lib/CodeGen/CGCall.cpp`を見ていく + +```cpp +/// Helper data structure to emit `AllocAlignAttr`. +class AllocAlignAttrEmitter final + : public AbstractAssumeAlignedAttrEmitter<AllocAlignAttr> { +public: + AllocAlignAttrEmitter(CodeGenFunction &CGF_, const Decl *FuncDecl, + const CallArgList &CallArgs) + : AbstractAssumeAlignedAttrEmitter(CGF_, FuncDecl) { + if (!AA) + return; + // Alignment may or may not be a constant, and that is okay. + Alignment = CallArgs[AA->getParamIndex().getLLVMIndex()] + .getRValue(CGF) + .getScalarVal(); + } +}; + +} // namespace + +RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, + const CGCallee &Callee, + ReturnValueSlot ReturnValue, + const CallArgList &CallArgs, + llvm::CallBase **callOrInvoke, + SourceLocation Loc) { + // FIXME: We no longer need the types from CallArgs; lift up and simplify. + + assert(Callee.isOrdinary() || Callee.isVirtual()); + + // Handle struct-return functions by passing a pointer to the + // location that we would like to return into. + QualType RetTy = CallInfo.getReturnType(); + const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); + + llvm::FunctionType *IRFuncTy = getTypes().GetFunctionType(CallInfo); + + const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl().getDecl(); + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) + // We can only guarantee that a function is called from the correct + + ``` + +```cpp + unsigned FirstIRArg, NumIRArgs; + std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); + + switch (ArgInfo.getKind()) { + case ABIArgInfo::InAlloca: { + assert(NumIRArgs == 0); + assert(getTarget().getTriple().getArch() == llvm::Triple::x86); + if (I->isAggregate()) { + Address Addr = I->hasLValue() + ? I->getKnownLValue().getAddress(*this) + : I->getKnownRValue().getAggregateAddress(); + llvm::Instruction *Placeholder = + cast<llvm::Instruction>(Addr.getPointer()); + + if (!ArgInfo.getInAllocaIndirect()) { + // Replace the placeholder with the appropriate argument slot GEP. + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(Placeholder); + Addr = Builder.CreateStructGEP(ArgMemory, + ArgInfo.getInAllocaFieldIndex()); + Builder.restoreIP(IP); + } else { + // For indirect things such as overaligned structs, replace the + // placeholder with a regular aggregate temporary alloca. Store the + // address of this alloca into the struct. + Addr = CreateMemTemp(info_it->type, "inalloca.indirect.tmp"); + Address ArgSlot = Builder.CreateStructGEP( + ArgMemory, ArgInfo.getInAllocaFieldIndex()); + Builder.CreateStore(Addr.getPointer(), ArgSlot); + } + deferPlaceholderReplacement(Placeholder, Addr.getPointer()); + } else if (ArgInfo.getInAllocaIndirect()) { + // Make a temporary alloca and store the address of it into the argument + // struct. + Address Addr = CreateMemTempWithoutCast( + I->Ty, getContext().getTypeAlignInChars(I->Ty), + "indirect-arg-temp"); + I->copyInto(*this, Addr); + Address ArgSlot = +``` + + +なんかLifeTimeSizeとか出てきた + +```cpp + if (NeedCopy) { + // Create an aligned temporary, and copy to it. + Address AI = CreateMemTempWithoutCast( + I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); + IRCallArgs[FirstIRArg] = AI.getPointer(); + + // Emit lifetime markers for the temporary alloca. + uint64_t ByvalTempElementSize = + CGM.getDataLayout().getTypeAllocSize(AI.getElementType()); + llvm::Value *LifetimeSize = + EmitLifetimeStart(ByvalTempElementSize, AI.getPointer()); + + // Add cleanup code to emit the end lifetime marker after the call. + if (LifetimeSize) // In case we disabled lifetime markers. + CallLifetimeEndAfterCall.emplace_back(AI, LifetimeSize); + + // Generate the copy. + I->copyInto(*this, AI); + } else { + // Skip the extra memcpy call. + auto *T = V->getType()->getPointerElementType()->getPointerTo( + CGM.getDataLayout().getAllocaAddrSpace()); + IRCallArgs[FirstIRArg] = getTargetHooks().performAddrSpaceCast( + *this, V, LangAS::Default, CGM.getASTAllocaAddressSpace(), T, + true); + } + } + ``` + + このfunction call時のclean upなLifeTime操作 + - このルーチンが有効化されていると、TailCall最適化できない + + ```cpp + 4543 // If we made a temporary, be sure to clean up after ourselves. Note that we +4544 // can't depend on being inside of an ExprWithCleanups, so we need to manually +4545 // pop this cleanup later on. Being eager about this is OK, since this +4546 // temporary is 'invisible' outside of the callee. +4547 if (UnusedReturnSizePtr) +4548 pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, SRetAlloca, +4549 UnusedReturnSizePtr); +4550 +4551 llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); +4552 +4553 SmallVector<llvm::OperandBundleDef, 1> BundleList = +4554 getBundlesForFunclet(CalleePtr); +4555 +4556 if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) +4557 if (FD->usesFPIntrin()) +4558 // All calls within a strictfp function are marked strictfp +4559 Attrs = +4560 Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, +4561 llvm::Attribute::StrictFP); +4562 +4563 AssumeAlignedAttrEmitter AssumeAlignedAttrEmitter(*this, TargetDecl); +4564 Attrs = AssumeAlignedAttrEmitter.TryEmitAsCallSiteAttribute(Attrs); +4565 +4566 AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs); +4567 Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs); + ``` + +このあたりも関係してそう + + +```cpp +4789 } +4790 +4791 // Explicitly call CallLifetimeEnd::Emit just to re-use the code even though +4792 // we can't use the full cleanup mechanism. +4793 for (CallLifetimeEnd &LifetimeEnd : CallLifetimeEndAfterCall) +4794 LifetimeEnd.Emit(*this, /*Flags=*/{}); +4795 +4796 return Ret; +4797 } +``` + +Tail Call関連 + +```cpp +4619 // Suppress tail calls if requested. +4620 if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { +4621 if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) +(gdb) l +4622 Call->setTailCallKind(llvm::CallInst::TCK_NoTail); +4623 } +``` + + +### 使ったbreak point + +```log +Num Type Disp Enb Address What +3 breakpoint keep y 0x00000000039b0d76 in clang::CodeGen::CodeGenFunction::EmitCall(clang::QualType, clang::CodeGen::CGCallee const&, clang::CallExpr const*, clang::CodeGen::ReturnValueSlot, llvm::Value*) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGExpr.cpp:5047 + breakpoint already hit 1 time +4 breakpoint keep y 0x000000000393619f in clang::CodeGen::CodeGenFunction::EmitCall(clang::CodeGen::CGFunctionInfo const&, clang::CodeGen::CGCallee const&, clang::CodeGen::ReturnValueSlot, clang::CodeGen::CallArgList const&, llvm::CallBase**, clang::SourceLocation) + at /mnt/dalmore-home/one/src/LLVM_original/clang/lib/CodeGen/CGCall.cpp:4547 +breakpoint already hit 1 time +``` + + +### 作ってそう? + +- `CreateCall`とか`createBasicBlock`とかしている + +```cpp +4566 AllocAlignAttrEmitter AllocAlignAttrEmitter(*this, TargetDecl, CallArgs); +4567 Attrs = AllocAlignAttrEmitter.TryEmitAsCallSiteAttribute(Attrs); +4568 +4569 // Emit the actual call/invoke instruction. +4570 llvm::CallBase *CI; +4571 if (!InvokeDest) { +4572 CI = Builder.CreateCall(IRFuncTy, CalleePtr, IRCallArgs, BundleList); +4573 } else { +4574 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); +4575 CI = Builder.CreateInvoke(IRFuncTy, CalleePtr, Cont, InvokeDest, IRCallArgs, +4576 BundleList); +4577 EmitBlock(Cont); +4578 } +4579 if (callOrInvoke) +4580 *callOrInvoke = CI; +4 +``` + +### コード生成文 + +- `return Insert(CI, Name)`で呼び出しているのが生成してそう +- 多分` llvm/include/llvm/IR/IRBuilder.h`で呼ばれているもの + +``` +llvm::IRBuilder<llvm::ConstantFolder, clang::CodeGen::CGBuilderInserter>::Insert<llvm::CallInst> ( + this=0x7fffffff7ca8, I=0xe6c2ee0, Name=...) + at /mnt/dalmore-home/one/src/LLVM_original/llvm/include/llvm/IR/IRBuilder.h:993 +993 this->InsertHelper(I, Name, BB, InsertPt); +(gdb) l +988 const T &getFolder() { return Folder; } +989 +990 /// Insert and return the specified instruction. +991 template<typename InstTy> +992 InstTy *Insert(InstTy *I, const Twine &Name = "") const { +993 this->InsertHelper(I, Name, BB, InsertPt); +994 this->SetInstDebugLocation(I); +995 return I; +996 } +``` +ここの`llvm::IRBuilder`でコード生成されていそう +- このInsertHelperが何をしているかによりそう +- これ自体はtemplateなので109個のInsertが存在している + - instruction typeの数だけ + - call/add/条件分岐, 代入とか... + + +
--- a/Events/srcread/compiler/rust-2020.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Events/srcread/compiler/rust-2020.md Wed Dec 16 15:11:16 2020 +0900 @@ -8,16 +8,709 @@ - コンパイル時に関数に型名を入れるので,nmで関数名を取り出す必要がある - `$nm /rust/rust/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-ce53599820ba664c.so | grep parse_expr` -[* compilerソースながめる] - https://github.com/rust-lang/rust/tree/master/compiler - メイン部分 - https://github.com/rust-lang/rust/tree/master/compiler/rustc_driver - クレート寄せ集めっぽい - run_compiler() - || lambda式 - https://doc.rust-lang.org/rust-by-example/fn/closures.html#:~:text=Closures%20in%20Rust%2C%20also%20called,for%20on%20the%20fly%20usage - FnOnce - `rustc_interface::interface::create_compiler_and_run::hd06f00e0a4bf9137 at interface.rs:190:5` +# compilerソースながめる +- https://github.com/rust-lang/rust/tree/master/compiler + - メイン部分 + - https://github.com/rust-lang/rust/tree/master/compiler/rustc_driver + - クレート寄せ集めっぽい + - `run_compiler()` + - `||` lambda式 + - https://doc.rust-lang.org/rust-by-example/fn/closures.html#:~:text=Closures%20in%20Rust%2C%20also%20called,for%20on%20the%20fly%20usage + - `FnOnce` + - `rustc_interface::interface::create_compiler_and_run::hd06f00e0a4bf9137 at interface.rs:190:5` + +## backtrace + +```txt +* thread #2, name = 'rustc', stop reason = breakpoint 2.1 + * frame #0: 0x00007ffff41919fb librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_catch_underscore::h43010b29c3bbcd9b [inlined] rustc_parse::parser::Parser::with_res::hd719d9af60fa6475 at mod.rs:1025:19 + frame #1: 0x00007ffff41919fb librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_catch_underscore::h43010b29c3bbcd9b [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_res::h5928421b15332eef at expr.rs:127 + frame #2: 0x00007ffff41919fb librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_catch_underscore::h43010b29c3bbcd9b [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr::h95dab2ee425c859e at expr.rs:91 + frame #3: 0x00007ffff41919fb librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_catch_underscore::h43010b29c3bbcd9b at expr.rs:99 + frame #4: 0x00007ffff41ecc6f librustc_driver-ce53599820ba664c.so`rustc_parse::parser::Parser::parse_seq_to_before_tokens::h4a23b282ffc32d65 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_paren_expr_seq::_$u7b$$u7b$closure$u7d$$u7d$::h9e07a7a5b55bc601 at expr.rs:117:40 + frame #5: 0x00007ffff41ecc67 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::Parser::parse_seq_to_before_tokens::h4a23b282ffc32d65 at mod.rs:721 + frame #6: 0x00007ffff41f32c1 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::Parser::parse_delim_comma_seq::h18ef14e316c0bef4 [inlined] rustc_parse::parser::Parser::parse_seq_to_before_end::h12b9e502ad9050a9 at mod.rs:737:9 + frame #7: 0x00007ffff41f3293 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::Parser::parse_delim_comma_seq::h18ef14e316c0bef4 [inlined] rustc_parse::parser::Parser::parse_seq_to_end::hc7808e14c4dd5e83 at mod.rs:749 + frame #8: 0x00007ffff41f3293 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::Parser::parse_delim_comma_seq::h18ef14e316c0bef4 [inlined] rustc_parse::parser::Parser::parse_unspanned_seq::ha6405b33d8be6d2b at mod.rs:767 + frame #9: 0x00007ffff41f3286 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::Parser::parse_delim_comma_seq::h18ef14e316c0bef4 at mod.rs:775 + frame #10: 0x00007ffff419881a librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_dot_or_call_expr_with_::h2fe7120292b29822 [inlined] rustc_parse::parser::Parser::parse_paren_comma_seq::h2172e4858f2fe322 at mod.rs:787:9 + frame #11: 0x00007ffff419880a librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_dot_or_call_expr_with_::h2fe7120292b29822 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_paren_expr_seq::h9867ea0ce8ef4b27 at expr.rs:117 + frame #12: 0x00007ffff419880a librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_dot_or_call_expr_with_::h2fe7120292b29822 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_fn_call_expr::hd0da9e0f8e9441b5 at expr.rs:961 + frame #13: 0x00007ffff419880a librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_dot_or_call_expr_with_::h2fe7120292b29822 at expr.rs:805 + frame #14: 0x00007ffff4197fe6 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_dot_or_call_expr_with::h34aaddda78ce4242 at expr.rs:780:9 + frame #15: 0x00007ffff41dba15 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_path_start::_$u7b$$u7b$closure$u7d$$u7d$::h7e3aae8192395074 at stmt.rs:90:24 + frame #16: 0x00007ffff41db9d6 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::Parser::with_res::h54245f39af292c7a at mod.rs:1027 + frame #17: 0x00007ffff41db9d6 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_path_start::hf728862f2bc639f1 at stmt.rs:89 + frame #18: 0x00007ffff41db9d6 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 at stmt.rs:56 + frame #19: 0x00007ffff41dedbc librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_full_stmt::he7a0d36b0005f620 at stmt.rs:374:30 + frame #20: 0x00007ffff41de908 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_block_tail::h06bebcce30737a4d at stmt.rs:346:30 + frame #21: 0x00007ffff41dde05 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_block_common::h8e2ad585959efd9f at stmt.rs:328:13 + frame #22: 0x00007ffff41a65ce librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_block_expr::h9f26ea288236c2f2 at expr.rs:1564:34 + frame #23: 0x00007ffff419be4c librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_bottom_expr::hf1ab8a77513b78e0 at expr.rs:1035:13 + frame #24: 0x00007ffff41957ea librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_prefix_expr::_$u7b$$u7b$closure$u7d$$u7d$::ha8c245b3e504f09c [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_dot_or_call_expr::h6aac50c8864667eb at expr.rs:766:20 + frame #25: 0x00007ffff41957dd librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_prefix_expr::_$u7b$$u7b$closure$u7d$$u7d$::ha8c245b3e504f09c at expr.rs:487 + frame #26: 0x00007ffff4194b71 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_prefix_expr::h8ca59e1bc7493784 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::maybe_collect_tokens::hb7156b7dc9c2c50a at expr.rs:1137:13 + frame #27: 0x00007ffff419497d librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_prefix_expr::h8ca59e1bc7493784 at expr.rs:474 + frame #28: 0x00007ffff4191e3b librustc_driver-ce53599820ba664c.so`rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_assoc_expr_with::h022381be78dbbd0d at expr.rs:155:17 + frame #29: 0x00007ffff41db216 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_assoc_expr::ha4c0ea088735151f at expr.rs:136:9 + frame #30: 0x00007ffff41db206 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_res::_$u7b$$u7b$closure$u7d$$u7d$::hbc4a592d9e915c57 at expr.rs:127 + frame #31: 0x00007ffff41db206 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::Parser::with_res::hd719d9af60fa6475 at mod.rs:1027 + frame #32: 0x00007ffff41db1f5 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 [inlined] rustc_parse::parser::expr::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_expr_res::h5928421b15332eef at expr.rs:127 + frame #33: 0x00007ffff41db1f5 librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_stmt_without_recovery::h9aac38d541d3ee33 at stmt.rs:66 + frame #34: 0x00007ffff41dedbc librustc_driver-ce53599820ba664c.so`rustc_parse::parser::stmt::_$LT$impl$u20$rustc_parse..parser..Parser$GT$::parse_full_stmt::he7a0d36b0005f620 at stmt.rs:374:30 + frame #35: 0x00007ffff400f96a librustc_driver-ce53599820ba664c.so`rustc_expand::expand::parse_ast_fragment::h88005342af03b165 at expand.rs:918:37 + frame #36: 0x00007ffff3fdc20b librustc_driver-ce53599820ba664c.so`rustc_expand::mbe::macro_rules::ParserAnyMacro::make::ha84ea912487ab58f at macro_rules.rs:143:30 + frame #37: 0x00007ffff3fe648a librustc_driver-ce53599820ba664c.so`rustc_expand::expand::_$LT$impl$u20$rustc_expand..base..MacResult$u20$for$u20$rustc_expand..mbe..macro_rules..ParserAnyMacro$GT$::make_stmts::hd01eb759776eb308 at expand.rs:141:22 + frame #38: 0x00007ffff401a221 librustc_driver-ce53599820ba664c.so`rustc_expand::expand::AstFragmentKind::make_from::h312efd385e333563 at expand.rs:74:49 + frame #39: 0x00007ffff400ae91 librustc_driver-ce53599820ba664c.so`rustc_expand::expand::MacroExpander::fully_expand_fragment::h21e2cb708bcabf6b [inlined] rustc_expand::expand::MacroExpander::expand_invoc::heb4508fe5dc7f59d at expand.rs:704:56 + frame #40: 0x00007ffff400ad35 librustc_driver-ce53599820ba664c.so`rustc_expand::expand::MacroExpander::fully_expand_fragment::h21e2cb708bcabf6b at expand.rs:497 + frame #41: 0x00007ffff4009e33 librustc_driver-ce53599820ba664c.so`rustc_expand::expand::MacroExpander::expand_crate::hdcbcbdbd5ffd9b81 at expand.rs:390:15 + frame #42: 0x00007fffef8b3f0f librustc_driver-ce53599820ba664c.so`rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::h8f8d9b170ba156cc [inlined] rustc_interface::passes::configure_and_expand_inner::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h89914587490008fa at passes.rs:301:50 + frame #43: 0x00007fffef8b3e7c librustc_driver-ce53599820ba664c.so`rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::h8f8d9b170ba156cc [inlined] rustc_data_structures::profiling::VerboseTimingGuard::run::h1de2d120ce6be700 at profiling.rs:570 + frame #44: 0x00007fffef8b3dd1 librustc_driver-ce53599820ba664c.so`rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::h8f8d9b170ba156cc [inlined] rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::hb61a37b80af8edf9 at utils.rs:9 + frame #45: 0x00007fffef8b3db7 librustc_driver-ce53599820ba664c.so`rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::h8f8d9b170ba156cc [inlined] rustc_interface::passes::configure_and_expand_inner::_$u7b$$u7b$closure$u7d$$u7d$::h5baa5dc2d3b7d5ab at passes.rs:301 + frame #46: 0x00007fffef8b3bba librustc_driver-ce53599820ba664c.so`rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::h8f8d9b170ba156cc [inlined] rustc_data_structures::profiling::VerboseTimingGuard::run::hac59221ea2999e1f at profiling.rs:570 + frame #47: 0x00007fffef8b3b4c librustc_driver-ce53599820ba664c.so`rustc_session::utils::_$LT$impl$u20$rustc_session..session..Session$GT$::time::h8f8d9b170ba156cc at utils.rs:9 + frame #48: 0x00007fffef916fe3 librustc_driver-ce53599820ba664c.so`rustc_interface::passes::configure_and_expand_inner::h6195e087ea984a0c at passes.rs:253:13 + frame #49: 0x00007fffef8cade9 librustc_driver-ce53599820ba664c.so`rustc_interface::passes::configure_and_expand::_$u7b$$u7b$closure$u7d$$u7d$::h563ae5b7751e4716 at passes.rs:117:19 + frame #50: 0x00007fffef8b758f librustc_driver-ce53599820ba664c.so`rustc_data_structures::box_region::PinnedGenerator$LT$I$C$A$C$R$GT$::new::hdf5326c16352d0b3 [inlined] alloc::boxed::_$LT$impl$u20$core..ops..generator..Generator$LT$R$GT$$u20$for$u20$core..pin..Pin$LT$alloc..boxed..Box$LT$G$C$A$GT$$GT$$GT$::resume::h6f486135a6884478 at boxed.rs:1434:9 + frame #51: 0x00007fffef8b7574 librustc_driver-ce53599820ba664c.so`rustc_data_structures::box_region::PinnedGenerator$LT$I$C$A$C$R$GT$::new::hdf5326c16352d0b3 at box_region.rs:44 + frame #52: 0x00007fffef915c7d librustc_driver-ce53599820ba664c.so`rustc_interface::passes::configure_and_expand::h744723d4f46c935b [inlined] rustc_interface::passes::BoxedResolver::new::hd2be0aaa3ed2ea85 at box_region.rs:101:41 + frame #53: 0x00007fffef915bd6 librustc_driver-ce53599820ba664c.so`rustc_interface::passes::configure_and_expand::h744723d4f46c935b at passes.rs:113 + frame #54: 0x00007fffef815d76 librustc_driver-ce53599820ba664c.so`rustc_interface::queries::Queries::expansion::h7ac3f5ba274aafbd [inlined] rustc_interface::queries::Queries::expansion::_$u7b$$u7b$closure$u7d$$u7d$::ha21385b576de40f8 at queries.rs:178:13 + frame #55: 0x00007fffef81579a librustc_driver-ce53599820ba664c.so`rustc_interface::queries::Queries::expansion::h7ac3f5ba274aafbd [inlined] rustc_interface::queries::Query$LT$T$GT$::compute::ha966bf8cd6645071 at queries.rs:35 + frame #56: 0x00007fffef81579a librustc_driver-ce53599820ba664c.so`rustc_interface::queries::Queries::expansion::h7ac3f5ba274aafbd at queries.rs:174 + frame #57: 0x00007fffef58cb7b librustc_driver-ce53599820ba664c.so`rustc_interface::queries::_$LT$impl$u20$rustc_interface..interface..Compiler$GT$::enter::h745584ef9a1d214e [inlined] rustc_driver::run_compiler::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::hbfae80f2f337da53 at lib.rs:388:13 + frame #58: 0x00007fffef58bffb librustc_driver-ce53599820ba664c.so`rustc_interface::queries::_$LT$impl$u20$rustc_interface..interface..Compiler$GT$::enter::h745584ef9a1d214e at queries.rs:415 + frame #59: 0x00007fffef64d497 librustc_driver-ce53599820ba664c.so`rustc_span::with_source_map::hfa7e85594b278950 [inlined] rustc_driver::run_compiler::_$u7b$$u7b$closure$u7d$$u7d$::h453d29d790e8d9d5 at lib.rs:336:22 + frame #60: 0x00007fffef64d398 librustc_driver-ce53599820ba664c.so`rustc_span::with_source_map::hfa7e85594b278950 [inlined] rustc_interface::interface::create_compiler_and_run::_$u7b$$u7b$closure$u7d$$u7d$::h1d7ed3cb14ac6d8d at interface.rs:196 + frame #61: 0x00007fffef64d36c librustc_driver-ce53599820ba664c.so`rustc_span::with_source_map::hfa7e85594b278950 at lib.rs:764 + frame #62: 0x00007fffef58ef94 librustc_driver-ce53599820ba664c.so`rustc_interface::interface::create_compiler_and_run::hd06f00e0a4bf9137 at interface.rs:190:5 + frame #63: 0x00007fffef56d83f librustc_driver-ce53599820ba664c.so`scoped_tls::ScopedKey$LT$T$GT$::set::h30136cd23222a588 [inlined] rustc_interface::interface::run_compiler::_$u7b$$u7b$closure$u7d$$u7d$::h34c6c3f6e67ddbad at interface.rs:212:12 + frame #64: 0x00007fffef56d823 librustc_driver-ce53599820ba664c.so`scoped_tls::ScopedKey$LT$T$GT$::set::h30136cd23222a588 [inlined] rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h9533cbdf934b5d95 at util.rs:152 + frame #65: 0x00007fffef56d7df librustc_driver-ce53599820ba664c.so`scoped_tls::ScopedKey$LT$T$GT$::set::h30136cd23222a588 at lib.rs:137 + frame #66: 0x00007fffef572e45 librustc_driver-ce53599820ba664c.so`std::sys_common::backtrace::__rust_begin_short_backtrace::h8544078baa633623 [inlined] rustc_span::with_session_globals::h88e1584ec43a0922 at lib.rs:93:5 + frame #67: 0x00007fffef572e0b librustc_driver-ce53599820ba664c.so`std::sys_common::backtrace::__rust_begin_short_backtrace::h8544078baa633623 [inlined] rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::_$u7b$$u7b$closure$u7d$$u7d$::h038aa08aaeb0992f at util.rs:150 + frame #68: 0x00007fffef572ddb librustc_driver-ce53599820ba664c.so`std::sys_common::backtrace::__rust_begin_short_backtrace::h8544078baa633623 [inlined] rustc_interface::util::scoped_thread::_$u7b$$u7b$closure$u7d$$u7d$::h69fdee9624ece786 at util.rs:125 + frame #69: 0x00007fffef572aa4 librustc_driver-ce53599820ba664c.so`std::sys_common::backtrace::__rust_begin_short_backtrace::h8544078baa633623 at backtrace.rs:125 + frame #70: 0x00007fffef5bbd0f librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb [inlined] std::thread::Builder::spawn_unchecked::_$u7b$$u7b$closure$u7d$$u7d$::_$u7b$$u7b$closure$u7d$$u7d$::h9f644a1ef9be9a42 at mod.rs:474:17 + frame #71: 0x00007fffef5bbd0a librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb [inlined] _$LT$std..panic..AssertUnwindSafe$LT$F$GT$$u20$as$u20$core..ops..function..FnOnce$LT$$LP$$RP$$GT$$GT$::call_once::h6d5823d1b946d4ce at panic.rs:322 + frame #72: 0x00007fffef5bbd0a librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb [inlined] std::panicking::try::do_call::h09f3dccec07b571d at panicking.rs:379 + frame #73: 0x00007fffef5bbce9 librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb [inlined] std::panicking::try::h5e56e14357d67e8d at panicking.rs:343 + frame #74: 0x00007fffef5bbce5 librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb [inlined] std::panic::catch_unwind::h0523bb22b3f15298 at panic.rs:396 + frame #75: 0x00007fffef5bbce5 librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb [inlined] std::thread::Builder::spawn_unchecked::_$u7b$$u7b$closure$u7d$$u7d$::h0cd0077403ecd15a at mod.rs:473 + frame #76: 0x00007fffef5bbc72 librustc_driver-ce53599820ba664c.so`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::h7aa107b39bcde6bb at function.rs:227 + frame #77: 0x00007fffeea33488 libstd-1a656201d4f29b26.so`std::sys::unix::thread::Thread::new::thread_start::h755294a5ddedae4e [inlined] _$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::hef4c423c281428f6 at boxed.rs:1318:9 + frame #78: 0x00007fffeea33482 libstd-1a656201d4f29b26.so`std::sys::unix::thread::Thread::new::thread_start::h755294a5ddedae4e [inlined] _$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::h95870f8c37e6568d at boxed.rs:1318 + frame #79: 0x00007fffeea3347b libstd-1a656201d4f29b26.so`std::sys::unix::thread::Thread::new::thread_start::h755294a5ddedae4e at thread.rs:71 + frame #80: 0x00007fffee74f609 libpthread.so.0`start_thread(arg=<unavailable>) at pthread_create.c:477:8 + frame #81: 0x00007fffee891293 libc.so.6`__clone + 67 +``` + +- if let Some(stmt) = this.parse_full_stmt()? {} みたいな構文 + +- macro文 + - https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/index.html + - 例 + - https://doc.rust-lang.org/book/ch19-06-macros.html + - walk_list + - 引数がvisitor, method, list の3つで構成されている. + - 引数3つ以上の場合もある. + - visitorパターン + - デザインパターンを読もう + - https://www.amazon.co.jp/gp/product/B00I8ATHGW/ref=dbs_a_def_rwt_bibl_vppi_i0 + +`walk_list`はこのあたりで使われているらしい + +```shell +$ rg walk_list --files-with-matches +rustc_lint/src/late.rs +rustc_ast_lowering/src/lib.rs +rustc_ast_passes/src/ast_validation.rs +rustc_ast/src/visit.rs +rustc_passes/src/region.rs +rustc_hir/src/intravisit.rs +rustc_save_analysis/src/dump_visitor.rs +rustc_resolve/src/def_collector.rs +rustc_resolve/src/late.rs +rustc_resolve/src/late/lifetimes.rs +``` + +- passes + - https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/index.html + - configure_and_expand() + - https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.configure_and_expand.html + - コンパイラの前処理的な + - harness + - importとかで指定されてるライブラリの読み込み + - etc + + +## lldbのbreak pointをsaveする + +- lldbで + - `br write -f /tmp/rust_breakpoint.txt` + +- jsonが書き込まれる + +```json +[ + { + "Breakpoint": { + "BKPTOptions": { + "AutoContinue": false, + "ConditionText": "", + "EnabledState": true, + "IgnoreCount": 0, + "OneShotState": false + }, + "BKPTResolver": { + "Options": { + "NameMask": [ + 4 + ], + "Offset": 0, + "SkipPrologue": true, + "SymbolNames": [ + "_ZN11rustc_parse6parser4expr45_$LT$impl$u20$rustc_parse..parser..Parser$GT$27parse_expr_catch_underscore17h43010b29c3bbcd9bE" + ] + }, + "Type": "SymbolName" + }, + "Hardware": false, + "SearchFilter": { + "Options": {}, + "Type": "Unconstrained" + } + } + }, + { + "Breakpoint": { + "BKPTOptions": { + "AutoContinue": false, + "ConditionText": "", + "EnabledState": true, + "IgnoreCount": 0, + "OneShotState": false + }, + "BKPTResolver": { + "Options": { + "NameMask": [ + 56 + ], + "Offset": 0, + "SkipPrologue": true, + "SymbolNames": [ + "create_compiler_and_run" + ] + }, + "Type": "SymbolName" + }, + "Hardware": false, + "SearchFilter": { + "Options": {}, + "Type": "Unconstrained" + } + } + }, + { + "Breakpoint": { + "BKPTOptions": { + "AutoContinue": false, + "ConditionText": "", + "EnabledState": true, + "IgnoreCount": 0, + "OneShotState": false + }, + "BKPTResolver": { + "Options": { + "NameMask": [ + 24 + ], + "Offset": 0, + "SkipPrologue": true, + "SymbolNames": [ + "rustc_interface::interface::create_compiler_and_run" + ] + }, + "Type": "SymbolName" + }, + "Hardware": false, + "SearchFilter": { + "Options": {}, + "Type": "Unconstrained" + } + } + } +] +``` + +## `/rust/rust/compiler/rustc` +- src/main.rs + - _F1~_F6という関数がある + - `jmalloc_sys` +- `rustc_driver`というのをrustcにしたかった. + +## lldbがコンパイラのコードをうまく読み込めてないからブレークポイントがうまく立てられない感じ. +- `parse_expr`で止められない! +- `break point`がなんかよくわからないところについてる. + +## もう少しbreakpointの問題を追求する +- 関数のアドレスが実際のものとずれているのが問題 +- シンボルファイルから正しいアドレスを特定できればそのアドレスを使ってブレークポイントを設定できるはず. +- stage1のコンパイラを使ってやる. +- ダイナミックリンキングライブラリ + - `/rust/rust/build/x86_64-unknown-linux-gnu/stage1/bin/../lib/librustc_driver-ce53599820ba664c.so` +## 次はgdbでやってみる +- `b main` , `run` をやるとダイナミックリンクが発動して行き先ができる. +- gdbのほうが若干まし. + +## `rustc_interface/src/callbacks.rs` +- `span_debug()` +- `struct Compiler` + - pub(crate) + - 自分のname spaceにしか公開しない. +- `impl Compiler` (メソッド群) +- `run_compiler()` + - `R + Send` + +## `rustc_interface/src/lib.rs` +- passes + +## `'a`(頭のシングルクオート) +- ライフポインタパラメーター + +## passesの終わったルーチンのところは正しくブレークポイントでとまる. +- rustcはlldbを今はサポートしてないっぽい +- 走らせてからbreakpointを付ければリンクがあるから行ける + + +## これでparse部分は止められた +- `b rustc_interface::passes::parse` +- `b parse_crate_from_file` +- `backtrace` + +## back trace + +- `/rust/rust/compiler/rustc_parse/src/parser/item.rs` + +```text +#0 rustc_parse::parser::item::<impl rustc_parse::parser::Parser>::parse_mod () at compiler/rustc_parse/src/parser/item.rs:58 +#1 0x00007ffff426fd03 in rustc_parse::parser::item::<impl rustc_parse::parser::Parser>::parse_crate_mod () at compiler/rustc_parse/src/parser/item.rs:31 +#2 rustc_parse::parse_crate_from_file () at compiler/rustc_parse/src/lib.rs:56 +#3 0x00007fffef8b37ef in rustc_interface::passes::parse::{{closure}} () at compiler/rustc_interface/src/passes.rs:55 +#4 rustc_data_structures::profiling::VerboseTimingGuard::run () at /rust/rust/compiler/rustc_data_structures/src/profiling.rs:570 +#5 rustc_session::utils::<impl rustc_session::session::Session>::time () at /rust/rust/compiler/rustc_session/src/utils.rs:9 +#6 0x00007fffef9157c1 in rustc_interface::passes::parse () at compiler/rustc_interface/src/passes.rs:54 +#7 0x00007fffef81407d in rustc_interface::queries::Queries::parse::{{closure}} () at compiler/rustc_interface/src/queries.rs:125 +#8 rustc_interface::queries::Query<T>::compute () at compiler/rustc_interface/src/queries.rs:35 +#9 rustc_interface::queries::Queries::parse () at compiler/rustc_interface/src/queries.rs:124 +#10 0x00007fffef58c004 in rustc_driver::run_compiler::{{closure}}::{{closure}} () at compiler/rustc_driver/src/lib.rs:338 +#11 rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter () at /rust/rust/compiler/rustc_interface/src/queries.rs:415 +#12 0x00007fffef64d497 in rustc_driver::run_compiler::{{closure}} () at compiler/rustc_driver/src/lib.rs:336 +#13 rustc_interface::interface::create_compiler_and_run::{{closure}} () at /rust/rust/compiler/rustc_interface/src/interface.rs:196 +#14 rustc_span::with_source_map () at /rust/rust/compiler/rustc_span/src/lib.rs:764 +#15 0x00007fffef58ef94 in rustc_interface::interface::create_compiler_and_run () at /rust/rust/compiler/rustc_interface/src/interface.rs:190 +#16 0x00007fffef56d83f in rustc_interface::interface::run_compiler::{{closure}} () at /rust/rust/compiler/rustc_interface/src/interface.rs:212 +#17 rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::{{closure}}::{{closure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:152 +#18 scoped_tls::ScopedKey<T>::set () at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137 +#19 0x00007fffef572e45 in rustc_span::with_session_globals () at /rust/rust/compiler/rustc_span/src/lib.rs:93 +#20 rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::{{closure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:150 +#21 rustc_interface::util::scoped_thread::{{closure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:125 +#22 std::sys_common::backtrace::__rust_begin_short_backtrace () at /rust/rust/library/std/src/sys_common/backtrace.rs:125 +#23 0x00007fffef5bbd0f in std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}} () at /rust/rust/library/std/src/thread/mod.rs:474 +#24 <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once () at /rust/rust/library/std/src/panic.rs:322 +#25 std::panicking::try::do_call () at /rust/rust/library/std/src/panicking.rs:379 +#26 std::panicking::try () at /rust/rust/library/std/src/panicking.rs:343 +#27 std::panic::catch_unwind () at /rust/rust/library/std/src/panic.rs:396 +#28 std::thread::Builder::spawn_unchecked::{{closure}} () at /rust/rust/library/std/src/thread/mod.rs:473 +#29 core::ops::function::FnOnce::call_once{{vtable-shim}} () at /rust/rust/library/core/src/ops/function.rs:227 +#30 0x00007fffeea33488 in <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () at /rust/rust/library/alloc/src/boxed.rs:1318 +#31 <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () at /rust/rust/library/alloc/src/boxed.rs:1318 +#32 std::sys::unix::thread::Thread::new::thread_start () at library/std/src/sys/unix/thread.rs:71 +#33 0x00007fffee74f609 in start_thread (arg=<optimized out>) at pthread_create.c:477 +#34 0x00007fffee891293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 +``` + +- `compiler/rustc_parse/src/parser/item.rs` +- parse_crate_mod() +- parse_item() +- parse_item_common() + - Selfはキーワード + - https://doc.rust-lang.org/beta/std/keyword.Self.html + - collect_tokenがparse_itemを実行 +- parse_item_kind() + - check_fn_front_matter() + - fnのパーサー(関数判定) + - parse_ident() + - 関数名が入るはず(pで中身見れないのつらいな.) + - fn where構文 + - parse_fn_body() + +``` +(gdb) b parse_fn_ +rustc_parse::parser::expr::<impl rustc_parse::parser::Parser>::parse_fn_block_param +rustc_parse::parser::item::<impl rustc_parse::parser::Parser>::parse_fn_decl +rustc_parse::parser::item::<impl rustc_parse::parser::Parser>::parse_fn_front_matter +rustc_parse::parser::item::<impl rustc_parse::parser::Parser>::parse_fn_params::{{closure}} +(gdb) b parse_fn_body +(gdb) b item.rs:1535 + +Continuing. +[New Thread 0x7fffee3f1700 (LWP 2815433)] +[Switching to Thread 0x7fffee3f1700 (LWP 2815433)] + +Thread 2 "rustc" hit Breakpoint 2, rustc_parse::parser::item::<impl rustc_parse::parser::Parser>::parse_fn_body () + at compiler/rustc_parse/src/parser/item.rs:1535 +1535 let (inner_attrs, body) = if self.eat(&token::Semi) { +(gdb) l +1530 &mut self, +1531 attrs: &mut Vec<Attribute>, +1532 ident: &Ident, +1533 sig_hi: &mut Span, +1534 ) -> PResult<'a, Option<P<Block>>> { +1535 let (inner_attrs, body) = if self.eat(&token::Semi) { +1536 // Include the trailing semicolon in the span of the signature +1537 *sig_hi = self.prev_token.span; +1538 (Vec::new(), None) +1539 } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { +(gdb) p token +$1 = {fn () -> int} 0x7fffee8a8d20 <token> +(gdb) p *token +$2 = {fn () -> int} 0x7fffee8a8d20 <token> +``` + +# 2020/11/29 + +## テストコード + +```rust +fn hugo(i: i64) -> i64 { + return i * 2 + 1; +} + + +fn main() { + let hoge = 1; + + println!("hello {:?}", hugo(hoge*2+1)); +} +``` + +## used with no filenames on the command line, reading from STDIN. +## compiler/rustc_ast +- READMEにあったURL + - https://rustc-dev-guide.rust-lang.org/the-parser.html + - https://rustc-dev-guide.rust-lang.org/macro-expansion.html + - マクロ展開系を書くのは新たに1言語書くのに等しい... + - マクロルールで定義する方法 +- src + - ast.rs + - trait + - https://doc.rust-lang.org/rust-by-example/trait.html + - lifetime + - AngleBracketedArg + - ParamKindOrd + - 関数の中で関数を定義(nested function) + - operator + - Exprのspanの中身をみたい. + - exprが1 + 1だったらspanには1が入っているはず + - precedence + - operationのオーダー + - ExprKind::Binary + +# compiler/rustc_parse/src/parser/expr.rs周辺をトレース +- used with no filenames on the command line, reading from STDIN. +- mk_expr_opでexprのoperationを作るはず +- bump() bump_with() + - https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.bump + - advance the parser by one token + - トークン一つ読み飛ばす...? + - 1 + 1だったら1の次に1を読む感じか. +- op.fixity() + - 結合方向 + - https://cgaebel.github.io/rispc/syntex_syntax/util/parser/enum.Fixity.html +- 計算された値はrhsに入るはず(pで中身が見れないから全部"〜はず"になる...) +- mk_expr_sp() + - 計算の優先順位をみて順番を変える. +- recursive descent + - https://ie.u-ryukyu.ac.jp/~kono/lecture/compiler/c4/lecture.html#content008 + +# コード生成部分をみる +- used with no filenames on the command line, reading from STDIN. +- compiler/rustc_codegen_ssa/README.md + - https://rustc-dev-guide.rust-lang.org/backend/backend-agnostic.html +- LLVM IRを生成する前にMIRを生成する. +- compiler/rustc_mirあたりを読む +- compiler/rustc_middle +- compiler/rustc_hir + - high level IR + - src + - arena.rs + - def.rs + - DefKind + - 定義できるものの種類をまとめた +- rustcで生成後のものは見れる + +```rust +Singularity> rustc -Z unstable-options --pretty expanded,identified /tmp/test.rs + #![feature(prelude_import)] + #![no_std] + #[prelude_import] + use ::std::prelude::v1::*; /* 4 */ + #[macro_use] + extern crate std; /* 10 */ + fn hugo(i /* pat 13 */: i64) -> i64 { + (return (((i /* 20 */) * (2 /* 21 */) /* 22 */) + (1 /* 23 */) /* 24 */) + /* 25 */); + } /* block 18 */ /* 11 */ + + + fn main() { + let hoge /* pat 29 */ = (1 /* 30 */); + + ({ + ((::std::io::_print /* 35 + */)(((::core::fmt::Arguments::new_v1 /* 42 + */)((&([("hello " /* 43 */), ("\n" /* 44 */)] /* 45 */) + /* 46 */), + (&(match (((&((hugo /* 48 + */)((((hoge /* 50 */) * + (2 /* 51 */) /* 52 */) + + (1 /* 53 */) /* 54 */)) + /* 55 */) /* 56 */),) /* 57 */) { + (arg0 /* pat 60 */,) /* pat 59 */ => + ([((::core::fmt::ArgumentV1::new /* 65 + */)((arg0 /* 67 */), + (::core::fmt::Debug::fmt /* 72 + */)) /* 73 */)] /* 74 */), + } /* 75 */) /* 76 */)) /* 77 */)) /* 36 */); + } /* block 31 */ /* 37 */); + } /* block 27 */ /* 26 */ +``` + + +- used with no filenames on the command line, reading from STDIN. +- rustc -Zunpretty=hir-tree /tmp/test.rs + - こっちのほうが正解 + - 実行してみるとめっちゃ長いHIRのコードが見れる. + +## high level からじゃなくて low levelからアプローチしてみる? +- rustc_passesからアプローチをかけるか. +- public/rustc_mir_build/src/build/ + - into.rs + - into_expr() +- codegenっぽいところ + + +``` +#0 <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::CodegenBackend>::codegen_crate () at compiler/rustc_codegen_llvm/src/lib.rs:270 +#1 0x00007fffef91c75b in rustc_interface::passes::start_codegen::{{closure}} () + at compiler/rustc_interface/src/passes.rs:996 +#2 rustc_data_structures::profiling::VerboseTimingGuard::run () + at /rust/rust/compiler/rustc_data_structures/src/profiling.rs:570 +#3 rustc_session::utils::<impl rustc_session::session::Session>::time () + at /rust/rust/compiler/rustc_session/src/utils.rs:9 +#4 rustc_interface::passes::start_codegen () + at compiler/rustc_interface/src/passes.rs:995 +#5 rustc_interface::queries::Queries::ongoing_codegen::{{closure}}::{{closure}} () + at compiler/rustc_interface/src/queries.rs:284 +#6 rustc_interface::passes::QueryContext::enter::{{closure}} () + at compiler/rustc_interface/src/passes.rs:725 +#7 rustc_middle::ty::context::tls::enter_context::{{closure}} () + at /rust/rust/compiler/rustc_middle/src/ty/context.rs:1739 +#8 rustc_middle::ty::context::tls::set_tlv () + at /rust/rust/compiler/rustc_middle/src/ty/context.rs:1723 +#9 rustc_middle::ty::context::tls::enter_context () + at /rust/rust/compiler/rustc_middle/src/ty/context.rs:1739 +#10 rustc_interface::passes::QueryContext::enter () + at compiler/rustc_interface/src/passes.rs:725 +#11 0x00007fffef818cb5 in rustc_interface::queries::Queries::ongoing_codegen::{{closure}} () at compiler/rustc_interface/src/queries.rs:275 +#12 rustc_interface::queries::Query<T>::compute () + at compiler/rustc_interface/src/queries.rs:35 +#13 rustc_interface::queries::Queries::ongoing_codegen () + at compiler/rustc_interface/src/queries.rs:273 +#14 0x00007fffef58d391 in rustc_driver::run_compiler::{{closure}}::{{closure}} () +--Type <RET> for more, q to quit, c to continue without paging-- + at compiler/rustc_driver/src/lib.rs:441 +#15 rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter () + at /rust/rust/compiler/rustc_interface/src/queries.rs:415 +#16 0x00007fffef64d497 in rustc_driver::run_compiler::{{closure}} () + at compiler/rustc_driver/src/lib.rs:336 +#17 rustc_interface::interface::create_compiler_and_run::{{closure}} () + at /rust/rust/compiler/rustc_interface/src/interface.rs:196 +#18 rustc_span::with_source_map () at /rust/rust/compiler/rustc_span/src/lib.rs:764 +#19 0x00007fffef58ef94 in rustc_interface::interface::create_compiler_and_run () + at /rust/rust/compiler/rustc_interface/src/interface.rs:190 +#20 0x00007fffef56d83f in rustc_interface::interface::run_compiler::{{closure}} () + at /rust/rust/compiler/rustc_interface/src/interface.rs:212 +#21 rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::{{closure}}::{{closure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:152 +#22 scoped_tls::ScopedKey<T>::set () + at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137 +#23 0x00007fffef572e45 in rustc_span::with_session_globals () + at /rust/rust/compiler/rustc_span/src/lib.rs:93 +#24 rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::{{closure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:150 +#25 rustc_interface::util::scoped_thread::{{closure}} () + at /rust/rust/compiler/rustc_interface/src/util.rs:125 +#26 std::sys_common::backtrace::__rust_begin_short_backtrace () + at /rust/rust/library/std/src/sys_common/backtrace.rs:125 +#27 0x00007fffef5bbd0f in std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}} () at /rust/rust/library/std/src/thread/mod.rs:474 +#28 <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once + () at /rust/rust/library/std/src/panic.rs:322 +--Type <RET> for more, q to quit, c to continue without paging-- +#29 std::panicking::try::do_call () at /rust/rust/library/std/src/panicking.rs:379 +#30 std::panicking::try () at /rust/rust/library/std/src/panicking.rs:343 +#31 std::panic::catch_unwind () at /rust/rust/library/std/src/panic.rs:396 +#32 std::thread::Builder::spawn_unchecked::{{closure}} () + at /rust/rust/library/std/src/thread/mod.rs:473 +#33 core::ops::function::FnOnce::call_once{{vtable-shim}} () + at /rust/rust/library/core/src/ops/function.rs:227 +#34 0x00007fffeea33488 in <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () at /rust/rust/library/alloc/src/boxed.rs:1318 +#35 <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () + at /rust/rust/library/alloc/src/boxed.rs:1318 +#36 std::sys::unix::thread::Thread::new::thread_start () + at library/std/src/sys/unix/thread.rs:71 +#37 0x00007fffee74f609 in start_thread (arg=<optimized out>) at pthread_create.c:477 +#38 0x00007fffee891293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 +``` + +- rustでunicode使えるはず +- https://doc.rust-lang.org/book/ch08-02-strings.html + +## compiler/rustc_interface/src/queries.rs +- lower_to_hir +## compiler/rustc_codegen_ssa +- codegen_crate() +- cgu_name_builder() +- codegen_unit() +- monomorphization + - ポリモーフィズムなところをアセンブラ用にモノに直すこと +- dep_graph + - dependency graph +- ongoing_codegen +- パラレルコンパイル +- LTO + - linking最適化をしてスピードアップを図る + - https://doc.rust-lang.org/rustc/linker-plugin-lto.html +- generate_lto_work + - WorkItem::CopyPostLtoArtifacts() +- Itemは並列処理でスレッド処理していく単位 +- codegen_statement + + +## rustc_codegen_llvm +- https://rustc-dev-guide.rust-lang.org/backend/codegen.html +- builder.rs + - BuilderMethods + - from_const + - 実態はlayout + - OperandValue::Immediate() + - llvmのAPI + - eval_mir_constant_to_operand + + +``` + +#0 <rustc_codegen_llvm::builder::Builder as rustc_target::abi::LayoutOf>::layout_of + () at compiler/rustc_codegen_llvm/src/builder.rs:92 +#1 rustc_codegen_ssa::mir::operand::OperandRef<V>::from_const () + at /rust/rust/compiler/rustc_codegen_ssa/src/mir/operand.rs:74 +#2 0x00007fffefab11c0 in rustc_codegen_ssa::mir::constant::<impl rustc_codegen_ssa::mir::FunctionCx<Bx>>::eval_mir_constant_to_operand () + at /rust/rust/compiler/rustc_codegen_ssa/src/mir/constant.rs:20 +#3 rustc_codegen_ssa::mir::operand::<impl rustc_codegen_ssa::mir::FunctionCx<Bx>>::codegen_operand () at /rust/rust/compiler/rustc_codegen_ssa/src/mir/operand.rs:442 +#4 0x00007fffefaad25b in rustc_codegen_ssa::mir::rvalue::<impl rustc_codegen_ssa::mir::FunctionCx<Bx>>::codegen_rvalue_operand () + at /rust/rust/compiler/rustc_codegen_ssa/src/mir/rvalue.rs:458 +#5 0x00007fffefaa07c6 in rustc_codegen_ssa::mir::statement::<impl rustc_codegen_ssa::mir::FunctionCx<Bx>>::codegen_statement () + at /rust/rust/compiler/rustc_codegen_ssa/src/mir/statement.rs:24 +#6 rustc_codegen_ssa::mir::block::<impl rustc_codegen_ssa::mir::FunctionCx<Bx>>::codegen_block () at /rust/rust/compiler/rustc_codegen_ssa/src/mir/block.rs:939 +#7 0x00007fffefa9db40 in rustc_codegen_ssa::mir::codegen_mir () + at /rust/rust/compiler/rustc_codegen_ssa/src/mir/mod.rs:254 +#8 0x00007fffefbda37a in rustc_codegen_ssa::base::codegen_instance () + at /rust/rust/compiler/rustc_codegen_ssa/src/base.rs:358 +#9 0x00007fffef9c6b44 in <rustc_middle::mir::mono::MonoItem as rustc_codegen_ssa::mono_item::MonoItemExt>::define () + at /rust/rust/compiler/rustc_codegen_ssa/src/mono_item.rs:42 +#10 0x00007fffefa6f39b in rustc_codegen_llvm::base::compile_codegen_unit::module_codegen () at compiler/rustc_codegen_llvm/src/base.rs:128 +#11 0x00007fffefad280e in rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl () at /rust/rust/compiler/rustc_query_system/src/dep_graph/graph.rs:301 +#12 rustc_query_system::dep_graph::graph::DepGraph<K>::with_task () +--Type <RET> for more, q to quit, c to continue without paging-- + at /rust/rust/compiler/rustc_query_system/src/dep_graph/graph.rs:200 +#13 0x00007fffefa6ec9c in rustc_codegen_llvm::base::compile_codegen_unit () + at compiler/rustc_codegen_llvm/src/base.rs:104 +#14 0x00007fffefbd795d in <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::ExtraBackendMethods>::compile_codegen_unit () + at compiler/rustc_codegen_llvm/src/lib.rs:106 +#15 rustc_codegen_ssa::base::codegen_crate () + at /rust/rust/compiler/rustc_codegen_ssa/src/base.rs:642 +#16 0x00007fffefc11b95 in <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::CodegenBackend>::codegen_crate () + at compiler/rustc_codegen_llvm/src/lib.rs:267 +#17 0x00007fffef91c75b in rustc_interface::passes::start_codegen::{{closure}} () + at compiler/rustc_interface/src/passes.rs:996 +#18 rustc_data_structures::profiling::VerboseTimingGuard::run () + at /rust/rust/compiler/rustc_data_structures/src/profiling.rs:570 +#19 rustc_session::utils::<impl rustc_session::session::Session>::time () + at /rust/rust/compiler/rustc_session/src/utils.rs:9 +#20 rustc_interface::passes::start_codegen () + at compiler/rustc_interface/src/passes.rs:995 +#21 rustc_interface::queries::Queries::ongoing_codegen::{{closure}}::{{closure}} () + at compiler/rustc_interface/src/queries.rs:284 +#22 rustc_interface::passes::QueryContext::enter::{{closure}} () + at compiler/rustc_interface/src/passes.rs:725 +#23 rustc_middle::ty::context::tls::enter_context::{{closure}} () + at /rust/rust/compiler/rustc_middle/src/ty/context.rs:1739 +#24 rustc_middle::ty::context::tls::set_tlv () + at /rust/rust/compiler/rustc_middle/src/ty/context.rs:1723 +#25 rustc_middle::ty::context::tls::enter_context () + at /rust/rust/compiler/rustc_middle/src/ty/context.rs:1739 +--Type <RET> for more, q to quit, c to continue without paging-- +#26 rustc_interface::passes::QueryContext::enter () + at compiler/rustc_interface/src/passes.rs:725 +#27 0x00007fffef818cb5 in rustc_interface::queries::Queries::ongoing_codegen::{{closure}} () at compiler/rustc_interface/src/queries.rs:275 +#28 rustc_interface::queries::Query<T>::compute () + at compiler/rustc_interface/src/queries.rs:35 +#29 rustc_interface::queries::Queries::ongoing_codegen () + at compiler/rustc_interface/src/queries.rs:273 +#30 0x00007fffef58d391 in rustc_driver::run_compiler::{{closure}}::{{closure}} () + at compiler/rustc_driver/src/lib.rs:441 +#31 rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter () + at /rust/rust/compiler/rustc_interface/src/queries.rs:415 +#32 0x00007fffef64d497 in rustc_driver::run_compiler::{{closure}} () + at compiler/rustc_driver/src/lib.rs:336 +#33 rustc_interface::interface::create_compiler_and_run::{{closure}} () + at /rust/rust/compiler/rustc_interface/src/interface.rs:196 +#34 rustc_span::with_source_map () at /rust/rust/compiler/rustc_span/src/lib.rs:764 +#35 0x00007fffef58ef94 in rustc_interface::interface::create_compiler_and_run () + at /rust/rust/compiler/rustc_interface/src/interface.rs:190 +#36 0x00007fffef56d83f in rustc_interface::interface::run_compiler::{{closure}} () + at /rust/rust/compiler/rustc_interface/src/interface.rs:212 +#37 rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::{{closure}}::{{closure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:152 +#38 scoped_tls::ScopedKey<T>::set () + at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/scoped-tls-1.0.0/src/lib.rs:137 +#39 0x00007fffef572e45 in rustc_span::with_session_globals () + at /rust/rust/compiler/rustc_span/src/lib.rs:93 +#40 rustc_interface::util::setup_callbacks_and_run_in_thread_pool_with_globals::{{clo--Type <RET> for more, q to quit, c to continue without paging-- +sure}} () at /rust/rust/compiler/rustc_interface/src/util.rs:150 +#41 rustc_interface::util::scoped_thread::{{closure}} () + at /rust/rust/compiler/rustc_interface/src/util.rs:125 +#42 std::sys_common::backtrace::__rust_begin_short_backtrace () + at /rust/rust/library/std/src/sys_common/backtrace.rs:125 +#43 0x00007fffef5bbd0f in std::thread::Builder::spawn_unchecked::{{closure}}::{{closure}} () at /rust/rust/library/std/src/thread/mod.rs:474 +#44 <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once + () at /rust/rust/library/std/src/panic.rs:322 +#45 std::panicking::try::do_call () at /rust/rust/library/std/src/panicking.rs:379 +#46 std::panicking::try () at /rust/rust/library/std/src/panicking.rs:343 +#47 std::panic::catch_unwind () at /rust/rust/library/std/src/panic.rs:396 +#48 std::thread::Builder::spawn_unchecked::{{closure}} () + at /rust/rust/library/std/src/thread/mod.rs:473 +#49 core::ops::function::FnOnce::call_once{{vtable-shim}} () + at /rust/rust/library/core/src/ops/function.rs:227 +#50 0x00007fffeea33488 in <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () at /rust/rust/library/alloc/src/boxed.rs:1318 +#51 <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once () + at /rust/rust/library/alloc/src/boxed.rs:1318 +#52 std::sys::unix::thread::Thread::new::thread_start () + at library/std/src/sys/unix/thread.rs:71 +#53 0x00007fffee74f609 in start_thread (arg=<optimized out>) at pthread_create.c:477 +#54 0x00007fffee891293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 +``` +
--- a/Gears/Xv6.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,4 +4,8 @@ # リポジトリ -- http://www.cr.ie.u-ryukyu.ac.jp/hg/CbC/CbC_xv6/ \ No newline at end of file +- http://www.cr.ie.u-ryukyu.ac.jp/hg/CbC/CbC_xv6/ + +# ページ + +$lsx(./) \ No newline at end of file
--- a/Gears/Xv6/QA.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/QA.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,4 +4,7 @@ --- -## 質問: \ No newline at end of file +## 質問: 「変換した時にgoto metaの前に書き戻されない」 + +A. 次の継続に遷移する際に `goto self->codegear(hoge,foo,piyo)`としないとだめ +
--- a/Gears/Xv6/cmmon_errors.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/cmmon_errors.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,12 +1,65 @@ # よくあるエラー +# 一般的に +- Gearsの場合は CbCで書いたファイルをPerlスクリプトで変換して、変換後のファイルがコンパイルされる +- そのために自分が書いた.cbcなファイルと、生成された.cファイル、ヘッダファイルを見てエラーを考える必要がある +- 他にはCファイルの問題もある + +# 個別 + ## `Gearef(cbc_context,char)` -### 原因 +### 原因 1 - CodeGearの引数を実装しているInteface/Interfaceの実装に無いフィールドを参照しているときに起こる - Gearefの第2引数はDataGear(context.hの中のunion Dataにかかれている構造体)でないとだめだが、charは無いので ### 解決方法 - `char* hoge`などを引数で渡していると考えられるので、これをInteface/InterfaceImplのfieldに追加する - - headefileに書けばいい \ No newline at end of file + - headefileに書けばいい + +### 原因 2 +- `#interface "hoge.h"`している`hoge.h`が`generate_stub.pl`側から参照できない + - generate_stub中でPerlの `if (-f $filename)` でファイルを判定している為 + +### 解決方法 +- `#interface`以降のファイル名をmakeしているディレクトリからの相対パスで書く + - ビルドしている.cbcと同じディレクトリの場合は省略可能 + +## `Gearef`の第2引数が空白になっている + +### 原因 +- generate_stubで上手く生成できていない +- generate_stubは現在実装しているinterfaceの名前をコンストラクタの関数名でキャプチャしている + - `Interface* createInterfaceImpl()` + - この`Interface*`に該当するものが、Intefaceの名前であり、 Gearefの第2引数になる + +### 解決 +- 該当するコンストラクタを書く + - コメントでも別に問題はない +- 書かれたコンストラクタはextern.hに出力される + +## `__code next(...)`が.cでも置換されてない/ stubで渡している変数の数が足りない + +### 原因 +- 引数の型名を `struct hoge* foo`ではなくて `stuct hoge *foo`にしているのが原因 +- `*`は必ず型名の方につける必要がある + +### 解決 +- 生成されたcのstubのコードを見ながらポインタの位置がずれてそうな箇所を探す + - 特定されたら修正する + +## よくわからないGearefが生成されている + +### 原因 +- 現状のgenerate_stubは `//`はCのコメントに対応していない +- `// goto hoge()`みたいに書いてしまうと、コメントの外にGearefのマクロが出力されてしまう + +### 対策 +- 複数コメントにしておく +```c +/* + goto hoge(); +*/ +``` + \ No newline at end of file
--- a/Gears/Xv6/src/CMakeLists.txt.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/CMakeLists.txt.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,4 +1,16 @@ # src/CMakeLists.txt - CbCXv6のkernelの方のCMakeLists.txt - - usrとかは別のディレクトリに置かれている \ No newline at end of file + - usrとかは別のディレクトリに置かれている + +# 処理内容 + +- Gearsで記述された内容をCbCに変換してビルドするのはいつもどおり +- 中でkernel.elfを作るために色々処理をしている + - ここはlinux(dalmore)とmacOSで処理を分岐する必要があるためpmake.plで制御している +- 別のディレクトリでビルドできるように、現在のビルドディレクトリにいろいろコピーする + - ヘッダファイルはフラットな状態ですべてビルドディレクトリに配置される + +## 新しいファイルを追加したら + +- ファイル末尾の`GearsCommand`のTARGETに対象のファイル名を記述する必要がある \ No newline at end of file
--- a/Gears/Xv6/src/gearsTools.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/gearsTools.md Wed Dec 16 15:11:16 2020 +0900 @@ -13,4 +13,10 @@ ## ビルド時に自動で実行される - [[generate_context.pl]] -- [[generate_stub.pl]] \ No newline at end of file +- [[generate_stub.pl]] + + +# モジュール + +- [[lib]]以下に置かれている`*.pm`がPerlモジュール + - generate_contextなどの内部で利用している \ No newline at end of file
--- a/Gears/Xv6/src/gearsTools/generate_stub.pl.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/gearsTools/generate_stub.pl.md Wed Dec 16 15:11:16 2020 +0900 @@ -24,7 +24,82 @@ - Interfaceのフィードにあるかないかで生成されるマクロが異なる - ここで`%var`には `$name`と`$tname(変数名)`, `$ttype(型名)`が登録される - `$ttype`は`struct|union`は外された状態で登録される - - これらは `typedef`で外された型名でも使えるため - - そのため`Gearef`のマクロではstructを外した状態で書かれる + - これらは `typedef`で外された型名でも使えるので、そちらで生成している + - そのため`Gearef`のマクロではstructを外した状態で書かれる - constの場合は `const char`で1つの型なので、constが来ていたらconstを戻している -- いずれにせよポインタの`*`はここでは落とさなければならない \ No newline at end of file +- いずれにせよポインタの`*`はここでは落とさなければならない + - `if ($ttype =~ /^(union|struct|const)?\s*(\w+)/)`の正規表現でポインタを外している + + +# TODO + +## OutPutDataGearが2つ存在するケース + +Stackのinterfaceで言うところの`get2`と`pop2`のケース + +```c +typedef struct Stack<Type, Impl>{ + union Data* stack; + union Data* data; + union Data* data1; + /* Type* stack; */ + /* Type* data; */ + /* Type* data1; */ + __code whenEmpty(...); + __code clear(Impl* stack,__code next(...)); + __code push(Impl* stack,Type* data, __code next(...)); + __code pop(Impl* stack, __code next(Type* data, ...)); + __code pop2(Impl* stack, __code next(Type* data, Type* data1, ...)); + __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...)); + __code get(Impl* stack, __code next(Type* data, ...)); + __code get2(Impl* stack, __code next(Type* data, Type* data1, ...)); + __code next(...); +} Stack; +``` + +`pop2`と`get2`はそれぞれ`__code next`に2つの出力が存在する +- これを取り出して来るのは`pop2`などの呼び出し元が設定したContinuationによって異なる + +例えばRedBlackTreeの例題では、このように呼び出している + +```c +__code insertCase3(struct RedBlackTree* tree) { + struct Stack* nodeStack = tree->nodeStack; + struct Node* uncle; + + if (tree->grandparent->left == tree->parent) { + uncle = tree->grandparent->right; + } else { + uncle = tree->grandparent->left; + } + + if (uncle && (uncle->color == Red)) { + // do insertcase1 on grandparent, stack must be pop by two + tree->parent->color = Black; + uncle->color = Black; + tree->grandparent->color = Red; + tree->current = tree->grandparent; + goto nodeStack->pop2(insertCase1); + } + goto insertCase4(); +} +``` +上の例題では `goto nodeStack->pop2(insertCase1);`の部分が相当する +- Stackの実装はnodeStack +- pop2に渡している継続は`insertCase1` + +この場合、insertCase1はstubでStackのInterfaceから値を2つ取り出す必要がある +- 現状のgenerate_stubはこの出力に対応していないので、👇のようなstubを静的に書いている + +``` +__code insertCase1_stub(struct Context* context) { + goto insertCase1(context, + &Gearef(context, Tree)->tree->Tree.tree->RedBlackTree, + &context->data[D_Stack]->Stack.data->Node, + &context->data[D_Stack]->Stack.data1->Node); +} +``` + +### やりたいこと +- 呼び出すAPIの出力に応じて、継続先のstubをいい感じに整形する + - 呼び出した先のInterfaceがなんであるかを判定する必要がありそう \ No newline at end of file
--- a/Gears/Xv6/src/gearsTools/generate_stub.pl/overview.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/gearsTools/generate_stub.pl/overview.md Wed Dec 16 15:11:16 2020 +0900 @@ -33,4 +33,117 @@ - 型定義かどうかのファイル - つまるところInterfaceのヘッダファイルなら1になっている - 具体的には `/^typedef struct (\w+)\s*<(.*)>/`か`/^typedef struct (\w+)/`にヒットすればこのモードになる -- $described_data_gear \ No newline at end of file +- $described_data_gear + + +### InTypedefがtrueの時に実行されるもの + +Interfaceの定義(読み込んでいる対象がヘッダファイルだった場合)に実行されるのが想定されていそう +- InTypedefをfalseにするコードが無いので、一度ここに来たらずっとこれが実行されているはず + +👇のコードは`struct hoge* foo;`や`int hoge;`などがキャプチャされる +- `$ttype`には型名もキャプチャされるケースがある(union, struct, const) +- 発見されたフィールどは、型名と識別子をハッシュ`%var`に設定する必要がある +- この時点では型名の`struct`などは外す必要がある + - そのために、`const`以外のケースは`$ttype`の中身を更に確認して、キャプチャ出来た値を利用する + +```perl +# gather type name and type +$dataGear{$name} .= $_; +if (/^\s*(.*)\s+(\w+);$/ ) { + my $ttype = $1; + my $tname = $2; + if ($ttype =~ /^(union|struct|const)?\s*(\w+)/) { + if ($1 ne 'const') { + $ttype = $2; + } else { + $ttype = "const $2"; + } + } + $described_data_gear = 1; + $var{$name}->{$tname} = $ttype; +} +``` + +このコードは`__code`である場合にキャプチャする +- Interfaceの定義で、`__code`の中だけに引数を書いておけば、静的に書く必要がなくなる機能を実装する際に書かれた +- `__code`のCodeGearの名前は特にキャプチャせず、中の引数をキャプチャしていく + +``` +if (/__code (\w+)/) { + next if $described_data_gear; + my $args = $'; + while ($args =~ /\s*(struct|union|const)?\s*([\w\[\]_]+)\*?\s*(\w+),?/g) { + #$args eq (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + my $const_type = $1; + my $ttype = $2; + my $tname = $3; + + $ttype =~ s/(Impl|Isa|Type)/Data/; + if ($const_type eq 'const') { + $ttype = "const $ttype"; + } + $var{$name}->{$tname} = $ttype; + } +} +if (/^}/) { + $inTypedef = 0; +} +``` + +### falseの時 + +入力されたファイルがCbCで無いときに実行されるのが想定されている +- 実際は`inTypedef`を1にする正規表現のブロックが実行されるまではデフォルトでこのブロックが処理される + +```perl +if (/^typedef struct (\w+)\s*<(.*)>/) { + $inTypedef = 1; + $name = $1; + $dataGear{$name} = $_; + $var{$name} = {}; + $code{$name} = {}; + $generic{$name} = \split(/,/,$2); +} elsif (/^typedef struct (\w+)/) { + $inTypedef = 1; + $name = $1; + $dataGear{$name} = $_; + $var{$name} = {}; + $code{$name} = {}; + $generic{$name} = []; +} elsif (/^(\w+)(\*)+ create(\w+)\(/) { + if (defined $interface) { + die "duplicate interface $interface\n"; + } + $interface = $1; + $implementation = $3; + if ( -f "$interface.cbc") { + &getDataGear("$interface.cbc"); + } +} elsif(/^(.*)par goto (\w+)\((.*)\)/) { + my $codeGearName = $2; + if ($filename =~ /^(.*)\/(.*)/) { + $codeGearName = "$1/$codeGearName"; + } + if ( -f "$codeGearName.cbc") { + &getCodeGear("$codeGearName.cbc"); + } +} elsif(/^#interface "(.*)"/) { + # use interface + my $interfaceHeader = $1; + next if ($interfaceHeader =~ /context.h/); + if (-f $interfaceHeader) { + &getDataGear("$interfaceHeader"); + &getCodeGear("$interfaceHeader"); + } +} elsif (/^\_\_code (\w+)\((.*)\)(.*)/) { + my $codeGearName = $1; + if ($filename =~ /^(.*)\/(.*)/) { + $codeGearName = "$1/$codeGearName"; + } + if ( -f "$codeGearName.cbc") { + &getCodeGear("$codeGearName.cbc"); + } +} +next; + ``` \ No newline at end of file
--- a/Gears/Xv6/src/gearsTools/pmake.pl.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/gearsTools/pmake.pl.md Wed Dec 16 15:11:16 2020 +0900 @@ -15,7 +15,7 @@ - `print_exec_system`に送ったリストがsystemで実行されるようになっている - 現状はOSがdarwinかそうでないか判断している - - dawrinだとdalmoreだと思いこんで実行している + - dawrinじゃないとdalmoreだと思いこんで実行している - 現状コンパイラを探す機能とか、armLibraryを拾ってくる機能は無い - 付け加えれば問題ないけど...
--- a/Gears/Xv6/src/impl/pipe.h.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/impl/pipe.h.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,7 +1,7 @@ # pipe.h - pipe 構造体 - - struct file interfaceを実装している + - [struct file interface](../interface/file.dg)を実装している # 内容 - 2020/01/14現在 @@ -16,4 +16,39 @@ int readopen; // read fd is still open int writeopen; // write fd is still open } pipe; -``` \ No newline at end of file +``` + +# UML + +@startuml +interface File { + ..Data.. + +union Data* file + +union Data* impl + +int ref + +char readable + +char writable + +unsigned int off + +struct stat* st + +char* addr + +int n + ..CodeGear.. + __code stat() + __code read() + __code write() + __code close() +} + + +File <|-- Pipe + +class Pipe { + +struct spinlock lock + +char data[PIPESIZE]; + +uint nread; + +uint nwrite; + +int readopen; + +int writeopen; +} + +@enduml \ No newline at end of file
--- a/Gears/Xv6/src/interface/file.dg.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/src/interface/file.dg.md Wed Dec 16 15:11:16 2020 +0900 @@ -21,4 +21,26 @@ __code write(Impl* file, char* addr, int n, __code next(...)); __code close(Impl* file,__code next(...)); } file; -``` \ No newline at end of file +``` + +# UML + +@startuml +interface File { + ..Data.. + +union Data* file + +union Data* impl + +int ref + +char readable + +char writable + +unsigned int off + +struct stat* st + +char* addr + +int n + ..CodeGear.. + __code stat() + __code read() + __code write() + __code close() +} +@enduml \ No newline at end of file
--- a/Gears/Xv6/todo.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/todo.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,126 @@ +# CbCXv6の実装方針 +- kernel側のsyscallを書き換える + - user側はあとで考える +- kernel側はsyscallに対応したinterfaceを作成する + - syscall entryで個別にインスタンスを作成するか、呼び出すか + + # CbCXv6の実装Todo -- [ ] User側のAPI callをオブジェクト指向的にする +- [ ] generate_stubの修正 +- [ ] KernelのContext - [ ] Readsyscall周りの再実装 +- [ ] User側のAPI callをオブジェクト指向的にする + +# そこまで優先度たかくない - [ ] Interfaceの積を取れるようにする -- [ ] usbドライバの作成 \ No newline at end of file +- [ ] usbドライバの作成 +- [ ] (Interfaceの多重実装) + + +## generate_stubの修正 + +いまのところinterfaceで定義したCodeGearを実装しているうちは正常 +- Interfaceで定義していない(Implで独自定義したCodeGearの場合)は上手くgoto metaが変換されない +- generate_stubは `#interface`を見ているので、正常に生成される + +--- +## Read + +- [ ] ~~PipeReadなどを個別のAPI化する~~ + - これではなくてFile Interfaceを実装していく + +# File Interface + +- kernel内部で利用している `struct file`に着目する + - fileは必ず`read`, `write`, `close`, `seek`ができる + - これはunixの想定と同じ +- xv6では `struct file`は`NONE`, `Pipe`, `INODE`の3種類に分類される +- その為、 `struct file`をInterface化し、 `none`などで実装をする + +## image + +### Interface + +``` +typedef struct file <Impl> { + union Data* file; + int ref; // reference count + char readable; + char writable; + unsigned int off; + struct stat* st; + char* addr; + int n; + __code dup(Impl* file, __code next(...)); + __code stat(Impl* file, struct stat* st, __code next(...)); + __code read(Impl* file, char* addr, __code next(...)); + __code write(Impl* file, char* addr, int n, __code next(...)); +} file; +``` +- 👆がFile Interface + - 既存のfile構造体に、API(=CodeGear)で利用する引数を設定している + +### Impl +- pipeやnoneなどで実装する + +``` +typedef struyct NoneFile<Impl, Isa> file { +} NoneFile; +``` +- 👆のような雰囲気の構造体を作成すれば良い + + +### コンストラクタ + +- `sys_open`や`sys_read`の中で、対象のファイルがなんであるかでインスタンスを切り替える + - system call以外のAPIを生やすのも可能ではある(user側との橋渡し) + + +# 図にした + +@startuml + +interface File { + ..DataGear.. + +union Data* file + +union Data* impl + ..CodeGear.. + __code read() + __code write() +} + +File <|-- Inode + +class Inode { + ..DataGear.. + TBD + ..CodeGear.. + __code readInode() + __code writeInode() +} + +File <|-- Pipe + +class Pipe { + ..DataGear.. + TBD + ..CodeGear.. + __code readPipe() + __code writePipe() +} + +File <|-- None + +class None { + ..DataGear.. + TBD + ..CodeGear.. + __code readNone() + __code writeNone() +} + +@enduml + + + \ No newline at end of file
--- a/Gears/Xv6/todo/design.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/todo/design.md Wed Dec 16 15:11:16 2020 +0900 @@ -12,7 +12,7 @@ __code cg_name(struct hoge* foo) ``` -# Inteface +# Interface Gearsでのモジュール化の仕組み。JavaのInterface, Haskellの型クラスに相当する。 @@ -71,4 +71,17 @@ enum Code close; enum Code next; } IO; -``` \ No newline at end of file +``` + +# Interfaceの実装 + +宣言したInterfaceは実装を持つ事ができる。 + + +# Interfaceを使うCodeGearの宣言 + +```c +__code test_code1(IO *io, char* args, __code next(...)) { + goto io->write(args, next); +} +```
--- a/Gears/Xv6/todo/page.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/Xv6/todo/page.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,4 +1,391 @@ # おさらい - 仮想アドレス <-> 物理アドレスの変換をするのがページング - 実際にはTLBに対象のアドレスがある場合はそちらが使われる - - TLBとアドレスの対応を同期させるために tlb flushが必要になる \ No newline at end of file + - TLBとアドレスの対応を同期させるために tlb flushが必要になる +- プロセスを造ったとき, 拡張したい時などに使われる +- ゼロページ + - ゼロが入っているページは書き込まれるまではすべてのプロセスが見ていていい + - 書き込まれた場合に初めて物理メモリに割当をする + - copy on write... +- 仮想メモリにCPUがアクセスに行くと、ディスクをコピって制御する必要がある + - 一旦追い出して、コピった後はtlb flushする必要がある + - いろいろしたら tlb flush して trap return + +# Xv6では + +- memlayout.h + - v2p(仮想メモリ -> 実メモリ)などを制御するマクロが宣言されている +- mmu.h + - 実際に使用されるページに関するマクロが定義 + - おおよそ定数を指定しているもの, ビット演算が書かれているものがある + - user page table sizeは4K + +## vm.c +- 大体このファイルで実装されていそう +- staticがついているものはprivate codegear +- xv6は4K +- ARMは1K + - 1つのブロックを4つに分ける + - `pde_t *kpgdir; // for use in scheduler()` + - スケジューラーに値を渡すためのglobal variable + - contextに書き込めば問題なさそう + - `kpt_mem` とかはDataGearにすれば良さそう +### init_vmm +``` +void init_vmm (void) +{ + initlock(&kpt_mem.lock, "vm"); + kpt_mem.freelist = NULL; +} +``` +- lockのとこに0をいれるだけ + - 0だったら誰も使ってない + - 使っている人のidをいれるのが本来 +- freelistをNULLにしてるのはclearにしている +- init_vmmは外から呼び出されるのでInterfaceにするべき + +### _kpt_free + +- メモリページ全体をlinked listにしているrを取り出す + - vで指しているページテーブルをフリーリストにつなげる + - このリストは物理メモリで作られている + +``` +static void _kpt_free (char *v) +{ + struct run *r; + + r = (struct run*) v; + r->next = kpt_mem.freelist; + kpt_mem.freelist = r; +} +``` + +### ktp_free + +- kfreeがカーネルのメモリフリー +- acquireとreleaseをしているので並列によばれる可能性がある + - acquireとreleaseはメタ計算でやるべき...? + +``` +static void kpt_free (char *v) +{ + if (v >= (char*)P2V(INIT_KERNMAP)) { + kfree(v, PT_ORDER); + return; + } + + acquire(&kpt_mem.lock); + _kpt_free (v); + release(&kpt_mem.lock); +} +``` + + +### kpt_freerange + +- 何ページもfreeするときはページごとにlinked listに接続する +- lockしていない + - これを呼ぶときはマルチプロセス環境で読んではいけない + - とはいえ外からよばれる + - release/lockは自前でする必要がある + +```c +// add some memory used for page tables (initialization code) +void kpt_freerange (uint32 low, uint32 hi) +{ + while (low < hi) { + _kpt_free ((char*)low); + low += PT_SZ; + } +} +``` + +### kpt_alloc + +- lockしてNULLだったら kmalloc + - 失敗したらpanic +- allocateに成功したらゼロクリア + +```c +void* kpt_alloc (void) +{ + struct run *r; + + acquire(&kpt_mem.lock); + + if ((r = kpt_mem.freelist) != NULL ) { + kpt_mem.freelist = r->next; + } + + release(&kpt_mem.lock); + + // Allocate a PT page if no inital pages is available + if ((r == NULL) && ((r = kmalloc (PT_ORDER)) == NULL)) { + panic("oom: kpt_alloc"); + } + + memset(r, 0, PT_SZ); + return (char*) r; +} +``` + +### walkpgdir + +- page table側の場所を探す +- page table entryにNULL pointerがあるとセグフォして死ぬので厳しい + +```clike= +// Return the address of the PTE in page directory that corresponds to +// virtual address va. If alloc!=0, create any required page table pages. +static pte_t* walkpgdir (pde_t *pgdir, const void *va, int alloc) +{ + pde_t *pde; + pte_t *pgtab; + + // pgdir points to the page directory, get the page direcotry entry (pde) + pde = &pgdir[PDE_IDX(va)]; + + if (*pde & PE_TYPES) { + pgtab = (pte_t*) p2v(PT_ADDR(*pde)); + + } else { + if (!alloc || (pgtab = (pte_t*) kpt_alloc()) == 0) { + return 0; + } + + // Make sure all those PTE_P bits are zero. + memset(pgtab, 0, PT_SZ); + + // The permissions here are overly generous, but they can + // be further restricted by the permissions in the page table + // entries, if necessary. + *pde = v2p(pgtab) | UPDE_TYPE; + } + + return &pgtab[PTE_IDX(va)]; +} +``` + +### mappages + +- code gearに書き換えなくても良さそう + +```clike +// Create PTEs for virtual addresses starting at va that refer to +// physical addresses starting at pa. va and size might not +// be page-aligned. +static int mappages (pde_t *pgdir, void *va, uint size, uint pa, int ap) +{ + char *a, *last; + pte_t *pte; + + a = (char*) align_dn(va, PTE_SZ); + last = (char*) align_dn((uint)va + size - 1, PTE_SZ); + + for (;;) { + if ((pte = walkpgdir(pgdir, a, 1)) == 0) { + return -1; + } + + if (*pte & PE_TYPES) { + panic("remap"); + } + + *pte = pa | ((ap & 0x3) << 4) | PE_CACHE | PE_BUF | PTE_TYPE; + + if (a == last) { + break; + } + + a += PTE_SZ; + pa += PTE_SZ; + } + + return 0; +} +``` + +### switchuvm + +- pageを切り替えるやつ +- inline 展開されそう +- push/pop cliで割り込み禁止 + +``` +// Switch to the user page table (TTBR0) +void switchuvm (struct proc *p) +{ + uint val; + + pushcli(); + + if (p->pgdir == 0) { + panic("switchuvm: no pgdir"); + } + + val = (uint) V2P(p->pgdir) | 0x00; + + asm("MCR p15, 0, %[v], c2, c0, 0": :[v]"r" (val):); + flush_tlb(); + + popcli(); +} +``` + +### inituvm + +- pageディレクトリを作るやつ + +```clike +// Load the initcode into address 0 of pgdir. sz must be less than a page. +void inituvm (pde_t *pgdir, char *init, uint sz) +{ + char *mem; + + if (sz >= PTE_SZ) { + panic("inituvm: more than a page"); + } + + mem = alloc_page(); + memset(mem, 0, PTE_SZ); + mappages(pgdir, 0, PTE_SZ, v2p(mem), AP_KU); + memmove(mem, init, sz); +} +``` + +### loaduvm + +- swapから呼び出す +- kernelの中をぐるぐるしてreadiに入る + - 入った場合は待ちになる + - user proc側が街になる +- context側でどこで止まっていて、どこから実行するかを書かないとだめ + +```clike= +// Load a program segment into pgdir. addr must be page-aligned +// and the pages from addr to addr+sz must already be mapped. +int loaduvm (pde_t *pgdir, char *addr, struct inode *ip, uint offset, uint sz) +{ + uint i, pa, n; + pte_t *pte; + + if ((uint) addr % PTE_SZ != 0) { + panic("loaduvm: addr must be page aligned"); + } + + for (i = 0; i < sz; i += PTE_SZ) { + if ((pte = walkpgdir(pgdir, addr + i, 0)) == 0) { + panic("loaduvm: address should exist"); + } + + pa = PTE_ADDR(*pte); + + if (sz - i < PTE_SZ) { + n = sz - i; + } else { + n = PTE_SZ; + } + + if (readi(ip, p2v(pa), offset + i, n) != n) { + return -1; + } + } + + return 0; +} +``` + + +### allocuvm/deallocuvm + +- page tableをallocateするか消すかの対応になっている +- memory clearはここでは行われない +- user virtual momeryの略? + +### copyuvm + +- forkのときによばれる + - forkの場合は自分のメモリ空間を子供にコピるので +- for文のパラメーターをどこかに保存しておく必要がある + +```clike= +// Given a parent process's page table, create a copy +// of it for a child. +pde_t* copyuvm (pde_t *pgdir, uint sz) +{ + pde_t *d; + pte_t *pte; + uint pa, i, ap; + char *mem; + + // allocate a new first level page directory + d = kpt_alloc(); + if (d == NULL ) { + return NULL ; + } + + // copy the whole address space over (no COW) + for (i = 0; i < sz; i += PTE_SZ) { + if ((pte = walkpgdir(pgdir, (void *) i, 0)) == 0) { + panic("copyuvm: pte should exist"); + } + + if (!(*pte & PE_TYPES)) { + panic("copyuvm: page not present"); + } + + pa = PTE_ADDR (*pte); + ap = PTE_AP (*pte); + + if ((mem = alloc_page()) == 0) { + goto bad; + } + + memmove(mem, (char*) p2v(pa), PTE_SZ); + + if (mappages(d, (void*) i, PTE_SZ, v2p(mem), ap) < 0) { + goto bad; + } +``` + + +### copyout + +- 仮想メモリのコピーに巻き込まれそう... + +```clike +int copyout (pde_t *pgdir, uint va, void *p, uint len) +{ + char *buf, *pa0; + uint n, va0; + + buf = (char*) p; + + while (len > 0) { + va0 = align_dn(va, PTE_SZ); + pa0 = uva2ka(pgdir, (char*) va0); + + if (pa0 == 0) { + return -1; + } + + n = PTE_SZ - (va - va0); + + if (n > len) { + n = len; + } + + memmove(pa0 + (va - va0), buf, n); + + len -= n; + buf += n; + va = va0 + PTE_SZ; + } + + return 0; +} +``` + +## 方針 +- free以外のfor/while文はCodeGearに変換する \ No newline at end of file
--- a/Gears/gearstools/trans_impl.pl.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/gearstools/trans_impl.pl.md Wed Dec 16 15:11:16 2020 +0900 @@ -14,4 +14,13 @@ # 生成されたファイル - 特にオプションを指定しないと標準出力に出力されます - `perl trans_impl.pl SingleLinkedStack.h | pbcopy` - - こうしておくとクリップボードにコピーされて便利 \ No newline at end of file + - こうしておくとクリップボードにコピーされて便利 + + +# 実装に関して + +- trans_impl側に直書きしている処理と, ライブラリ化した`Gears::` 名前空間のモジュールをいくつか利用している + +# TODO +- 実装側の`__code`は別ファイルに書き出すようにしたい + - 同じファイルの場合はgenerate_stubでの生成が怪しくなる \ No newline at end of file
--- a/Gears/introduction.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,4 +5,16 @@ ## 環境構築 - [CbCコンパイラのinstall](/CbC/install) - - armのクロスコンパイラの構成 \ No newline at end of file + - armのクロスコンパイラの構成 + +## コンテンツ + $lsx(/Gears/introduction) + + +## 実装編 + +### interface +[[Interface入門 >./interface]] + +## context +- [context.h](/Gears/introduction/context/context.h) \ No newline at end of file
--- a/Gears/introduction/context/context.h.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction/context/context.h.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,7 @@ # context.h -GearsOSの中心的なヘッダファイル +- GearsOSの中心的なヘッダファイル +- 実行されるすべてのCodeGear, 利用されるすべてのDataGearが定義されている # 内容 @@ -25,4 +26,28 @@ ## 現在の方法 -- `update_context.pl` もしくは `generate_context.pl` で自動的に生成される \ No newline at end of file +`generate_context.pl` で自動的に生成される + +## generate_context.pl内での生成について +- `ALLOCATE`などのマクロや、`__code`での引数で利用している構造体がピックアップされる +- 構造体の名前に対応するヘッダファイルが検索される + - `struct Stack`の場合は`Stack.h` +- ヘッダファイルの名前が衝突する場合、 `.dg` のファイルが優先的に利用される +- 中身がスキャンされた後、 辞書順で「Interface -> Impl」の順で union Data として出力される + +### テンプレートファイル + +- `gearstools/lib/Gears/Context/Template.pm`もしくは、 `Template/XV6.pm`がテンプレート + - 直接メソッドにヒアドキュメントで記述されている + +# おかしいな?と思ったら +- 生成された `context.h` を確認してください + - XV6の場合は `CMakeFiles/kernel.dir/context.h` が対応します + +# context.hに含めたくないCodeGearの引数 +- `//\s*Skip:\s*generate_context` の正規表現にマッチされた場合、次の行を飛ばす仕組みが実装されています + +``` +//Skip: generate_context +__code sample_codegear(Impl* nanka, struct hoge* fooo,__code next(...)){ +``` \ No newline at end of file
--- a/Gears/introduction/interface.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction/interface.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,4 +4,102 @@ - JavaやgolangのInterface, Haskellの型クラスに相当する構文です ## Interfaceで定義するもの -- golangのInterfaceでは、関数の集合、及び関数の引数と返り値がinterfaceとして定義されていました \ No newline at end of file +- golangのInterfaceでは、関数の集合、及び関数の引数と返り値がinterfaceとして定義されていました +- GearsOSのItnerfaceでも同様に、使用するデータ構造と、関数を記述します +- 使用するデータ(DataGear)はPerlスクリプト側の改良により、`__code`の中に定義しておけば問題ないようになった + +## 書き方(~2019/02/03) + +``` +typedef struct InterfaceName<Type, Impl>{ + //入出力で使用するデータ構造を記述する + union Data* stack; + union Data* data; + union Data* data1; + + // APIとして使用するCodeGearを列挙する + //ここで利用する引数|出力は必ず上で列挙する必要がある + __code whenEmpty(...); + __code clear(Impl* stack,__code next(...)); + __code get2(Impl* stack, __code next(Type* data, Type* data1, ...)); + + //継続先のCodeGear + __code next(...); +} InterfaceName; +``` +- Type + - 自分自身の型 +- Impl + - 自分自身の実装の型 + - Stackの場合はSingleLinkedStackなど... + +## 書き方(2019/02/03~) + +- Perl側を改良したので引数を別で定義する必要がなくなった + +``` +typedef struct InterfaceName<Type, Impl>{ + // APIとして使用するCodeGearを列挙する + __code whenEmpty(...); + __code clear(Impl* stack,__code next(...)); + __code get2(Impl* stack, __code next(Type* data, Type* data1, ...)); + + //継続先のCodeGear + __code next(...); +} InterfaceName; +``` +## 仕様QA +`__code`の記述が始まる前に引数を宣言していた場合、宣言された引数のみが使われる。 + +(`__code`の中の引数はキャプチャされない) + +## Interfaceのファイルを利用するスクリプト +- interfaceのファイルは次のPerlスクリプトで利用され、CbCレベルでは実は参照されません +- `trans_impl.pl` + - cbcファイルの雛形を生成する際に、実装しているファイルから動的に呼び出されます +- ` generate_stub.pl` +- ` generate_context.pl` + - 入出力の引数チェックで行われます + - `generate_context`では、 `context.h`を生成する際に読み込まれます + +## CbCレベルでのInterface +- CbCレベルでは、 stub 及び, `context.h` の `union Data` の定義内で定義されています + - その為 `context.h` を `include`することで、これらの型を利用できます + +## Interfaceの具体例 +- [Stack](/Gears/introduction/interface/Stack) + +## Interfaceの実装の具体例 +- [SingleLinkedStack](/Gears/introduction/interface/impl/SingleLinkedStack) + +## Q&A + +### Q.「Interefaceに書いたDataGearはどうやって実装側から使うの?」 + +**A.「引数で与える」** + +### Q.「引数で使ってないけどContextにDataGearを登録したい」 + +**A.「専用の構文があります」** +- `// data_gear "WantStruct.h"` と書いておくと `generate_context.pl`時に解決される + +#### 例 + +- 例えば `"DataGearExample`をcontextに加えたい場合 + - まず最初に対象のヘッダファイルをどこかに作っておく + - `struct DataGearExample`を使いたいCbCファイルに以下の記述を書いておく + +```c +#include "hoge.h" +//data_gear "DataGearExample.h" +``` + +- `#interface "hoge.h"`構文もあるが、 `generate_stub`の時点でこの文が消えるので、コメントで追加している + +### Q.Intefaceに値持たせたいんだけど + +**A. 値は実装側に持たせるのでInterfaceには書いちゃだめ!!** + +- interfaceはあくまでもCodeGearの入出力だけのDataしかない +- 細かなDataはすべて実装に持たせる + - 同じfieldを持つ実装が複数存在する \ No newline at end of file
--- a/Gears/introduction/interface/Stack.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction/interface/Stack.md Wed Dec 16 15:11:16 2020 +0900 @@ -20,4 +20,67 @@ __code get2(Impl* stack, __code next(Type* data, Type* data1, ...)); __code next(...); } Stack; -``` \ No newline at end of file +``` + +## stackのAPI + +StackのInterfaceでは、StackのAPIとして、幾つかのCodeGear(=メソッド)を提供しています。 + +- whenEmpty + - Stack内部が空だった場合に行われる継続 +- clear + - Stack内部の初期化 +- push + - `Type* data`を引数として受け取り、Stackにpush(最後に追加)する +- pop + - Stackから値を取り出し、次の継続の引数として渡す +- isEmpty + - Stackの内部が空でない場合は`next`に継続し、空である場合は`wehenEmpty` に継続する +- get + - 入出力のデータはpopと変わらないが、おそらくStackを破壊しない + +## next +- nextは次に継続するCodeGearを指します + - 具体的にどういう引数が来るかは、継続先によって異なるので`...`で表現しています +- pop/getは次の継続にデータを渡す必要があります + - この場合は`next`の第一引数の対象のデータを記述することで生成できます + +## union Data +- Stackのdata1, data2はともに `union Data*` で表現されています + - GearsOSのシステムでは、すべてのデータはDataGearとして、Context内で `union Data`で管理されています + - その為、data1, data2は一種の総称型(generics)の役割を果たしています + +## union Data* stack +- interfaceの定義の最初には `union Data* stack`を書く必要があります + - これにはInterfaceを実装した実態が入ります + - 例えばStackの場合はSingleLinkedStack, DoublyLinkedStackなど + - Interface側ではどのような型が来るのか判断できない為、 genericsである `union Data*` が入ります + +## DataGearへの変換 + + StackInterfacehは、 `generate_context.pl`内部で context.h へDataGearに変換されて出力されます。 + + +前述の通り`union Data`の中に定義が生成されます。 + +``` + struct Stack { + union Data* stack; + union Data* data; + union Data* data1; + enum Code whenEmpty; + enum Code clear; + enum Code push; + enum Code pop; + enum Code pop2; + enum Code isEmpty; + enum Code get; + enum Code get2; + enum Code next; + } Stack; +``` +- 変換された `struct Stack`はCの構造体となります +- CodeGearは `enum Code`にすべて変換されます + - 構造体がもつ`enum Code`には、入出力の情報が存在しません + - 具体的にどんなCodeGearが実行されるかは、 このInterfaceの初期化時に決定します +- この構造体は、Interfaceの実装側で初期化します
--- a/Gears/introduction/interface/impl.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction/interface/impl.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,4 +1,46 @@ # Interfaceの実装 - [[Interfaceの定義については確認しました>../about]] -- 続いては定義したInterfaceに具体的な実装を書いていきます \ No newline at end of file +- 続いては定義したInterfaceに具体的な実装を書いていきます + +# 構文 + +- 構文は明確には定まっている訳ではなく[[anatofuz>/user/anatofuz]]が勝手に考えているものです + - 2019/12/25までの論文ではInterfaceの定義の記述のみしか存在していない為です + +```c +typedef struct ImplName<Type, Isa> impl <InterfaceName> { + struct pipe* p; + int i; + int n; + __code cbc_piperead1(Type* sys_read, struct pipe* p, __code next(...)); + __code cbc_piperead2(Type* sys_read, int i, int n, struct pipe* p, __code next(...)); + __code cbc_piperead3(Type* sys_read, int i, struct pipe* p, __code next(...)); + __code next(...); +} ImplName; +``` + +- 構文はInterfaceの構文と似ています + +## 解説 + +### 1行目(実装名の定義) + +- 先頭に「実装の構造体の名前」「実装するInterfaceの名前」を書きます +- `typedef struct ImplName<Type, Isa> impl <InterfaceName>` + - `typedef struct`の直後の実装名を書きます + - `impl`の後の `<>` の中にInterface名をいれます + - 現時点では実装できるInterfaceは1つだけになっています +- `<Type, Isa>`については後ほど解説します + +### DataGear部分 + +- Interfaceと同じ様にImpl内で使う引数を列挙します + - Interfaceで定義したAPIの引数ではありません + +### CodeGear部分 +- `__code name()`で記述します +- `Type`が「自分自身の型」であり Isaが「Interfaceの型」のエイリアスです +- これらのCodeGearはInterfaceが提供するものではないので、一種のprivate methodです + - Interfaceの使用側からは意識しないCodeGearになります + - Interfaceで登録された`next`に継続する必要があります \ No newline at end of file
--- a/Gears/introduction/interface/impl/SingleLinkedStack.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction/interface/impl/SingleLinkedStack.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,5 +5,33 @@ 今回はこのInterfaceの具体的な実装である`SingleLinkedStack`を見ていきます。 -## SingleLinkedStackのヘッダファイル +# SingleLinkedStackのヘッダファイル + +``` c +typedef struct SingleLinkedStack<Type, Isa> impl Stack { + struct Element* top; +} SingleLinkedStack; +``` +- SingleLinkedStackは `struct Element* top`を持っている + - これはインスタンス変数に該当する概念です +- SingleLinkedStackは独自のprivete メソッドを持たない + - その為、ヘッダファイルにCodeGearが登録されていない + +# SingleLinkedStack.cbc +- SingleLinkedStack.hでデータ構造を定義しましたが、ふるまいの実装はまだ行っていません。 +- 今現在はすでに実装されたものが存在しますが、ここでは1から実装を書いてみましょう + +## 雛形生成 + +- `trans_impl.pl`に**実装側のヘッダファイル**を通すことで生成できます + - `perl trans_impl.pl SingleLinkedStack.h` +- `-w` オプションを付けることで、同名の`.cbc`ファイルが生成されます + - `perl trans_impl.pl -w SingleLinkedStack.h` +- `-o` オプションを付けることで、生成するファイル名を指定できます + - `perl trans_impl.pl -o single_linked_stack.cbc SingleLinkedStack.h` + +## 生成されたファイル +- 特にオプションを指定しないと標準出力に出力されます + - `perl trans_impl.pl SingleLinkedStack.h | pbcopy` + - こうしておくとクリップボードにコピーされて便利 \ No newline at end of file
--- a/Gears/introduction/parallel_execution.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Gears/introduction/parallel_execution.md Wed Dec 16 15:11:16 2020 +0900 @@ -25,4 +25,53 @@ マクロの意味は次の通り。 - `TARGET` - - プロジェクトの名前。 `make sample`などでビルド出来るようになり、生成されたバイナリの名前にもなる \ No newline at end of file + - プロジェクトの名前。 `make sample`などでビルド出来るようになり、生成されたバイナリの名前にもなる +- `SOURCES` + - プロジェクトに含める`.cbc`や`.c`などのCファイル + - ヘッダはここに含めない + +### 必ずいれないといけないCbCのソース + +ContextやTaskManager関連の操作で必須となる + +- `TaskManagerImpl.cbc` +- `CPUWorker.cbc` +- `SynchronizedQueue.cbc` +- `AtomicReference.cbc` + +## プロジェクトを始める + +`examples`の下にディレクトリを作成し、その中に`main.cbc`を置く +- 別に`main.cbc`である必要は無いけれど、わかりやすい +- 他の`.cbc`もそのディレクトリ中に置く + - Gears全体に関わるものはトップディレクトリ(`CMakeLists.txt`があるディレクトリ)に置く + +## Interfaceを書く + +Interfaceを使いたい場合は(当然だけど)型定義から始める必要がある +- context.hへは自動で付け加えられる + +生成用のPerlスクリプトがあるので、それを使うと最低限の雛形が生成される +- `perl tools/static_gen_header.pl --interface ExampleInterface` + - `-w`をつけるとファイル生成してくれる + - `-o`の後にファイル名とパスを指定できる + - static_gen_header.plが置いてある場所はプロジェクトごととかで異なるので頑張って探す + +Interfaceの詳しい書き方は[Interface入門](https://growi.cr.ie.u-ryukyu.ac.jp/Gears/introduction/interface)を見ること + +## Interfaceの実装の型 + + +生成用のPerlスクリプトがあるので、それを使うと(ry +- `perl tools/static_gen_header.pl --interface ExampleInterface --impl ExampleInterfaceImpl` + - `-w`をつけるとファイル生成してくれる + - `-o`の後にファイル名とパスを指定できる + - static_gen_header.plが置いてある場所はプロジェクトごととかで異なるので頑張って探す + +## 実装のcbcを作る + +生成用のPerlスクリプトがあるのd(ry + +- `perl tools/trans_impl.pl examples/sample/ExampleInterfaceImpl.h` + - 実装のヘッダファイルを入力する + - オプションは`trans_impl`と同じ様な世界観 \ No newline at end of file
--- a/Linux/Kernel/debug_build.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Linux/Kernel/debug_build.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,11 +5,53 @@ ## ansible - http://www.cr.ie.u-ryukyu.ac.jp/hg/Ansible/fedora_kernel_build/ -## やりかた +## virshを使ったやりかた - まずdebug buildしたいfedoraのvmをつくる - - dalmoreでやると便利 + - 大学のdalmoreサーバーでやると便利 - 結構パワーが必要なので、ansibleのファイルにある通りVMの設定を書き換える - CPUのコア数を8コア - HDDの容量を30GBは確保する - cpuのコア数はvirshのxmlを書き換える -- HDDの容量は、qemu-imgでresizeしたあとに、VMにログインしてファイルシステムを拡張する \ No newline at end of file +- HDDの容量は、qemu-imgでresizeしたあとに、VMにログインしてファイルシステムを拡張する +- ここまで準備が出来たら実行可能! VMのmac addressをakatsukiに登録して、別のマシンから以下のコマンドでansibleを実行する + - 実行する前にVMのipを書いたhostsファイルを用意する + - main.ymlのユーザー名を変更するなどもしておく +``` +$screen -L ansible-playbook -i hosts main.yml --ask-become-pass +``` + + +- 完了したらビルドしたファイルをyomitanなどに転送する +``` +ssh localhost -p 2222 -l root 'cd /usr/src/kernels ; tar czf - fedora' | dd of=fedora26-kernel.tgz +``` +- ここのlocalhostはVMのIPとかに変えておこう。あとユーザーとかもそんな感じで... + +## 起動するkernelを切り替える +- ansibleをかけただけでは、VMが起動するkernelが切り替わってないので切り替える必要がある +- ちまたでは`awk`を使って番号を決めて`grub2-`で解決する方法が出回っている + - 最近のFedoraでは `grub2.config`をいくらgrepしてもkernel情報が乗ってない +- 最近のfedoraでは次の通りにする + +### kernelの変更 +- `$ grubby --info=ALL` を実行して、切り替えたいkernelを探す +- `$grubby --set-default /boot/vmlinuz-4.2.0-1.fc23.x86_64`で切り替える + +### 参考 +- [Working with the GRUB 2 Boot Loader](https://docs.fedoraproject.org/en-US/fedora/rawhide/system-administrators-guide/kernel-module-driver-configuration/Working_with_the_GRUB_2_Boot_Loader/) + + + +## gdbでdebugするには(学内限定) +1. debugしたいvmを`ie-virsh define-gdb`でdefineしなおす + - すでにdefineしていたらundefineする + - gdbのportが開放されたxmlファイルが生成される +2. `ie-virsh dumpxml 04(defineした番号)`で、gdbのportを確認する +3. `ie-virsh strart 04`して起動する +4. kernelから転送したvmlinuxをgdbで `gdb vmlinux`する +5. breakpointを設定する +6. `target remote localhost:(確認したport)`にするとVMに接続される +7. `c`してあとは自由に!! + +# Tips +- dalmoreのvirshのxmlを書き換えるにはroot権限が必要 \ No newline at end of file
--- a/Raku.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Raku.md Wed Dec 16 15:11:16 2020 +0900 @@ -6,4 +6,8 @@ - 公式Document - https://docs.raku.org/ - - `docs.perl6.org`のものは古いので見ない \ No newline at end of file + - `docs.perl6.org`のものは古いので見ない + +# contents + +$lsx(/Raku) \ No newline at end of file
--- a/Raku/build.md Wed Dec 16 15:04:03 2020 +0900 +++ b/Raku/build.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,9 +1,53 @@ # macos 上で Raku を build する git clone https://github.com/rakudo/rakudo.git - + ## 以下を実行する - perl Configure.pl --prefix=/Users/one/src/Perl6/rakudo_build --gen-moar --gen-nqp --backends=moar --moar-option='--compiler=clang' --moar-option='--static' - -static にしないと moar のshared libraryを見つけられないらしい。開発用なら、これで良いのではないか。 \ No newline at end of file +``` + export RB=/Users/one/src/Perl6/rakudo_build + export DYLD_FALLBACK_LIBRARY_PATH=$RB/lib + perl Configure.pl --prefix=$RB --gen-moar --gen-nqp --backends=moar --moar-option='--compiler=clang' +``` + +失敗する + +## nqp/MoarVM/Configure.pl* を修正する + +``` +diff --git a/Configure.pl b/Configure.pl +index 69351ff52..13d9b30c8 100755 +--- a/Configure.pl ++++ b/Configure.pl +@@ -201,14 +201,14 @@ if ($^O eq 'darwin') { + if ($gnu_toolchain && $gnu_count != scalar @check_tools) { + print "\nNot all tools in the toolchain are GNU. Please correct this and retry.\n" + . "See README.markdown for more details.\n\n"; +- exit -1; ++ # exit -1; + } + + ## Otherwise, make sure that none of them are GNU + elsif (!$gnu_toolchain && $gnu_count != 0) { + print "\nGNU tools detected, despite this not being a GNU-oriented build.\n" + ." Please correct this and retry. See README.markdown for more details.\n\n"; +- exit -1; ++ # exit -1; + } + } +``` + +もう一度、 + +``` + perl Configure.pl --prefix=$RB --gen-moar --gen-nqp --backends=moar --moar-option='--compiler=clang' +``` + +する。 + + +## おまけ + +moar を --moar-option="-static" にしても、nqp-m とかが同じ問題を言ってくる。LD_LIBRARY_PATH ではダメらしい。 + +https://stackoverflow.com/questions/3146274/is-it-ok-to-use-dyld-library-path-on-mac-os-x-and-whats-the-dynamic-library-s \ No newline at end of file
--- a/growi.md Wed Dec 16 15:04:03 2020 +0900 +++ b/growi.md Wed Dec 16 15:11:16 2020 +0900 @@ -7,4 +7,16 @@ - plantumlで記述できる - https://plantuml.com/ - 詳しい書き方はこの辺をみる - - https://real-world-plantuml.com/ \ No newline at end of file + - https://real-world-plantuml.com/ + +# アクセス制限 + growiで作ったエントリはアクセス制限がかけれる +- 公開 +- 自分だけ +- URLを知っている人だけ +- 特定グループだけ(研究室内) + +# hackmd連携 +- 研究室のhackmd(実際はcodimd)とも連携している +- 編集するタイミングで👆のhackmdをクリックするとhackmdと同期される +- そのためgrowiで書いたエントリはhackmdでも見れる \ No newline at end of file
--- a/software.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software.md Wed Dec 16 15:11:16 2020 +0900 @@ -6,4 +6,6 @@ # contents +| 内容 | +| -------- | | $lsx(./) | \ No newline at end of file
--- a/software/CVS.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/CVS.md Wed Dec 16 15:11:16 2020 +0900 @@ -209,14 +209,14 @@ - 以下はタグの付いたポイントをcheckoutするコマンドです。 cvs-cr checkout -r [tag_name] Game_project/Test/test_program -##プロジェクトを最新の状態にする +## プロジェクトを最新の状態にする タグなどによって古いバージョンに戻したあと、再びプロジェクトを最新の状態にしたいとき。 cvs up -A オプション"A"を忘れずに付けましょう。 -##で、CVSって何よ? +## で、CVSって何よ? そんなあたなにプレゼント -[[CVSの使い方:http://nile.ulis.ac.jp/ yuka/memo/cvs.html]] +[CVSの使い方](http://nile.ulis.ac.jp/~yuka/memo/cvs.html) CVSについてさらに知りたければ、研究室にCVS関連の本がありますのでどうぞ。もしくは Let's google!!
--- a/software/FreeMind.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/FreeMind.md Wed Dec 16 15:11:16 2020 +0900 @@ -3,7 +3,7 @@ - Javaで書かれたMindMap作成ツール -# 書き込もうとしたら泊まる場合 +# 書き込もうとしたら止まる場合 ## 原因
--- a/software/Hazelcast.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/Hazelcast.md Wed Dec 16 15:11:16 2020 +0900 @@ -163,6 +163,7 @@ ・1つのローカル内で2つのノードに見立てて立ち上げ、データをやりとりします ・相手ノードのノード名と相手側のデータの2つの入力が揃ったらそれを表示します ・データをインクリメントしてそれを繰り返します + ``` インプット: 1 アウトプット: @@ -175,6 +176,7 @@ A: 7 B : 8 A: 9 + ``` 2.調査:ノード間でトポロジー(ツリーとかリングとか)を形成したいとき、それをサポートする機能はあるか?
--- a/software/KVM/ie-virsh.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/KVM/ie-virsh.md Wed Dec 16 15:11:16 2020 +0900 @@ -49,4 +49,7 @@ - vm名を指定する必要があるが、wrapperなので全部打つ必要がないようにしている - `e155730-anatofuz` の場合は `ie-virsh start anatofuz` でいい - vm名をフルで打っても問題ない -- 起動しているvmに対しての操作はidを指定しても問題ないようになっている \ No newline at end of file +- 起動しているvmに対しての操作はidを指定しても問題ないようになっている + +# bug +- `define-gdb`が動かない \ No newline at end of file
--- a/software/Torque.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/Torque.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,7 +4,7 @@ クラスターを利用して、実験を行う際には、Job Schedulerを用いる必要がある。 それは、他のクラスターユーザーが存在する場合に、同時に別スレッドで処理を実行してしまうならば、CPUなどのリソースを取り合うことになるため、台数効果などの実験結果が正確に得られないからである。 -まず、[Torqueのインストール](./install)をする。 +まず、[Torqueのインストール](./Torque/install)をする。 それでは、Torqueの使い方を見てみよう。 ## Torqueがインストールされたserverにログインする @@ -27,26 +27,26 @@ Qmgr: set queue tqueue resources_max.nodes = 2 ``` 各コマンドの意味を以下に示す。 -- create queue <queue名> queue_type = <queueのタイプ> +- `create queue <queue名> queue_type = <queueのタイプ>` - 指定された名前、タイプのqueueを作成する。 - タイプはE,executionを指定するとexecution queueになりR,routeを指定するとrouting queueとなる。 -- set queue <queue名> <Attributes> +- `set queue <queue名> <Attributes>` - 指定したqueueの指定したAttributesを設定する。 例で設定したAttributesについて -- enabled = <true or false> +- `enabled = <true or false>` - trueにすると新しいjobを受け付ける。 -- started = <true or false> +- `started = <true or false>` - trueにするとqueueの中のjobの実行を許可する。 -- resources_max.ncpus = <cpu数> +- `resources_max.ncpus = <cpu数>` - queueに割り当てるcpu数を設定する。 -- resources_max.nodes = <node数> +- `resources_max.nodes = <node数>` - queueに割り当てるnode数を設定する。 -- set server <Attributes> +- `set server <Attributes>` - 指定したqueueの指定したAttributesを設定する。 例で設定したAttributesについて -- default_queue = <queue名> +- `default_queue = <queue名>` - 指定したqueueをデフォルトqueueとする。 -- scheduling = <true or false> +- `scheduling = <true or false>` - Schedulingを可能にする。 ここまでの設定の確認を行う。 @@ -63,70 +63,82 @@ ### 設定の保存 以下のようにリダイレクトして保存する。 -``` - # echo "p s" | <torqueのインストール先>/bin/qmgr > <ファイル名> -``` +`#echo "p s" | <torqueのインストール先>/bin/qmgr > <ファイル名>` 次回以降はこのファイルを与えることで設定が楽になる。 ファイルの与え方もリダイレクト - # <torqueのインストール先>/bin/qmgr < <ファイル名> -#Torque チュートリアル +` # <torqueのインストール先>/bin/qmgr < <ファイル名>` + +# Torque チュートリアル -##Torqueを使用する前に +## Torqueを使用する前に Torqueは、naha.ie.u-ryukyu.ac.jp上で使用することができる。 実験を行うためには、パスワードを使用せずにsshできるように、鍵認証の設定を行わなくてはならない。しかし、mauiユーザーでは既に設定が行われているため、Torqueをすぐに使用することができるようになっている。 +``` % ssh ie-user@tino-vm1.ads.ie.u-ryukyu.ac.jp +``` 尚、パスワードはサーバー班が管理しているので、サーバー班から教えてもらうことができる。 ログインすると、ホームディレクトリにProjectフォルダがあるので、その中に自分の学籍番号のフォルダを作成し、その中で作業を行うようにする。 +``` % mkdir student/eXX57XX % cd student/eXX57XX +``` 追記 ただし, Projectフォルダは分散環境上で共有されていないため, ファイルを共有したい場合は /mnt/data/* の中にworkspaceを作り, その中で作業を行うのが望ましい. -##Torque上でジョブを実行する -###ジョブを実行するための準備 +## Torque上でジョブを実行する +### ジョブを実行するための準備 jobs.shを作成する。 +``` - jobs.sh #!/bin/sh echo hello hostname +``` -###ジョブの実行 +### ジョブの実行 Torqueのジョブは、qsubコマンドによって投入される。 - % qsub jobs.sh + + `% qsub jobs.sh` + このように実行すると、1台のクラスターでのみ処理が行なわれる。 -###ジョブの実行結果 +### ジョブの実行結果 スクリプトの実行が終わると、jobs.sh.oXXX, jobs.sh.eXXXという2つのファイルが生成される。XXXは、Torqueによって割り振られたジョブ番号である。 ファイルにはそれぞれ、標準出力と、標準エラー出力の内容が出力されている。 +``` % cat jobs.sh.oXXX hello cls001.cs.ie.u-ryukyu.ac.jp +``` -###複数のノードを用いた実験 +### 複数のノードを用いた実験 また10台で実験を行うには次のように、実行すれば良い。 +``` % qsub -l nodes=10 jobs.sh % cat jobs.sh.oXXX hello cls010.cs.ie.u-ryukyu.ac.jp +``` 10台のノードを指定しても、実際には10台が使用可能になっただけであり、10台で実行された訳ではない。 このcls010.csは、親ノードである。この親ノード(cls010.cs)から、他のノード(cls001-cls009)に対して、命令を行うようにプログラミングする必要がある。 例えば、以下のような処理を行う必要がある。 +``` - jobs.sh #!/bin/sh #PBS -N ExampleJob @@ -136,6 +148,7 @@ ssh $serv hostname & done wait +``` #PBSを用いてコメントをつけると、その部分が、qsubコマンドのオプションとして認識される。 - -N: ExampleJob.oXXXのように、ジョブに名前を付けることができるようになる。 @@ -143,6 +156,7 @@ 親ノードのシェルには、$PBS_NODEFILEという、環境変数が準備されている。 +``` - (例) % echo $PBS_NODEFILE /var/spool/torque/aux/XXX.naha.ie.u-ryukyu.ac.jp @@ -151,11 +165,13 @@ cls009.cs.ie.u-ryukyu.ac.jp ...(略)... cls001.cs.ie.u-ryukyu.ac.jp +``` $PBS_NODEFILEの先頭行のホストが親ノードである。 このスクリプトを実行してみると、以下のようになった。 +``` % qsub jobs.sh % cat ExampleJob.oXXX cls003.cs.ie.u-ryukyu.ac.jp @@ -168,50 +184,65 @@ cls005.cs.ie.u-ryukyu.ac.jp cls002.cs.ie.u-ryukyu.ac.jp cls001.cs.ie.u-ryukyu.ac.jp +``` このように、10台のノードで、hostnameコマンドを実行した結果が表示されていることが分かる。 これらの他に、mpiを用いて、他のノードにジョブを割り振ることもできる。 -##1ノード2CPUを用いた実験方法 +## 1ノード2CPUを用いた実験方法 クラスターはCoreDuoを搭載しているため、CPUを2つまで使用することができる。つまり、1ノードで、2つの処理を行なうことができる。 その場合は、以下のように実行する。 +``` % qsub -l nodes=10:ppn=2 jobs.sh +``` この場合、$PBS_NODEFILEには、同じホストが2つずつ登録されていることになる。 -##1ジョブでマルチタスクの実行 +## 1ジョブでマルチタスクの実行 また、1つのジョブで、複数の同じタスクを実行することもできる。 その場合は、以下のように実行する。 +``` % qsub -t 1-3 -l nodes=10 jobs.sh +``` この場合、出力結果も3つのタスクごとに出力される。 -&ref(torque_qsub.png); -##その他、便利なコマンド +## その他、便利なコマンド +``` - jobs.sh #!/bin/sh #PBS -N ExampleJob #PBS -l nodes=1,walltime=00:01:00 sleep 10 echo hello +``` +``` % qsub jobs.sh +``` sleepを行って、ジョブを長引かせてテストする。 +``` % qstat Job id Name User Time Use S Queue ___ XXX.naha ExampleJob maui 0 R batch +``` このように、ジョブの状態を確認することができる。 -##Error 対処メモ +## Error 対処メモ Nodeの数を4 9台に設定するとなぜかjobがうまく動かない。以下のようなエラーがでる。 +``` qsub: Job exceeds queue resource limits MSG=cannot satisfy queue max nodes requirement +``` 対処法はNodeの数の設定時に、一桁だった場合は 05 といったように0をつけることで解決する。 +``` % qsub -l nodes=05 test.sh +``` 全体で登録しているNodeの数が二桁になるとこうする必要がある。 また、Nodeの数を間違っていなくても、上のエラーがでるときがある。その時は今使っているqueueの設定をみる。 +``` % qmgr -c "p s" : create queue cqueue @@ -220,13 +251,16 @@ set queue cqueue resources_max.nodes = 46 set queue cqueue enabled = True set queue cqueue started = True +``` ncpus の値やnodesの値を確認する。resource_max.nodes でなく、 resource_max.nodect も設定したほうがいいかもしれない。 +``` % sudo qmgr set queue cqueue resources_max.nodect = 46 +``` -##crとcsの両方のtorqueクラスタを1つで使う +## crとcsの両方のtorqueクラスタを1つで使う crで作成したtorqueのクラスタをcsの方でまとめて使うための方法。 以下の2つの設定変更により行える @@ -234,12 +268,17 @@ - 親のtorqueのnodesの設定にcrのクラスタの情報を付け加える。 上記の変更をpbsをstopさせて変更を行う。 +``` % sudo /etc/init.d/torque stop -###クライアント側のserver_nameファイルとconfigファイルをmass00.cs(親)の設定に変更する +``` +### クライアント側のserver_nameファイルとconfigファイルをmass00.cs(親)の設定に変更する 変更するファイルは以下の2つ +``` /var/spool/torque/server_name /var/spool/torque/mom_priv/config +``` それぞれの中身をみてみる +``` mass01(cr) % cat /var/spool/torque/server_name mass00.cr.ie.u-ryukyu.ac.jp mass01(cr) % cat /var/spool/torque/mom_priv/config @@ -248,6 +287,7 @@ $ideal_load 1.0 $pbsserver mass00.cr.ie.u-ryukyu.ac.jp $restricted mass00.cr.ie.u-ryukyu.ac.jp% +``` 上記のmass00.crをmass.csに変更すればよい ###親のtorqueのnodesの設定にcrのクラスタの情報を付け加える @@ -255,6 +295,7 @@ /var/spool/torque/server_priv/nodes 中にはクライアントとなるサーバのドメインと使用するcpuの数の記述がある。 +``` % sudo cat /var/spool/torque/server_priv/nodes mass02.cs.ie.u-ryukyu.ac.jp np=4 mass03.cs.ie.u-ryukyu.ac.jp np=4 @@ -262,11 +303,14 @@ :略 mass46.cs.ie.u-ryukyu.ac.jp np=4 mass47.cs.ie.u-ryukyu.ac.jp np=4 +``` これにmass01.cr.ie.u-ryukyu.ac.jp といったcr側のクライアントの情報を追加してあげればよい。 設定が終わったら +``` % sudo /etc/init.d/torque start +``` をして起動させる。 クライアント全部を手作業でやるのは面倒臭いのでcapistrano を使ってください。 @@ -274,9 +318,12 @@ ### 力技(rootのゴリ押し) 例えばie-user@tino-vm1.ads.ie.u-ryukyu.ac.jp で +``` mkdir /mnt/data/fuga +``` と作成しようとしてもPermmision Errorになる. また, rootで作成しても +``` sudo mkdir /mnt/data/fuga ls -l /mnt/data 合計 48 @@ -284,22 +331,27 @@ drwxr-xr-x 2 ie-user ie-user 4096 8月 9 2016 examples drwxr-xr-x 2 nfsnobody nfsnobody 6 1月 24 06:08 fuga ... +``` となり, usernameとgroupが違うため, 他のvmがfugaにアクセスできない. (そもそも, このvmでもsudoがないとファイルが書き込めないはず. このファイルを管理しているのはtino-vm2の方なので, そこにアクセスしてファイル権限を書き換える +``` ssh tino-vm2.ads.ie.u-ryukyu.ac.jp # /exports/data がmountされていたため, この中のfugaを変える sudo chown -R ie-user:ie-user /exports/data/fuga exit +``` その後ファイルを見てみると書き換わっている +``` ls -l /mnt/data 合計 48 ... drwxr-xr-x 2 ie-user ie-user 4096 8月 9 2016 examples drwxr-xr-x 2 ie-user ie-user 6 1月 24 06:08 fuga ... +``` ただゴリ押しなので他の方法もあるかも. (というか普通は管理者に言うべきなんだろうなぁ....
--- a/software/Torque/install.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/Torque/install.md Wed Dec 16 15:11:16 2020 +0900 @@ -2,7 +2,6 @@ Torqueは、Job Schedulerである。Job Schedulerは、クラスターに次々と投入されるジョブを、キューなどを用い、スケジューリングを行って管理してくれる。 クラスターを利用して、実験を行う際には、Job Schedulerを用いる必要がある。 それは、他のクラスターユーザーが存在する場合に、同時に別スレッドで処理を実行してしまうならば、CPUなどのリソースを取り合うことになるため、台数効果などの実験結果が正確に得られないからである。 - それでは、Torqueの使い方を見てみよう。 # Torqueの設定 @@ -26,9 +25,10 @@ # make && make install ``` - torqueはデフォルトではscpを用いるが、rcpを用いたい時には configureを実行する時点で --with-rcpオプションを指定し、`=<rcpの場所>`としなければならない。 + ## ポートの設定 +``` Torqueが使用するポートについて/etc/servicesに記述する。以下に記述例を示す。 -``` pbs 15001/tcp # pbs_server pbs_mom 15002/tcp # mom to/from server pbs_resmom 15003/tcp # mom resource management requests @@ -47,14 +47,119 @@ ## スケジューラの設定(サーバー側) スケジューラの設定は$Torque/sched_priv/sched_configで行える。デフォルトではFIFOスケージューら。 - ## 設定の反映(サーバー側) サーバーとスケジューラの設定を反映させるために一度pbs_serverを停止させなければならない。 ``` # killall pbs_server ``` +## ノードファイルの作成(サーバー側) +$Torque/sched_priv/nodes を編集する。以下に例を示す。 +``` + nodeA np=1 + nodeB np=1 + nodeC np=1 +``` -## ノードファイルの作成(サーバー側) +user側からはpbsnodesで見ることができる。 + +## 計算ノード用のconfigファイル作成(計算ノード側) +$Torque/mom_priv/config を編集。編集例を以下に示す。 + logevent 0x1ff + max_load 1.2 + ideal_load 1.0 + clienthost <管理サーバー> +- logevent + - ログレベルの指定。この場合デバッグレベル。 +- max_load + - 使用できるCPU資源の限界。この値を超えない。 +- ideal_load + - 使用するCPU資源の最適値。cpu数に合わせると良い。 +- clienthost + - 管理サーバーの指定を行う。 + +## 起動スクリプトの作成 +以下のようなスクリプトを作り、/etc/rc.d/init.d以下に保存する。 +```sh + #!/bin/sh + # + # pbs This script will start and stop the PBS daemons + # + # chkconfig: 345 85 85 + # description: PBS is a batch versitle batch system for SMPs and clusters + # + # Source the library functions + . /etc/rc.d/init.d/functions + PBS_HOME=/var/spool/torque + + # let see how we were called + case "$1" in + start) + echo "Starting PBS daemons: " + if [ -x /usr/local/torque/sbin/pbs_mom ] ; then + if [ -f $PBS_HOME/mom_priv/config ] ; then + echo -n "Starting pbs_mom: " + daemon /usr/local/torque/sbin/pbs_mom + echo + fi + fi + if [ -x /usr/local/torque/sbin/pbs_sched ] ; then + if [ -d $PBS_HOME/sched_priv ] ; then + echo -n "Starging pbs_sched: " + daemon /usr/local/torque/sbin/pbs_sched + echo + fi + fi + if [ -x /usr/local/torque/sbin/pbs_server ] ; then + if [ -d $PBS_HOME/server_priv ] ; then + echo -n "Starting pbs_server: " + daemon /usr/local/torque/sbin/pbs_server -a true + echo + fi + fi + ;; + stop) + echo "Shutting down PBS: " + if [ -x /usr/local/torque/sbin/pbs_server ] ; then + if [ -d $PBS_HOME/server_priv ] ; then + echo -n "Stopping pbs_server: " + killproc pbs_server + echo + fi + fi + if [ -x /usr/local/torque/sbin/pbs_sched ] ; then + if [ -d $PBS_HOME/sched_priv ] ; then + echo -n "Stopping pbs_sched: " + killproc pbs_sched + echo + fi + fi + if [ -x /usr/local/torque/sbin/pbs_mom ] ; then + if [ -f $PBS_HOME/mom_priv/config ] ; then + echo -n "Stopping pbs_mom: " + killproc pbs_mom + echo + fi + fi + ;; + status) + status pbs_server + status pbs_mom + status pbs_sched + ;; + restart) + echo "Restarting PBS" + $0 stop + $0 start + echo "done." + ;; + *) + echo "Usage: pbs {start|stop|restart|status}" + exit 1 + esac +``` + +このように、"ノード名 np=<ノードのcpu数>と記述する。 +## 実行 先ほど作成したスクリプトから実行する。 ``` # /etc/rc.d/init.d/torque start
--- a/software/hg.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/hg.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,317 @@ # hg -- mercurial \ No newline at end of file +- クロスプラットフォームの分散型バージョン管理システム +- 全てのコマンドはhgから始まる +- mercuryが水銀を意味し、その元素記号がHgであることに由来する + - https://www.mercurial-scm.org/ + +# 研究室のmercurial web +- http://www.cr.ie.u-ryukyu.ac.jp/hg + + + +## 使い方(コマンドライン編) + +### インストール +HomeBrewを使用する。 + + brew install mercurial + +でインストール出来る。 + +### hgwebの修正 + +brew upgrade mercurialでhgwebが動かなくなった時には、 +/var/www/cgi-hg/index.cgi の以下の行を修正する。 + +``` +import sys +sys.path.insert(0, "/usr/local/Cellar/mercurial/5.0/lib/python2.7/site-packages") +``` + +一応修正スクリプトを生成しました + +dateを絶対表示にするのは、 +`/usr/local/Cellar/mercurial/4.4.2/lib/python2.7/site-packages/mercurial/templates/static/mercurial.js` +の function age をなおしてしまうのが良い。添付ファイルにあるので、それと入れ替える。 + +### リポジトリの初期化(init) +管理したいディレクトリ内で以下のコマンドを実行する。 + +``` + hg init +``` + +### ファイルをリポジトリに追加(add,commit) +ファイルをリポジトリに追加する場合、以下のコマンドを実行する。 + +``` + hg add ファイル名 +``` + +addで追加対象を設定し、commitでリポジトリに反映させる。 + +``` + hg commit +``` + +### リポジトリを複製(clone) +リポジトリを手元に複製し、作業をそこで行う。 + +``` + hg clone ssh://one@firefly.cr.ie.u-ryukyu.ac.jp/リポジトリ名 ローカル名 +``` + +### 履歴の閲覧(log) +複製したディレクトリ内で実行する。リポジトリ に起きたすべての出来事の要約を、最新のものから時間を遡って表示する。 + +``` + hg log + + changeset: 46:98c2bbeaecb4 + tag: tip + user: convert-repo + date: Tue Nov 18 02:12:32 2008 +0000 + summary: update tags +``` + +### 変更の確認(diff) +変更の内容を確認する時は、以下のコマンドを実行する。 + +``` + hg diff +``` + +### ファイルの削除(remove) +ファイルを削除する時は、以下のコマンドを実行する。 + +``` + hg remove ファイル名 +``` + +このままでは削除されていないので、commitを行うとリポジトリに反映される。 + +### commit前の状態に戻す(revert) +誤って削除してしまったり、変更してしまった場合も、commit前なら変更内容を無かった事に出来る。 + +``` + hg revert --all +``` + +### タグを打つ(tag) +チェンジセットに独自の識別子を付ける。 + +``` + hg tag タグ名 +``` + +### サーバーのリポジトリの変更内容を反映する。(pull) +変更内容の同期をとるため、サーバーから変更内容を取得する。 + +``` + hg pull ssh://one@firefly.cr.ie.u-ryukyu.ac.jp/リポジトリ名 +``` + +### サーバーに変更内容を反映する。(push) +手元にある変更したファイルをサーバー側に反映させる。 + +``` + hg push ssh://one@firefly.cr.ie.u-ryukyu.ac.jp/リポジトリ名 +``` + +## hgignoreに書いたファイルを削除したい時 + +``` +$ hg forget "set:hgignore() and not ignored()" +``` +cf. https://stackoverflow.com/questions/19820020/hg-remove-all-files-listed-in-hgignore + +## 基本的な使い方 +### はじめ + +hg commit したら、 + +hg push する前に、 + + hg incoming + +してみて、他の人が commit してないかどうかを見る。 + +### 衝突無し +なかったら、そのまま hg push する。 +そして、hg incoming して、自分のがtopだったら[終り]。 + +そうではなかったら、やっぱり[衝突あり] (pushの瞬間に割り込まれた...) + +### 衝突あり +何かあったら、 + +``` + hg pull +``` + +する。すると、hg heads で、pull した version が出る。これを +merge してやれば良い。hg pull で取れたのが、例えば、(localで) 255だったら、 + +``` + hg merge -r 255 +``` + +とする。 + +で、conflict をvi/emacs で修正して、 + +``` + hg commit +``` + +で、[はじめ]に戻る。 + + + +### リポジトリからファイルを取り除く (convert) +間違えて登録してしまったファイルを最初からなかったかのように跡形もなく消す方法。(forget等と異なり過去のバージョンからも消される) +まず最初に、消したいファイルのファイルパスを適当なファイルに以下のようにして記述する。 +``` + exclude "<file path>" +(例 : convert.txt) + + exclude "history/black.txt" + exclude "history/black2.txt" + exclude "aua" #ディレクトリ指定も可能。 + include "aua/auaua.txt" #指定したディレクトリ内のあるファイルのみ保持するときはincludeで指定。 +``` + +次に、hgrcに以下の記述を加えてconvertを利用出来るようにする。 +``` + [extensions] + hgext.convert= +``` + +それから以下のようにコマンドを打ち、convertする。 +``` + hg convert --filemap <削除ファイルのパスを書いたファイル> <対象リポジトリ> <新しく作られるリポジトリのパス> +``` + +convertが完了したら一度`hg update`を行う必要がある。 +updateしたらhg log等でリポジトリが正しく作成されているか確認し、find等を用いて指定したファイルが削除されているかも確認する。ファイルが消えてない場合大抵convert用のファイルの記述が正しいか、漏れがないか等を確認。 + +うまくいっていたら、元のリポジトリの.hg/hgrcを新しいリポジトリにコピーする。そして元のリポジトリを削除して新しい方をrenameすれば完了。 + +### convert作業例(.svnを間違えて入れちゃったので消す場合) + + +``` + find ./ -name .svn > convert.txt #.svnの場所を探してconvert.txtに出力。 + sed -e "s/\.\/\//exclude \"/g" convert.txt #convert.txt内の .// を exclude " に、.svn を " に置換。 + sed -e "s/\.svn/\"/g" convert.txt + hg convert --filemap ./exclude.txt ../GCC_original ../GCC_original_rm_svn #convert(この前にhgrcでconvertを有効にしておく) + cd ../GCC_original_rm_svn + hg update # updateしないとファイルが構成されない。 + hg log # 正しく作成されているかの確認。 + find ./ -name .svn #ちゃんと消えているかの確認。 + cp ../GCC_original/.hg/hgrc ./hg/hgrc #hgrcのコピー。 + cd .. + rm -r GCC_original #元の削除 + mv GCC_original_rm_svn GCC_original #rename +``` + + +### メールでのpatch送信方法 + +メールで、最新のcommitをpatchとして送信する方法。 + +メールを送信したいlocalの /.hgrc を送信元の名前やメールの設定を追加編集する。 + +``` + [email] + method = smtp + from = Name <mail-address> + [smtp] + host = smtp.gmail.com + port = 587 + tls = starttls + username = mail-address +``` + + +送信したいrepositoryの .hg/hgrc に、送信先のメールアドレスを設定する。 + +``` + [email] + to = mail-address +``` + + +patchをメールで送信するコマンドは以下。 + +``` + $ hg email . +``` + +最初、abortが出る。 + +``` + abort: smtp.gmail.com certificate with fingerprint 9c:0a:cc:93:1d:e7:51:37:90:61:6b:a1:18:28:67:95:54:c5:69:a8 not verified + (check hostfingerprints or web.cacerts config setting) +``` + +abortで出たfingerprintを、メールを送信したいlocalの /.hgrc に追加する。 + +``` + [hostfingerprints] + smtp.gmail.com = 9c:0a:cc:93:1d:e7:51:37:90:61:6b:a1:18:28:67:95:54:c5:69:a8 +``` + +Gmailを使用する際、 +「安全性の低いアプリがアカウントにアクセスするのを許可する」 +設定が必要となる場合がありますので、もしエラーが出たら設定してください。 +https://support.google.com/accounts/answer/6010255 + +これらの設定で、patchをメールで送信することが出来るようになります。 + + +## 使い方(Eclipse編) + +### インストール +Eclipse3.3以上にて、 +"Help"->"Software Updates"を選択し +"Add Site..."から以下のURLを入力する。 + + Name: Vectrace (Mercurial Eclipse plugin) + URL: http://www.vectrace.com/eclipse-update/ + +その後、新しく現れた項目にチェックを入れて、"install..."でインストール完了。 + +### リポジトリの追加 +"File" -> "New"-> "Project..."より、"Clone Repository using Mercurial"を選択し"Next" +URLにはコマンドラインと同じ様に + + ssh://one@firefly.cr.ie.u-ryukyu.ac.jp/リポジトリ名 ローカル名 + +を入力し、ウィザードに従い必須項目を入力する。 +成功すれば、左のウィンドウにプロジェクトが追加される。 + +### その他の操作 +ファイルを右クリックした時に現れる"Team"内にMercurialのコマンドが表示される。 +内容はコマンドラインと一緒なので説明は割愛する。 + +## リンク +- Mercurial の使い方のチュートリアル +http://www.selenic.com/mercurial/wiki/index.cgi/JapaneseTutorial +- Mercurial Eclipse +http://www.vectrace.com/mercurialeclipse/ + + +# おすすめ設定 +- ホームディレクトリの.hgrcに書いておくとおすすめの設定 + +## xcodeのdiffを開かないようにしたい +``` +[ui] +merge=internal:merge +``` + +- こう書いておくと `>>>>` `=====` `<<<<<` のgitっぽい感じでdiffが直接ファイルに書き出される + - xcodeのdiffとかvim diffは慣れてないと使いづらいので... + \ No newline at end of file
--- a/software/hg/hgignore_templates.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/hg/hgignore_templates.md Wed Dec 16 15:11:16 2020 +0900 @@ -2,6 +2,14 @@ - mercurialでむしるファイルを設定できるhgignoreのテンプレート集 - なんかコピペしてつかってください + +# つかいかた +- リポジトリ直下に `.hgignore`という名前でつくる +- `$hg add .hgignore`する +- hg statusすると、ignoreしたファイルが消えてる + +# gitignoreからのconvert +- gitignoreのファイルの先頭に `syntax:glob`と書き加えるだけでほぼそのまま使える # LaTeX @@ -36,7 +44,6 @@ # *.pdf ## Generated if empty string is given at "Please type another file name for output:" -.pdf ## Bibliography auxiliary files (bibtex/biblatex/biber): *.bbl @@ -282,103 +289,4 @@ *.glstex # End of https://www.gitignore.io/api/latex - - -# Created by https://www.gitignore.io/api/node -# Edit at https://www.gitignore.io/?templates=node - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# react / gatsby -public/ - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# End of https://www.gitignore.io/api/node ``` \ No newline at end of file
--- a/software/tmux.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/tmux.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,8 +1,10 @@ # tmuxとは -mac osでデバッグ環境を構築する -端末多重化ソフトウェア。一つのターミナル画面に複数の端末を上げることができる。 +mac osでデバッグ環境を構築する端末多重化ソフトウェア。 + +一つのターミナル画面に複数の端末を上げることができる。 + またssh先で実行することで、コネクションが切れた際にも処理を継続してくれる # ソースコード
--- a/software/usb_serial.md Wed Dec 16 15:04:03 2020 +0900 +++ b/software/usb_serial.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,7 +1,8 @@ # USB Serial通信 Raspberry piとのUSB Serial通信の仕方をまとめる。 -参考にしたサイト: [Ubuntuでラズパイ とシリアル接続](http://dotnsf.blog.jp/archives/1071983142.html) +参考にしたサイト: [Ubuntuでラズパイ とシリアル接続](http://dotnsf.blog.jp/archives/1071983142.html) +Serial通信のコマンドはいろいろあるようです。: [シリアル通信いろいろ](https://qiita.com/yamori813/items/29e6bcd2f090983abb9a) ## 環境 ### 接続先 @@ -20,7 +21,8 @@ ``` mk@raspberry:~$ raspi-config ``` -設定画面でInterface -> Serialを選択してSerial通信をEnableにします。 +設定画面でInterface -> Serialを選択してSerial通信をEnableにします。Raspberry piにUSBを以下の画像のように接続します。(赤線は接続しなくても良いっぽい) +![P_20200210_121121.jpg](/attachment/5e4277427b378d004670d0f0) 次にUbuntu側の設定です。Serial通信用のコマンドをインストールします。 ```
--- a/trash/software/Christie.md Wed Dec 16 15:04:03 2020 +0900 +++ b/trash/software/Christie.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,1 @@ -tsts \ No newline at end of file +tsts by 一木 \ No newline at end of file
--- a/user.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,1 @@ -# Gears OSにおける multi threadにおけるプログラム検証 -# 要約 -* CbC は処理の移行を goto 用いて行い、データ構造はdate gearにより保持する事でプログラムの処理をcode gear毎の独立したものにする。 -* Geas OS はCbCで記述されおり、処理を変更する事なく処理の間に自由にメタ処理を挟む事ができる、これにスケジューラーを挟む事でマルチスレッド処理などが可能となる。 -* メタ計算部分にモデルチェッキングを入れる事でプログラムを実行しながらにして証明することが可能となる。 \ No newline at end of file
--- a/user/Itsuki/notes.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,24 +1,1 @@ -# 進捗報告 -## 研究目的 -- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. -- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 - - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 - - 編集に参加する全員がVScodeの環境を取り入れなければならない。 -- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 -- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 - -## 進捗内容 -- IntelJのプラグインを勉強してました。 - - javaでAction(Prugin部分)を作成して、pom.xmlにActionを登録するのが基本的な流れらしい。 - - Devkitを使うことでもAction登録ができる。 - - Actionを呼ぶ方法としてメニューバーから呼び出す、キーバインドなどがある。 -- デバック実行時するときにVMを立ててIntelJを起動させてる - - PCの性能のためか - -## やりたいこと -- Christie読み会 - - 前回話していたやつ、過去にDaemonからの流れを呼んでいたのですが、、 -- OS再勉強 - - 内容もだいぶ変わったみたいなので、夏休みに教えれるぐらいには -- シス管のタスクに触れてみたい - - Q.期限とかあるんですか? \ No newline at end of file +- note \ No newline at end of file
--- a/user/Itsuki/notes/11-24.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/11-24.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,47 @@ -tsts \ No newline at end of file +# 進捗報告 +## 研究目的 +- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. +- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 + - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 + - 編集に参加する全員がVScodeの環境を取り入れなければならない。 +- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 +- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 +- 既存のエディタのセッション実現の始めとしてIntelliJでの接続を試みる。 + +## 進捗内容 +### リモートエディタ +- Christieプロジェクトに後付けでプラグインの環境を組み込もうとしていた + - とりあえずChristieからプラグイン刺した状態でRunできるように + - やっぱり依存関係でつまづいてた(plugin.xml内のdepends表記) + - build.gradleのIntellijのversion指定も大事だった。 + - 正直まだ理解不足な感じかも + +- インターンシップ(という名の企業説明会)に参加してきた + - 社会のニュースは知っておけと言われた。 + - 周りみんな高学歴でうぐぐってなった + +- 気分が浮かない時は本読みしてました + - TCP/IPをかっちり読み直してる(つもり) + - 集中力がだんだん伸びてきた気がする + + + +### 次やること +- Intellijのプラグインの調査 +- Intellij上でリアルタイムで変化を観測したい + +## その他 +- 新しい題材を探したいです + - Gearsとかネットワーク周り触りたいです。 + +- 課題の論文紹介を始めます + - タイトルは「Extending Shared-Memory Computations to Multiple Distributed Nodes」なるもの + +- christieのNAT越えをやりたいと思っていた。 + - IPv4がこれから廃れると考えると確かに魅力ない.. + +- 飲食店バイトを年内に辞める報告してきました + - 研究がんばります。 + - 「夜勤はやめとけ」 + +
--- a/user/Itsuki/notes/11/10.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/11/10.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,35 @@ -tsts \ No newline at end of file +# 進捗報告 +## 研究目的 +- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. +- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 + - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 + - 編集に参加する全員がVScodeの環境を取り入れなければならない。 +- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 +- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 +- 既存のエディタのセッション実現の始めとしてIntelJでの接続を試みる。 + +## 進捗内容 +### リモートエディタ +- GradleでのIntelliJプラグインについて勉強してました。 + - Christieをコンパイルした時に一緒にプラグインも作成できるようにしたい + - ライブラリのimportができずに困っている。 + +- 複雑系講義の教科書発表を済ませた + - artisocなるモデルシミュレーターをメインにしている + - 生物の捕食被捕食の循環やウイルスの拡大のシミュレーションとかができる。 + - おもちゃっぽい(失礼)でもプログラミング初心者には楽しそうかもしれない + +### やりたいこと +- 手始めとしてプラグインからChristieが動くことを確認したい + - build.gradleとprugin.xmlをいじる様子? + +- christieのNAT越えをやりたいと思っていた。 + - IPv4がこれから廃れると考えると確かに魅力ない... + +## これからの考察、予定 +- (まだ先)IntelJのファイルへの入力への検知はどう実装するのか? +- (ずっと先)編集ファイルの共有方法や編集されたファイルの識別なども実装する。大変。 + +## その他 +- OSを再勉強する、TAをやることになったので頑張る。 +- 早起きする。 \ No newline at end of file
--- a/user/Itsuki/notes/8-25.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/8-25.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,47 @@ -* \ No newline at end of file +# 進捗報告 +## 研究目的 +- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. +- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 + - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 + - 編集に参加する全員がVScodeの環境を取り入れなければならない。 +- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 +- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 +- 既存のエディタのセッション実現の始めとしてIntelJでの接続を試みる。 + +## 進捗内容 +### リモートエディタ +- IntelJからプラグインでTopologyManagerへ接続する方法を探してました。 + - CGM(CodeGearManager)がThreadクラスを基盤に作られているのでThreadクラスのメソッドを調べてました。 + - プラグインな関係上staticなメソッドで見つけられたら楽だな〜と +- 今のところThread.getAllStackTraces()が有力そう?スタックトレース(スレッドへの仕事の割り振り履歴)を表示してくれる。 + - CGMとして作られたスレッドが検知できることはわかった。 + - TopologyManagerがどのスレッドで行われているかは判別できるかどうかが問題。 + +``` +Thread.getAllStackTraces() + +{Thread[Signal Dispatcher,9,system]=[Ljava.lang.StackTraceElement;@6d78f375, Thread[ACCEPT10000,5,main]=[Ljava.lang.StackTraceElement;@50c87b21, Thread[Reference Handler,10,system]=[Ljava.lang.StackTraceElement;@5f375618, Thread[pool-1-thread-2,5,main]=[Ljava.lang.StackTraceElement;@1810399e, Thread[main,5,main]=[Ljava.lang.StackTraceElement;@32d992b2, Thread[ACCEPT10001,5,main]=[Ljava.lang.StackTraceElement;@215be6bb, Thread[pool-1-thread-1,5,main]=[Ljava.lang.StackTraceElement;@4439f31e, Thread[Common-Cleaner,8,InnocuousThreadGroup]=[Ljava.lang.StackTraceElement;@5dfcfece, Thread[Finalizer,8,system]=[Ljava.lang.StackTraceElement;@23ceabc1} +``` + +### その他のやったこと + +- 今週は主にOSを再勉強してました(全然進んでないけど) + - Ansibleは記憶になかったので苦労しました。 +- うっかりメンテ中にyomitanにログインしようとしてロックされました(恥 + - 修正お願いしたいです。。 + - シス管のRedMineにrootパスワードでも落ちてないか探しましたが見つからず +``` +kex_exchange_identification: read: Connection reset by peer +``` + +## これからの考察、予定 +- 案:TopologyManagerを動かすスレッドには何かしら検知のための仕組みを作る? +- (まだ先)IntelJのファイルへの入力への検知はどう実装するのか? +- (ずっと先)編集ファイルの共有方法や編集されたファイルの識別なども実装する。大変。 + +## やりたいこと、その他 +- Christie読み会 + - 別マシン同士の通信を実現した形跡が見つからないので実装してみたいところ。 + - RemoteTakeあたりな記憶だけどしっかり把握できてない。 +- OS再勉強、割と時間がないので急ぎたいところ。 +- 早起きする。 \ No newline at end of file
--- a/user/Itsuki/notes/August-18.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/August-18.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,33 @@ -- \ No newline at end of file +# 進捗報告 +## 研究目的 +- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. +- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 + - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 + - 編集に参加する全員がVScodeの環境を取り入れなければならない。 +- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 +- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 +- 既存のエディタのセッション実現の始めとしてIntelJでの接続を試みる。 + +## 進捗内容 +- IntelJプラグインの基本を勉強してました。 + - java言語でAction(プラグインの中身)を作成して、pom.xmlファイルにActionを登録させるのが基本の流れ。 + - pom.xmlでなくてDevkitを使うことでも登録できるらしい。 + - Actionはメニューバーやキーバインドなどから呼び出せる。 + - デバック実行するとVMを立てた上でIntelJを呼び出すためPCが重くなってしまう + + +## これからの考察、予定 +- Topology-Managerが動いている状態をプラグインから検知,接続させる。 + - Topology-Managerは一つのCodeGearManagerが動かしている(?)のでノードのリストを見つけるところから? + - ChristieをCodeGearManagerから読む。 + +- (ずっと先)編集ファイルの共有方法や編集されたファイルの識別なども実装する。大変。 + +## やりたいこと、その他 +- 集中講義とOSの再履修が被ってしまいました。。(9/16~18と9/14~18) +- Christie読み会 +- Christieのメッセージパックの動きがだいぶ怪しいので改善(実装)したら論文のネタになりそう。 + - Javaのバージョンへの依存が強い、MsgPackは更新が終わっているらしい。 + - その他問題ありそう。 + + \ No newline at end of file
--- a/user/Itsuki/notes/June30.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/June30.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,29 @@ -tsts +# 進捗報告 +## 研究目的 +- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. +- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 + - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 + - 編集に参加する全員がVScodeの環境を取り入れなければならない。 +- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 +- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 + +## 進捗内容 +- Christieがエディタからの変更を拾う方法を探してました。 +- とりあえずMercurialと過去の論文を漁ってヒントを得る。 + - https://growi.cr.ie.u-ryukyu.ac.jp/Christie/RemoteEditorWithChristie/メモ書き に殴り書きしてました(更新中) + - 今のところ明確な手応えがない。。REPが作られたところから読むのがいいことは分かってきた。 + +- 本読みを継続中。 + - 過去の負債としてマスタリングTCP/IPを呼んでます。 + - Linuxの仕組みは読了。 +- 課題が片付いてきたと思ったらPMが増えた。 + - 一年生は優秀だけど二年生が大変。 +- 親知らずがついに無くなりました。 + +## やりたいこと +- Christie読み会 + - 前回話していたやつ、過去にDaemonからの流れを呼んでいたのですが、、 +- OS再勉強 + - 内容もだいぶ変わったみたいなので、夏休みに教えれるぐらいには +- シス管のタスクに触れてみたい + - Q.期限とかあるんですか?
--- a/user/Itsuki/notes/Merch-31.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/Merch-31.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,13 @@ -tsts \ No newline at end of file +# 進捗報告 +## 研究目的 + +## 進捗内容 +- Christieのコードを読んでいました。 + - Topology形成されてからどうコードが動いているのか?を目的に + - Daemonから読んでみてます。 + - DataGearの差込やputはコマンドパターンを使っているみたい?? + +- 本読みを意識してやってみてます。 + - 今まで読んでいて頭にスッキリ入ってないので工夫して読み直してます。 + +## タスク
--- a/user/Itsuki/notes/October-13.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/notes/October-13.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,38 @@ -- tst \ No newline at end of file +# 進捗報告 +## 研究目的 +- ペアプログラミングなど一つのファイルを複数人で編集する有効的手法の一つとして, 同じファイルを複数人が場所を 問わずに同時編集することができるリモートエディタをあげられる. +- リモートエディタ機能を持つ既存のテキストエディタとしてVisual Studio Code(VScode)のLive Share機能が挙げられる。 + - プログラマーには個人が各々慣れ親しんだ編集環境が存在する。 + - 編集に参加する全員がVScodeの環境を取り入れなければならない。 +- 参加者が好みの異なるエディタ環境で同時編集が行えるリモートエディタを作成したい。 +- 異なるマシン上のエディタ同士の通信は、当研究室が開発する分散フレームワークChristieを用いる。 +- 既存のエディタのセッション実現の始めとしてIntelJでの接続を試みる。 + +## 進捗内容 +### リモートエディタ +- Christieのソースコードで~~溺れて~~泳いでいました。 + - TopologyManagerに繋がってるCGMは通常のCGMソースを継承して作られてることがわかった。他にも似たような構成が多数。 + - DGとDGM関連も読んでました。 + - 結構時間かかりそう。 +- 正直構造が複雑で混乱している途中。 + - TopologyManagerの検索と接続が実装できればいいが。。 + + +### やりたいこと +- 別マシン間での分散処理ができるらしいがよく分かっていないのでテストしたい。 + - RemoteTake&Peekを使うらしいがどうも参考になるコードが見当たらない。 + - 引継ぎした際に参考になるようなExampleコードを作っておきたいかも。 + - だめそうだったら修正&開発したい + +- 手始めとしてプラグインからChristieが動くことを確認したい。 + - プラグインのプロジェクトにChristieのソースをそのまま載せるのは避けたい。どういう形が一番だろうか? + - HGからソースを引っ張ってくる方法が謎。 + + +## これからの考察、予定 +- (まだ先)IntelJのファイルへの入力への検知はどう実装するのか? +- (ずっと先)編集ファイルの共有方法や編集されたファイルの識別なども実装する。大変。 + +## その他 +- OSを再勉強する、TAをやることになったので頑張る。 +- 早起きする。 \ No newline at end of file
--- a/user/Itsuki/thesis.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Itsuki/thesis.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,4 +1,4 @@ -title: 分散フレームワークChristieを用いたリモートエディタの実装 +# 分散フレームワークChristieを用いたリモートエディタの実装 author: Takahiro Ikki, Shinji Kono profile: 琉球大学 lang: Japanese @@ -7,263 +7,102 @@ ## 研究目的, 背景 - リモートエディタとは別マシン上から同時に複数人が一つのファイルを編集することができる。 - ペアプログラミングやリモートワークに特に有効である。 -- 完全同期式の既存のリモートエディタアプリケーションとしてVisual Stdio Codeのlive share機能があげられる。 - - 編集環境を統一しなくてはならない。 +- 完全同期式の既存のリモートエディタアプリケーションにはVisual Stdio Codeのlive share機能がある。 + - 同時編集するには編集環境を統一しなくてはならない。 - 編集に参加するユーザーがそれぞれ好きなエディタが使えるアプリケーションを作成する。 - 本研究室で開発している分散フレームワークChristieを使って開発する。 - - ChristieはGearというプログラミング概念の性質上リモートエディタと相性がよい。 - -<!-- -## 発表の流れ -- リモートエディタの機能と開発手順の解説 - - javaで制作したテスト用エディタ - - コマンドパターンによる命令オブジェクトの作成 - - 編集位置の相違とその解消方法 -- スター型接続によるネットワーク通信 -- Christieの解説 - - Gearの概念 - - アノテーション - - TopologyManager -- 今後の課題とまとめ -!--> + - ChristieはGearというプログラミング概念の性質上、リモートエディタと相性がよい。 ## リモートエディタの概要説明 -- 本研究で作成するリモートエディタはChristieの機能を用いて通信環境を構成する。 +- 通信接続の構成や更新のやり取りはChristieが基盤となる。 - サーバーとノードに別れ、サーバーが編集ファイルの正しい状態を保持する。 -- 同期編集セッションに接続したユーザーは自身のマシン上でエディタを使って編集対象ファイルを開く。 - - ユーザーが起こしたファイルへの変更を、命令コマンドとして接続しているサーバー(ハブ)へ送信&実行させる。 +- ノードはサーバーのファイルを手元で開き編集を行える。 + - ノードが起こしたファイルへの変更を、命令コマンドとして接続しているサーバー(ハブ)へ送信&実行させる。 - 命令コマンドはサーバーへ集められ、サーバーは受け取ったコマンドを他の接続ノードへ送信し、実行させる。 -<div style="text-align: center;"> - <img src="images/RemoteEditor.pdf" alt="MetaGear" width="800"> -</div> - +![](http://ie.u-ryukyu.ac.jp/~e165713/images/RemoteEditor.pdf) ## テスト用テキストエディタ -- 通信の構成を行うChristieはjava言語で作成されているため、javaのswingを用いてテキストエディタを制作した。 +- Christieはjava言語で作成されている +- 基本構成のために、javaのswingを用いてテキストエディタを制作した。 - エディタ部分の入力、削除の取得はDocument Listenerクラスを使った。 - insertUpdate、removeUpdateメソッドがそれぞれ挿入、削除を検知した時に動作する。 -- このエディタはファイルの内容をオフセット番号で取り扱っている。 -<div style="text-align: center;"> - <img src="images/Editor.png" alt="MetaGear" width="800"> -</div> - -## DocumentListenerの記述部分 +![](http://ie.u-ryukyu.ac.jp/~e165713/images/Editor.png) ``` +textArea = new JTextArea(); +textArea.getDocument().addDocumentListener(new MyDocumentListener()); + public class MyDocumentListener implements DocumentListener { @Override public void insertUpdate(DocumentEvent e) { - Document doc = e.getDocument(); - loc = e.getOffset(); - System.out.println(loc); - + } - + @Override public void removeUpdate(DocumentEvent e) { - Document doc = e.getDocument(); - sendLoc = e.getOffset(); - System.out.println("delete " + sendLoc); + } @Override public void changedUpdate(DocumentEvent e) { + } } ``` - -## コマンドパターンの解説 -- リモートエディタの通信では、各ノード(参加ユーザのエディタ)がそれぞれ自身のファイルの変更内容を他のノードに送信する。 -- コマンドパターンとは命令を一つのオブジェクトとして表現するプログラム手法である。 -- 命令を表すクラスを作成し、インスタンスを作成と同時に命令の中身を入力することで命令を作成する。 - - リモートエディタにおいては「オフセットn番目に に 文字列 "A"を入力した」という変更を命令にして送信する。 -- コマンドパターンの利点として、 - - ChristieのGearの概念と相性がいい。 - - 命令に必要な内容をまとめて送信するため、時間差による相違の発生が防げる。 - - オブジェクトとして取り扱えるため管理が行いやすい。 - -``` - package christie.example.RemoteTake; - import org.msgpack.annotation.Message; - - @Message - class RTCommand { - public String line; - public String cmd; - public int offset; - - public RTCommand () {} +## Christie +- Christieは当研究室で開発している分散フレームワークである. +- ChristieではデータをGearという単位で分割して記述を行う。 + - Codegear、DataGear、CodeGearManager、DagaGearManagerの四種類が存在しする。 + - CodeGear = スレッド、クラス + - DataGear = 変数データ + - CodeGearManager = ノード + - DataGearManager = データベースプール - public RTCommand(String cmd, String line, int i) { - this.cmd = cmd; - this.line = line; - this.offset = i; - } - - @Override - public String toString() { - return "RTCommand{" + - "line='" + line + '\'' + - ", cmd='" + cmd + '\'' + - ", offset=" + offset + - '}'; - } - } -``` - - -## コマンドパターン実装の際に起こった問題 -- クラスを他ノードに送信するためには、クラスをシリアライズして送信する必要がある。 - - コマンドの送信にはmsgpackクラスとjavassistを利用している。 -- しかし、送信がうまく行えなかったため、原因を調査した。 - - javaのバージョン進行のため、msgpackバージョン0.6.12が非対称となっていた。 - - msgpackの最新バージョン0.8.20はシリアライズ機能が含まれなくなった。 -- 以上の原因に対処するため以下の対処を行った。 - - javassistのバージョンを最新版へ変更した。 - - シリアライズする命令クラスに対し、クラスをpublicに変更した。 -- 自身でシリアライズ機能をChristieに内蔵してしまえば、これらのパッケージは不要になる。 - -## 編集位置の相違 -- 同期編集のセッションでは命令コマンドの送信のすれ違いにより、ノードごとのファイル状態が異なってしまうことがある。 -- EditorAとEditorBはそれぞれの命令を自身のエディタバッファに施してから命令を送信するため、お互いバッファ状態が異なる状態で受け取った命令を実行してしまう。 +## CodeGear(以下CG) +- 設定されたkeyに全てのDGが格納されると動作し、DGを参照しながらクラス部分を実行できる。 -<div style="text-align: center;"> - <img src="images/difference_offset.pdf" alt="MetaGear" width="800"> -</div> - -## 編集の相違の解消 -- 同期編集のセッションはスター型の通信接続で行うため、サーバー対複数ノードの通信間で相違が発生する。 -- 編集の相違を防ぐためには二つの処理を行う必要がある。 - - サーバーとノード間の命令のすれ違いが発生したことを検知する。 - - すれ違いが発生した際に、オフセットのズレを修正する。 -- サーバーが正しいファイルの状態を保持するためサーバーの状態にノードが合わせる必要がある。 - -## 命令コマンドに番号をつけ相違を解消する -- 命令コマンド番号には以下の特性がある。 - - 全てのノード(サーバーを含める)は事前に処理した命令コマンドの番号を記憶している。 - - 新しく作られた命令コマンドは作られたノードの命令実行済み番号+1 を自身の命令コマンド番号とする。 - - ノードは自身が作成したか、他のノードに送られてきたかに関わらず命令コマンドを実行したら命令実行済み番号をその命令コマンドの番号と同じにする。 -- もしノードが送られてきた命令コマンドを見て、そのコマンドが自身の実行済み番号と同値以下の場合、送信元のノードとの命令のすれ違いが発生していることが分かる。 - -<div style="text-align: center;"> - <img src="images/FixCommand.pdf" alt="MetaGear" width="800"> -</div> - -## すれ違いが発生した際の処理 -- 全てのノードは自分が実行した命令コマンドを記録しており、後からオフセットや文字列を取り出すことができる。 -- すれ違いが発生した時点からの命令の中身を集計、参照しすれ違いで送られてきたコマンドを修正する。 -- insertを例とすると - - 受け取ったコマンドのオフセット > 受信コマンドとすれ違ったコマンドのオフセット のとき、受診したコマンドのオフセットに+1 する。 - - 受け取ったコマンドのオフセット <= 受信コマンドとすれ違ったコマンドのオフセット のとき、受診したコマンドのオフセットを変えずにそのまま実行できる。 - - - -## スター型通信 -- Christieにはノードの通信接続を行うTopologyManagerという機能がある。 -- 同期通信はスター型での接続を行う。 -- スター型通信の利点は - - サーバーが正しいファイル状態を保持するため、整合性を保つことができる。 - - どこかのノードが切断されても、要害の範囲をそのノードのみに抑えることができる。 - - 新しいノードが参加した、もしくは復帰の際にはサーバーのファイル状況を参照するのみで参加、復帰ができる。 - -<div style="text-align: center;"> - <img src="images/Star-Topology.pdf" alt="MetaGear" width="800"> -</div> - -## Christie -- Christieは当研究室で開発している、信頼性を重視した分散フレームワークである. -- 現在はjava上で開発されているが、別言語(CbC)で構成されたGearsOSに組み込む予定があるため,それに向けて書き換え可能な構成となっている。 -- ChristieではデータをGearという単位で分割して記述を行う。 - - CodeGear(以下CG) - - スレッドやクラスに相当し、javaの継承を用いて記述する。keyに全てのDGが格納された際に動作する。 - - DataGear(以下DG) - - DGは変数に相当し、CG内でアノテーションを用いてデータを取り出せる。 - - CodeGearManager(以下CGM) - - ノードに相当し, DG, CG, DataGearManagerの管理をする. - - DataGearManager(以下DGM) - - DGを管理するものであり, putという操作にて変数(DG)をkeyに格納する。 - +## DataGear(以下DG) +- CGに指定されたkeyに差し込まれる。 +- アノテーションを使って記述する。 +- ノードの同士がこのDGを差し込み合うことで通信を構成する。 + +## CodeGearManager(以下CGM) +- CGを指定してsetupすることでCGを動かすことができる。 +- putという操作でDGを対応したDGMに格納する。 +## DataGearManager(以下DGM) +- CGMが所持している。 +- プールになっておりputされたDGが保存され、keyとデータが結び付けられる。 ## Christieのコード例 ``` -package christie.example.HelloWorld; - -import christie.codegear.CodeGearManager; -import christie.codegear.StartCodeGear; - public class StartHelloWorld extends StartCodeGear { - public StartHelloWorld(CodeGearManager cgm) { - super(cgm); - } - public static void main(String[] args){ CodeGearManager cgm = createCGM(10000); cgm.setup(new HelloWorldCodeGear()); - cgm.setup(new FinishHelloWorld()); cgm.getLocalDGM().put("helloWorld","hello"); cgm.getLocalDGM().put("helloWorld","world"); } } ``` - ``` -ChristieDaemon.listen: bind to /0:0:0:0:0:0:0:0:10000 hello world ``` -<!-- -- 立ち上げ後はManager名を指定してDataSegmentAPI用いてDSのやり取りを行うため、プログラマはManager名を意識することでLocalへの操作もRemoteへの操作も同様に扱える。 ---> - -<!-- - -## Christieの言語概念 -- CGはスレッド, クラスに相当し, javaの継承を用いて記述する. -- DGは変数データに相当し, CG内でアノテーションを用いて変数データを取り出せる. -- CGMはノードであり, DG, CG, DGMを管理する. -- DGMはDGを管理するものであり, putという操作により, 変数データ(DG)を格納できる. - - DGMにはLocalDGMとRemoteDGMが存在する。LocalDGMは各ノード固有のデータベースである。RemoteDSMは他ノードのLocalDGMに対応するproxyであり、接続しているノードの数だけ存在する。 - - DGMのput操作を行う際にはLocalとRemoteのどちらかを選ぶ.Localであれば、LocalのCGMが管理するDGMに対しDGを格納し, Remoteの場合は接続したRemoteさきのCGMのDGMにDGを格納する. - ---> - - -## DGM -- CGMはDGをputという操作を使って、自身や他ノードのDGMに書き込ませる。 - - LocalDGMが自身、RemoteDGMが他ノードのDGMである。 - -<div style="text-align: center;"> - <img src="images/remote_datasegment.pdf" alt="MetaGear" width="800"> -</div> - - -<!-- -- RocalDGMを立ち上げるにはDataSegmentクラスが提供する、connectメソッドを用い、接続したいポートのipアドレスとport番号、そして任意のManager名を指定することで立ち上げる。 ---> - - ## DGのアノテーション -- DGを取り出す際にはCG内で宣言した変数にアノテーションをつける。DGアノテーションには -Take、Peek、TakeFrom、PeekFrom、の4つがある。 +- DGを取り出す際にはCG内で宣言した変数にアノテーションをつける。 +- DGアノテーションにはTake、Peek、TakeFrom、PeekFrom、の4つがある。 - Take - - 先頭のDGを読み込み、そのDGを削除する。 + - DGMに保管された先頭のDGを読み込み、そのDGを削除する。 - Peek - - 先頭のDGを読み込むが、DGが消去されない。そのため特に操作をしない場合、同じデータを参照し続ける。 + - DGMに保管された先頭のDGを読み込むが、DGが消去されない。そのため特に操作をしない場合、同じデータを参照し続ける。 - TakeFrom - Remote DGM nameを指定することで、その接続先のDGM からTake操作をおこえる。 - PeekFrom - Remote DGM nameを指定することで、その接続先のDGM からPeek操作をおこえる。 ``` -package christie.example.HelloWorld; - -import christie.annotation.Peek; -import christie.annotation.Take; -import christie.codegear.CodeGear; -import christie.codegear.CodeGearManager; - public class HelloWorldCodeGear extends CodeGear { @Take @@ -273,17 +112,35 @@ protected void run(CodeGearManager cgm) { System.out.print(helloWorld + " "); cgm.setup(new HelloWorldCodeGear()); - cgm.getLocalDGM().put(helloWorld,helloWorld); } } ``` -<!-- +#### LocalDGMとRemoteDGM +- CGMはDGをputという操作を使って、自身や他ノードのDGMにDGを書き込ませる。 +- DGMにはLocalDGMとRemoteDGMが存在する。 + - LocalDGMは各ノード固有のデータベースである。 + - RemoteDGMは他ノードのLocalDGMに対応するプールであり、接続しているノードの数だけ存在する。 +- DGMのput操作を行う際にはLocalとRemoteのどちらかを選ぶ. + - Localであれば、LocalのCGMが管理するDGMに対しDGを格納。 + - RemoteDGMを指定してputすることで、接続している任意のノードにDGを差し込ませることができる。 + +``` +cgm.getDGM("nodeB").put("Command" , cmd); +``` + +![](http://ie.u-ryukyu.ac.jp/~e165713/images/remote_datasegment.pdf) + ## TopologyManager -- TopologyManagerとはTopologyを形成のために、参加を表明したノード、TopologyNodeに名前を与え、必要があればノード同士の配線を行うノードである。 -- TopologyManagerのTopology形成方法として、静的Topologyと動的Topologyがある。 - - 動的Topologyは参加を表明したノードに対し、動的にノード同士の関係を作る。例えばTreeを構成する場合、参加したノードから順にrootに近い役割を与え、またCodeGearはノードが参加し、parentに接続された後に実行される。 - - 静的Toopologyはdotファイルを与えることノード関係の構築を行う。 +- 通信形成をより簡潔に行ってくれる機能である。 + - Topologyに参加を表明したノードを自動的に配線する。 + - 自動的に接続しているノードに相対的にラベルをつける。 +- 静的Topology形成 + - dotファイルを与えることノード関係の構築を行う。 + - ノード数が想定と一致しないと動作しない。 +- 動的Topology形成 + - 参加を表明したノードに対し、動的にノード同士の関係を作る。 + - 例えばTreeを構成する場合、参加したノードから順にrootに近い役割を与える。 ```Code digraph test { @@ -292,18 +149,75 @@ node2 -> node0 [label="right"] } ``` +![](http://ie.u-ryukyu.ac.jp/~e165713/images/ring.pdf) -<div style="text-align: center;"> - <img src="images/ring.pdf" alt="MetaGear" width="500"> -</div> -!--> +## コマンドパターンの解説 +- コマンドパターンとは命令を一つのオブジェクトとして表現するプログラム手法である。 +- 命令を表すクラスを作成し、インスタンスを作成と同時に命令の中身を入力することで命令を作成する。 +- 以下のプログラムの場合、三つの変数決定しつつインスタンスを作成する、これが命令コマンドとなる。 + - DGとして相手ノードのRemoteDGMにputすれば通信が行える。 + +``` + import org.msgpack.annotation.Message; + + @Message + class RTCommand { + public String line; + public String cmd; + public int offset; + + public RTCommand(String cmd, String line, int i) { + this.cmd = cmd; + this.line = line; + this.offset = i; + } + } +``` + + +## コマンドパターン実装の際に起こった問題 +- クラスを他ノードに送信するためには、クラスをシリアライズして送信する必要がある。 + - コマンドの送信にはmsgpackクラスとjavassistを利用している。 +- しかし、送信がうまく行えなかった。 + - javaのバージョン進行のため、msgpackバージョン0.6.12が非対称となっていた。 + - msgpackの最新バージョン0.8.20はシリアライズ機能がうまく機能しなくなっていた。 + +## コマンドパターンを実装するための修正 +- 以上の原因に対処するため以下の対処を行った。 + - javassistのバージョンを最新版へ変更した。 + - シリアライズする命令クラスに対し、クラスをpublicに変更した。 +- 自身でシリアライズ機能をChristieに内蔵してしまえば、これらのパッケージは不要になる。 + +## デモンストレーション + +## 編集位置の相違 +- 同期編集のセッションでは命令コマンドの送信のすれ違いにより、ノードごとのファイル状態が異なってしまうことがある。 +- EditorAとnodeはそれぞれの命令を自身のエディタバッファに施してから命令を送信する + - 結果バッファ状態が異なる状態で受け取った命令を実行してしまう。 +![](http://ie.u-ryukyu.ac.jp/~e165713/images/difference_offset.pdf) + +## 編集の相違の解消 +- 同期編集のセッションはスター型の通信接続で行うため、サーバー対複数ノードの通信間で相違が発生する。 +- 編集の相違を防ぐためには二つの処理を行う必要がある。 + - サーバーとノード間の命令のすれ違いが発生したことを検知する。 + - すれ違いが発生した際に、オフセットのズレを修正する。 +- サーバーが正しいファイルの状態を保持するためサーバーの状態にノードが合わせる必要がある。 + + +## スター型通信 +- 同期通信はスター型での接続を行う。 +- スター型通信の利点は + - サーバーが正しいファイル状態を保持するため、整合性を保つことができる。 + - どこかのノードが切断されても、障害の範囲をそのノードのみに抑えることができる。 + - 新しいノードが参加した、もしくは復帰の際にはサーバーのファイル状況を参照するのみで参加、復帰ができる。 + +![](http://ie.u-ryukyu.ac.jp/~e165713/images/Star-Topology.pdf) ## まとめとこれから -- 本研究発表ではリモートエディタの開発とそれに伴う技術について述べた。現時点で実装できた構成は以下である。 - - リモートエディタの基本となる命令のやり取り部分のコマンドパターン実装。 - - 編集相違を防ぐためのアルゴリズムの発案と検証。 -- 現時点では最低限のセッションを動かすまでの最低限の実装は終わっていない。これから取り組まなければならない課題として以下が挙げられる。 - - スター型Topologyの接続を動的に行わせる。 +- 本研究発表ではリモートエディタの開発とそれに伴う技術について述べた。 +- コマンドパターンを実装し、通信の大部分はChristieが行ってくれる。 +- 現時点では最低限のセッションを動かすまでの最低限の実装は終わっていない。 +- これから取り組まなければならない課題として以下が挙げられる。 - 編集するファイルの共有方法 - ファイルをそのまま送信すると、負担が大きいと予想される。 - 既存のエディタを同期通信に対応させる。
--- a/user/Okud/note/0929.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/Okud/note/0929.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,17 +1,21 @@ 9/29 -###研究目的 +# Gears OS Device Driver開発 +## 研究目的 OSには信頼性が保証できることと拡張性があることが求められている。信頼性をノーマルレベルの計算に対して保証し、 拡張性をメタレベルの計算で実現することを目標にGears OSを設計中である。現在、Geas OS を Raspberry Pi 上で動かすためにはMacとシリアル通信で繋げなければ入力ができない。 Raspberry Pi 上の Gears OS でキーボードやマウスを使えるようになれば利便性が向上する。また、Raspberry Pi 以外のハードウェアで動かす時にも、PCを介して接続しなくて良くなる。 本研究では、Rasberry Pi 上で Gears OS の Device Driver を CbC で開発しすることが目的である。 -###やったこと -- raspberry piのUEFIを起動した +## 進捗 +- raspberry piのUEFIを起動した<br> ![raspberry pi UEFI](http://www.cr.ie.u-ryukyu.ac.jp/hg/Papers/2020/okud-thesis/raw-file/tip/img/IMG_0382.jpeg) -- usb portどこ? -- usbの設定の場所がわからない - https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3 + -###やること +- usb_port<br> +https://github.com/tianocore/edk2-platforms/blob/master/Platform/RaspberryPi/Drivers/DwUsbHostDxe/DwcHw.h +## ToDo +- UEFI からxv6_CbCをインストールして動かす +- Device NameとDevice Typeをとってくる +- USB host controllerを作成
--- a/user/anatofuz/note/2019/12/18.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2019/12/18.md Wed Dec 16 15:11:16 2020 +0900 @@ -10,4 +10,9 @@ - interface_impl headerとimplの2種類 - そろそろsyscall interfaceを書くべき? - interfaceの仕様が結構混乱を招きそうな気配を感じている - - チュートリアル的な資料の充実...? \ No newline at end of file + - チュートリアル的な資料の充実...? + +## 次の継続に行く書き方 + +`__code next(int ret_val,...)` +- この `ret_val`は実装している方のitnerfaceに記述されている必要がある \ No newline at end of file
--- a/user/anatofuz/note/2020/01/14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/01/14.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,31 +1,148 @@ +# 研究目的 +- OSやファイルシステム、 DBなどの様々なソフトウェアを実装し、使用していく必要がある +- それらのソフトウェアの信頼性を向上するには、 テストを用いるか形式手法を用いる手法がある +- 現在開発しているOSにGearsOSがある +- GearsOSはデータをDataGear, 実行すべき単位をCodeGearの組で表現する +- これらを上手く組み合わせて、信頼性が向上、かつ、Gearの入れ替えを柔軟に行う新たな言語/OSを開発したい +- GearsOSはPerlでシンタックスシュガーをかぶせ、 CbCで実行している +- しかしGearsOSで行いたい処理が増えるに連れ、 Perlスクリプトの回収だけでは困難になってきた +- その為Gearsフレームワークに特化した言語を開発し、 より信頼性の高いプログラムを実装しやすいプログラミング言語として開発したい +- (CbCを使わないで実装する...?) -## 進捗 -- 就活おわり(去年) + +# 進捗 +- 就活おわりました + - オファー面談とかしてました +- 年末は胃腸炎+読書していました... - プロシン参加してきました - Cじゃなくて新しい言語ベースでCbCを実装するのがいいのではみたいな話をしていた + - ポスターの書き方はがんばります... + - 予稿集はfireflyの`~/Documents/Papers3`に上げといたので見たい方はどうぞ - そろそろHaskellとLispとagdaに詳しくなっておけという圧を感じている - GearsOSの実装を再開 - - いままでの変更点をある程度roolbackしたい - + - いままでの変更点をある程度roolbackした -## GearsOSの処理 +# GearsOSの書き換え +- 今まではsys_callをInterface化していた + - なんか違うきがしていた +- file interfaceがreadやcloseを振る舞いで持つ方が適切 + - OOPのIntefaceというより型クラスに近い感じで実装していきたい +- user空間のAPIはそこまで考えていないが、 syscall一択よりAPIの数が増える気がする + - ファイルディスクリプタから直接 `fd->read()`とかした気がするので +- 今の所のイメージ[/Gears/Xv6/todo] +# rollback + +- タグを打ち忘れたがrev120がいい感じに動くバージョン +- 下手に `sys_read*` 的なものを量産していたので一旦削除した - 変更されたファイル一覧を出力する ```sh -$hg status --change 120 +$hg status --rev 120:156 +M .hgignore +M src/CMakeLists.txt +M src/file.h +M src/fs.c +M src/gearsTools/lib/Gears/Context.pm +M src/gearsTools/lib/Gears/Context/Template/XV6.pm +M src/gearsTools/trans_impl.pl +M src/gearsTools/update_context.pl +M src/impl/FileRead.h +M src/impl/PipeRead.cbc +M src/impl/PipeRead.h M src/interface/SysRead.h -A src/old_makefiles/Makefile.osx -A src/old_makefiles/makefile-armclang -A src/old_makefiles/makefile-armgcc4.8.5 -A src/old_makefiles/makefile-armgccbc -A src/old_makefiles/makefile-osx.inc -A src/old_makefiles/makefile.inc -A src/plautogen/interface/Integer.h -R src/Makefile.osx -R src/makefile-armclang -R src/makefile-armgcc4.8.5 -R src/makefile-armgccbc -R src/makefile-osx.inc -R src/makefile.inc -``` \ No newline at end of file +M src/interface/file.dg +M src/pipe.cbc +M src/proc.h +M src/usr/CMakeLists.txt +A connect.gdb +A debug.sh +A src/file_read.cbc +A src/impl/SysOpenImpl.h +A src/inode.h +A src/interface/SysCall.dg +A src/interface/SysOpen.h +A src/move_data_gears/pipe.h +A src/sys_open_impl.cbc +A src/sys_pipe_read.cbc +R src/context.h +R src/impl/FileRead.cbc +``` + +# file interface +- file.cのAPIを参考にした + - `lseek`とかも必要とは思ったがxv6にはなさそう + +```c +typedef struct file <Impl> { + union Data* file; + int ref; // reference count + char readable; + char writable; + unsigned int off; + struct stat* st; + char* addr; + int n; + __code stat(Impl* file, struct stat* st, __code next(...)); + __code read(Impl* file, char* addr, __code next(...)); + __code write(Impl* file, char* addr, int n, __code next(...)); + __code close(Impl* file,__code next(...)); +} file; +``` + +# 本来のfile +- enumで管理しているtypeの分実装があれば良さそう + +```c +struct file { + enum { FD_NONE, FD_PIPE, FD_INODE } type; + int ref; // reference count + char readable; + char writable; + struct pipe *pipe; + struct inode *ip; + uint off; +}; +``` + +# 今の所のイメージ + +- pipe + +```c +typedef struct pipe<Impl, Isa> Impl file { + #define PIPESIZE 512 + struct spinlock lock; + char data[PIPESIZE]; + uint nread; // number of bytes read + uint nwrite; // number of bytes written + int readopen; // read fd is still open + int writeopen; // write fd is still open +} pipe; +``` + +- inode + +``` +typedef struct inode <Impl, Isa> impl file { + uint dev; // Device number + uint inum; // Inode number + int ref; // Reference count + int flags; // I_BUSY, I_VALID + + short type; // copy of disk inode + short major; + short minor; + short nlink; + uint size; + uint addrs[NDIRECT+1]; +} inode; +``` + +- これにnoneのものが加わる気がする + - とはいえNONEはcloseする箇所しか使っていない + +# 今週のtodo + +- このあたりの実装・動かすとこまで +- 空いている時間に関数型と論理式の勉強を... \ No newline at end of file
--- a/user/anatofuz/note/2020/01/20.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/01/20.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,28 +1,328 @@ -# GearsOSのビルド時の情報 + +# 研究目的 +- コンパイルが通ったプログラムは確実に動いていてほしい +- 検証可能/信頼性が高いプログラムを簡単に書けるようにしたい +- 何をしようかはちょっと考えてます... + - Gearsの専用言語みたいなのを先週までは考えていましたが、ちょっと違いそう + - 既存のプログラムを動的にGearsに変換するとかは面白そうな気がする + - user levelのGearsOSのAPIの決定? + - 仕様記述言語 + +# 今週の進捗... +- 内定承諾書をだした +- Xv6のpipeのcloseを中心に実装していました + - gearstoolsのバグを修正 +- hackmdたてました + +# hackmd +- 他人数で1つのドキュメントをいい感じに編集できるweb app +- forkされたOSSのCodeMDがあり、growiに組み込めるので組み込んでみました +- 単体でも使用可能 + +# Otoyaリポジトリたてた +- 名前を一応Abyssにしました +- Membersに作るのもな...と思ったのでOtherにいれといてます + + +# 生成ツール周りの修正 +- `genrate_context.pl`で呼び出されるPerlのライブラリをメンテしていました +## 変更点 +- `//data_gear "hoge.h"`とすると問答無用でinterfaceになるバグを修正 +- 内部構造のリファクタリング +- `__code`の引数を `union Data`に登録しないようにする構文を追加 + - `__code sample(union Data* hoge, struct foo* bar,__code next(...)){ //:skip` + - `//:skip`と書くとこの引数はPerlスクリプトがDataGearとして認識しなくなる + - interface/Interfaceの実装の構造体が別の構造体をメンバで持っていて、そのメンバをinterface化していないときに使える + +## GearsOSのビルド時の情報 + +- 対象のDataGearが、どのファイルの何行目で参照されてるか見れるようになりました + - 個人的に使う必要が出てきたので導入した + - Perlのhash refをdumpしているだけの質素な実装 + +``` +'impl' => { + 'SingleLinkedStack' => { + '/tmp/sandbox/CMakeFiles/kernel.dir/c/SingleLinkedStack.c' => [ + '5', + '35', + '46', + '61', + '80', + '109', + '126', + '153' + ] + }, + 'pipe' => { + '/tmp/sandbox/CMakeFiles/kernel.dir/c/pipe.c' => [ + [ + '13' + ] + ], + '/tmp/sandbox/CMakeFiles/kernel.dir/c/impl/file_impl_pipe.c' => [ + '32', + '79', + '92', + '108', + '162', + '175', + + +``` + +# pipe の実装 +- 実装にInteerfaceのポインタいれてみた + - ある程度書いてみたのでコンパイルエラーを取るのをします + - gearstoolsのバグでここまでこなかった... + +``` +typedef struct file <Impl> { + union Data* file; + enum { FD_NONE, FD_PIPE, FD_INODE } type; //TODO: after remoe + int ref; // reference count + char readable; + char writable; + unsigned int off; + struct stat* st; + char* addr; + struct pipe *pipe; //TODO : remove + struct inode *ip; //TODO : remove + int n; + int fd; + __code stat(Impl* file, struct stat* st, __code next(...)); + __code read(Impl* file, char* addr, __code next(...)); + __code write(Impl* file, char* addr, int n, __code next(...)); + __code close(Impl* file,int fd, __code next(...)); +} file; +``` + +``` +typedef struct pipe<Impl, Isa> impl file { + #define PIPESIZE 512 + union Data* file; + struct spinlock lock; + char data[PIPESIZE]; + uint nread; // number of bytes read + uint nwrite; // number of bytes written + int readopen; // read fd is still open + int writeopen; // write fd is still open + + // interface field + int n; + char* addr; + + // private code gear + __code piperead1(Impl* pipe, char* addr, int n, __code next(...)); + __code piperead2(Impl* pipe, char* addr, int n, __code next(...)); + __code cbc_pipeclose(Impl* pipe, Isa* file, __code next(...)); + __code cbc_pipeclose2(Impl* pipe, Isa* file, Isa* ff, __code next(...)); + __code cbc_pipeclose3(Impl* pipe, Isa* file, Isa* ff, __code next(...)); + __code cbc_pipeclose4(Impl* pipe, int writable, __code next(...)); + __code cbc_pipe_close_writeopen(Impl* pipe, __code next(...)); + __code cbc_pipe_close_readopen(Impl* pipe, __code next(...)); +} pipe; + +``` ``` - 'SingleLinkedQueue' => { - 'caller' => { - '/Users/anatofuz/src/firefly/hg/Gears/src/parallel_execution/c/SingleLinkedQueue.c' => [ - 8, - 34, - 46, - 63, - 85 - ] - } - }, - 'SynchronizedQueue' => { - 'caller' => { - '/Users/anatofuz/src/firefly/hg/Gears/src/parallel_execution/c/SynchronizedQueue.c' => [ - 11, - 24, - 43, - 83, - 126, - 145 - ] - } - }, +#include "../../context.h" +#interface "file.h" + +// ---- +// typedef struct pipe<Impl, Isa> impl file { +// #define PIPESIZE 512 +// union Data* file; +// struct spinlock lock; +// char data[PIPESIZE]; +// uint nread; // number of bytes read +// uint nwrite; // number of bytes written +// int readopen; // read fd is still open +// int writeopen; // write fd is still open +// +// // interface field +// int n; +// char* addr; +// +// // private code gear +// __code piperead1(Impl* pipe, char* addr, int n, __code next(...)); +// __code piperead2(Impl* pipe, char* addr, int n, __code next(...)); +// __code cbc_pipeclose(Impl* pipe, Isa* file, __code next(...)); +// __code cbc_pipeclose2(Impl* pipe, Isa* file, Isa* ff, __code next(...)); +// __code cbc_pipeclose3(Impl* pipe, Isa* file, Isa* ff, __code next(...)); +// __code cbc_pipeclose4(Impl* pipe, int writable, __code next(...)); +// __code cbc_pipe_close_writeopen(Impl* pipe, __code next(...)); +// __code cbc_pipe_close_readopen(Impl* pipe, __code next(...)); +// } pipe; +// ---- + +file* createpipe(struct Context* cbc_context) { + struct file* file = new file(); + struct pipe* pipe = new pipe(); + file->file = (union Data*)pipe; + pipe->file = NULL; + pipe->lock = 0; + pipe->spinlock = 0; + pipe->data = 0; + pipe->nread = 0; + pipe->nwrite = 0; + pipe->readopen = 0; + pipe->writeopen = 0; + pipe->n = 0; + pipe->addr = NULL; + file->remoe = 0; + file->off = 0; + file->st = NULL; + file->addr = NULL; + file->pipe = 0; + file->inode = 0; + file->n = 0; + file->fd = 0; + pipe->piperead1 = C_piperead1pipe; + pipe->piperead2 = C_piperead2pipe; + pipe->cbc_pipeclose = C_cbc_pipeclosepipe; + pipe->cbc_pipeclose2 = C_cbc_pipeclose2pipe; + pipe->cbc_pipeclose3 = C_cbc_pipeclose3pipe; + pipe->cbc_pipeclose4 = C_cbc_pipeclose4pipe; + pipe->cbc_pipe_close_writeopen = C_cbc_pipe_close_writeopenpipe; + pipe->cbc_pipe_close_readopen = C_cbc_pipe_close_readopenpipe; + file->stat = C_statpipe; + file->read = C_readpipe; + file->write = C_writepipe; + file->close = C_closepipe; + return file; +} + +__code statpipe(struct pipe* file, struct stat* st, __code next(...)) { //:skip + + goto next(...); +} + +__code readpipe(struct pipe* file, char* addr, int n, __code next(...)) { + acquire(&p->lock); + goto cbc_piperead1(file,addr,n,next); +} + +__code piperead1(struct pipe* p, char* addr, int n, __code next(...)) { + if (p->nread == p->nwrite && p->writeopen){ + goto cbc_piperead2(p,addr,n,next); + } + n = 0; + goto cbc_piperead3(p,addr,n,next); +} + +__code piperead2(struct pipe* p, char* addr, int n, __code next(...)) { + if(proc->killed){ + release(&p->lock); + goto cbc_context->error(); + } + goto cbc_sleep(p,&p->nread, &p->lock, next,cbc_piperead1); +} + + +__code cbc_sleep(struct pipe* p, unit* nread, struct spinlock* lock, __code next(...), __code pread(...)){ //:skip + if(proc == 0) { + goto cbc_context->panic("sleep"); + } -``` \ No newline at end of file + if(lk == 0) { + goto cbc_context->panic("sleep without lk"); + } + + if(lk != &ptable.lock){ //DOC: sleeplock0 + acquire(&ptable.lock); //DOC: sleeplock1 + release(lk); + } + goto cbc_sched(cbc_sleep1); +} + +__code cbc_sched_stub(struct pipe* p, unit* nread, struct spinlock* lock, __code next(...), __code pread(...)){ //:skip + proc->chan = chan; + proc->state = SLEEPING; + proc->lk = lk; + proc->cbc_next = next1; +} + +__code writepipe(struct pipe* file, char* addr, int n, __code next(...)) { + + goto next(...); +} + +__code pipeclose(struct pipe* file,int fd,__code next(...)) { + proc->ofile[fd] = 0; + goto file->cbc_pipeclose(file->file, next); +} + + +__code cbc_pipeclose(struct pipe* pipe, struct file* file, __code next(...)) { + struct file ff; + acquire(*ftable.loc) + + if (f->ref < 1) { + goto cbc_context->kernel_error->panic("file close"); + } + goto pipe->cbc_pipeclose2(f,ff,next); +} + +__code cbc_pipeclose2(struct pipe* pipe,struct file* file, struct file* ff,__code next(...)) { + if (--f->ref > 0) { + release(&ftable.lock); + goto cbc_context->return(); + } + goto pipe->cbc_pipeclose3(f,ff,next); +} + +__code cbc_pipeclose3(struct pipe* pipe,struct file* file, struct file* ff,__code next(...)) { + *ff = *f; + f->ref = 0; + f->type = FD_NONE; + relsease(&ftable.lock); + struct pipe* p = ff.pipe; + int writable = ff.writable; + + goto pipe->cbc_pipeclose4(p,writable,next); +} + +__code cbc_pipeclose4(struct pipe* pipe, int writable, __code next(...)) { + acquire(&pipe->lock); + if (writable) { + goto pipe->cbc_pipe_close_writeopen(next); + } + goto pipe->cbc_pipe_close_readopen(next); +} + + +__code cbc_pipe_close_writeopen(struct pipe* pipe, __code next(...)) { + pipe->writeopen = 0; + goto cbc_wakeup(&pipe->nread,pipe,cbc_pipe_release,next); +} + +__code cbc_pipe_close_readopen(struct pipe* pipe, __code next(...)) { + pipe->readopen = 0; + goto cbc_context->wakeup(&pipe->nwrite,pipe,cbc_pipe_release,next); +} + + +``` + +# CbCプログラミングテクニック + +- context.hの中の`union Data`内に全てのDataGearの定義を書く仕様になっている +- 現状context.hはxv6の`proc.h`内でinlcudeされている +- `proc.h`をincludeしているCファイルで、`union Data`に定義がある別のヘッダファイルをincludeすると、redefinition(再定義)エラーが発生する +- 回避するには構造体の方に `#ifndef`のマクロを追加する + +```c +#ifndef SPINLOCK_H +struct spinlock { + uint locked; // Is the lock held? + + // For debugging: + char *name; // Name of lock. + struct cpu *cpu; // The cpu holding the lock. + uint pcs[10]; // The call stack (an array of program counters) + // that locked the lock. +}; +#endif // SPINLOCK_H +#define SPINLOCK_H +```
--- a/user/anatofuz/note/2020/01/27.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/01/27.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,292 @@ # 研究目的 +- GearsOSで今のところInterfaceで定義したCodeGearから明示的にあるCodeGearに接続する箇所が上手くいっていない +- この箇所を修正したい +- 動的に実行するCodeGearを変えるのをためしてみたい + +# 進捗 +- よくあるエラーかいた + - http://growi.cr.ie.u-ryukyu.ac.jp/Gears/Xv6/cmmon_errors +- Xv6関連の作業 + - vm Interface/ Implの実装・修正 + - generate_stubのリライト? + +# generate_stub.pl +- Interfaceの入出力を見て`Gearef`を生成するルーチンが上手く動かないケースが多くなってきた + - 書き方をミスっている...? +- 引数と実際に生成された`Gearef`が参照しているfieldがずれるケースが多い +- Interfaceの実装側から、 private なCodeGearにgoto metaする場合は, 実装側に値を積む必要がある + - 現状のgenerate_stubは対応していない + - Interfaceと実装のヘッダファイルを見て`Gearef`を生成するルーチンを書く必要がある + +## 方針? +- generate_stub.plのテストスクリプトを書く +- ライブラリ化しつつ移植していく + - テストを通していく +- その後入れ替えを検討したい +- とはいえ今の時期やるべきなのかは微妙 + +## ライブラリ関連 +- gearstoolsの以下のひっそりと実装している +- すでにContext生成系の`Gears::Context`と、色々使う`Gears::Util`ライブラリがある +- `Gears::Stub`空間でいい感じにstub生成のコードを作成する + +## 現状のズレの対策 +- `__ncode`はgenrate_stubの対象では無いので、ncodeにしておく +- genrate_stubが変換するコードはすべて手で書く必要がある + - stub code gearも含めて + +# xv6のvm.cの書き換え +- CodeGearの定義は完了した? + - panicとかどうするか問題はありますが、とりあえずvmのInterfaceで持たせるのが早そう +- 書いたファイル + - interface + - interface/vm.h + - 実装のヘッダファイル + - impl/vm_impl.h + - interfaceに書かれたCodeGear + - vm_impl.cbc + - その中で遷移するやつ + - vm_impl_private.cbc +- 一旦voidの関数呼び出しをdummyでして、その中でgotoする戦略 + - 現状の状態から更新する箇所が少ない +- proc.cbcから一箇所だけgotoで呼び出すことには成功している + +```c +void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[]) +{ + // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + +} + + + +__ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip + + struct vm* vm = createvm_impl(cbc_context); + // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret); + Gearef(cbc_context, vm)->vm = (union Data*) vm; + Gearef(cbc_context, vm)->pgdir = pgdir; + Gearef(cbc_context, vm)->init = init; + Gearef(cbc_context, vm)->sz = sz ; + Gearef(cbc_context, vm)->next = C_vm_void_ret ; + goto meta(cbc_context, vm->init_inituvm); +} + +void userinit(void) +{ + struct proc* p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + initContext(&p->cbc_context); + + initproc = p; + + if((p->pgdir = kpt_alloc()) == NULL) { + panic("userinit: out of memory?"); + } + + dummy(p, _binary_initcode_start, _binary_initcode_size); + +``` + +- ほんとはこう書きたい + +``` +void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[]) +{ + // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + +} + + +__code cbc_init_vmm_dummy(struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip + + struct vm* vm = createvm_impl(cbc_context); + goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret); +} + +``` + +- コンパイルエラーにはならなかったが、このgotoで引数の数が足らず処理がおかしくなっていた + +``` + goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + +} + + +__ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip +``` + + + +# gotoの前に値を積む +- Interfaceで定義したCodeGearはInterfaceから値を取得/ Interfaceに値を積むコードが生成される + - 現状は値を積む場所はgenerate_stubのバグで一部出ないですが... +```c +__code init_inituvmvm_impl(struct Context *cbc_context,struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, enum Code next) { + + Gearef(cbc_context, vm_impl)->pgdir = pgdir; + Gearef(cbc_context, vm_impl)->init = init; + Gearef(cbc_context, vm_impl)->sz = sz; + Gearef(cbc_context, vm_impl)->next = next; + goto meta(cbc_context, C_init_inituvm_check_sz); +} -# 進捗 \ No newline at end of file +__code init_inituvmvm_impl_stub(struct Context* cbc_context) { + vm_impl* vm = (vm_impl*)GearImpl(cbc_context, vm, vm); + pde_t* pgdir = Gearef(cbc_context, vm)->pgdir; + char* init = Gearef(cbc_context, vm)->init; + uint sz = Gearef(cbc_context, vm)->sz; + enum Code next = Gearef(cbc_context, vm)->next; + goto init_inituvmvm_impl(cbc_context, vm, pgdir, init, sz, next); +} +``` + +# private->private + +- 今現在こういうコードを書いてもgoto metaに変換されるだけで、値は積まれない + +```c +__code init_inituvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)) { + goto init_inituvm_check_sz(vm, pgdir, init, sz, next(...)); +} +``` + +```c +__code init_inituvmvm_impl(struct Context *cbc_context,struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, enum Code next) { + + Gearef(cbc_context, vm_impl)->pgdir = pgdir; + Gearef(cbc_context, vm_impl)->init = init; + Gearef(cbc_context, vm_impl)->sz = sz; + Gearef(cbc_context, vm_impl)->next = next; + goto meta(cbc_context, C_init_inituvm_check_sz); +} +``` + +- 手でGearefを書く必要がある + +```c +__code init_inituvmvm_impl(struct vm_impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)) { + + Gearef(cbc_context, vm_impl)->pgdir = pgdir; + Gearef(cbc_context, vm_impl)->init = init; + Gearef(cbc_context, vm_impl)->sz = sz; + Gearef(cbc_context, vm_impl)->next = next; + goto init_inituvm_check_sz(vm, pgdir, init, sz, next(...)); +} +``` + +## ほか +- プロセスごとにContextを初期化する必要がある + - initContextを呼び出す必要がある + +```c +void initContext(struct Context* cbc_context) { + cbc_context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE; + cbc_context->code = (__code(**) (struct Context*)) NEWN(ALLOCATE_SIZE, void*); + cbc_context->data = NEWN(ALLOCATE_SIZE, union Data*); + cbc_context->heapStart = NEWN(cbc_context->heapLimit, char); + cbc_context->heap = cbc_context->heapStart; + // cbc_context->codeNum = Exit; + + cbc_context->code[C_allocuvm_check_newszvm_impl] = allocuvm_check_newszvm_impl_stub; + cbc_context->code[C_allocuvm_loopvm_impl] = allocuvm_loopvm_impl_stub; + cbc_context->code[C_allocuvmvm_impl] = allocuvmvm_impl_stub; + cbc_context->code[C_clearSingleLinkedStack] = clearSingleLinkedStack_stub; + cbc_context->code[C_clearpteu_check_ptevm_impl] = clearpteu_check_ptevm_impl_stub; + cbc_context->code[C_clearpteuvm_impl] = clearpteuvm_impl_stub; + cbc_context->code[C_copyout_loop_check_n] = copyout_loop_check_n_stub; + cbc_context->code[C_copyout_loop_check_pa0] = copyout_loop_check_pa0_stub; + cbc_context->code[C_copyout_loopvm_impl] = copyout_loopvm_impl_stub; + cbc_context->code[C_copyoutvm_impl] = copyoutvm_impl_stub; + cbc_context->code[C_copyuvm_check_nullvm_impl] = copyuvm_check_nullvm_impl_stub; + cbc_context->code[C_copyuvm_loop_bad] = copyuvm_loop_bad_stub; + cbc_context->code[C_copyuvm_loop_check_mappages] = copyuvm_loop_check_mappages_stub; + cbc_context->code[C_copyuvm_loop_check_mem] = copyuvm_loop_check_mem_stub; + cbc_context->code[C_copyuvm_loop_check_pte] = copyuvm_loop_check_pte_stub; + cbc_context->code[C_copyuvm_loop_check_walkpgdir] = copyuvm_loop_check_walkpgdir_stub; + cbc_context->code[C_copyuvm_loopvm_impl] = copyuvm_loopvm_impl_stub; + cbc_context->code[C_copyuvmvm_impl] = copyuvmvm_impl_stub; + cbc_context->code[C_exit_code] = exit_code_stub; + cbc_context->code[C_get2SingleLinkedStack] = get2SingleLinkedStack_stub; + cbc_context->code[C_getSingleLinkedStack] = getSingleLinkedStack_stub; + cbc_context->code[C_init_inituvm_check_sz] = init_inituvm_check_sz_stub; + cbc_context->code[C_init_inituvmvm_impl] = init_inituvmvm_impl_stub; + cbc_context->code[C_init_vmmvm_impl] = init_vmmvm_impl_stub; + cbc_context->code[C_isEmptySingleLinkedStack] = isEmptySingleLinkedStack_stub; + cbc_context->code[C_kpt_alloc_check_impl] = kpt_alloc_check_impl_stub; + cbc_context->code[C_kpt_allocvm_impl] = kpt_allocvm_impl_stub; + cbc_context->code[C_kpt_freerangevm_impl] = kpt_freerangevm_impl_stub; + cbc_context->code[C_loaduvm_check_PTE_SZ] = loaduvm_check_PTE_SZ_stub; + cbc_context->code[C_loaduvm_check_pgdir] = loaduvm_check_pgdir_stub; + cbc_context->code[C_loaduvm_exit] = loaduvm_exit_stub; + cbc_context->code[C_loaduvm_loopvm_impl] = loaduvm_loopvm_impl_stub; + cbc_context->code[C_loaduvm_ptesize_checkvm_impl] = loaduvm_ptesize_checkvm_impl_stub; + cbc_context->code[C_loaduvmvm_impl] = loaduvmvm_impl_stub; + cbc_context->code[C_paging_intvm_impl] = paging_intvm_impl_stub; + cbc_context->code[C_paging_intvmvm_impl] = paging_intvmvm_impl_stub; + cbc_context->code[C_pop2SingleLinkedStack] = pop2SingleLinkedStack_stub; + cbc_context->code[C_popSingleLinkedStack] = popSingleLinkedStack_stub; + cbc_context->code[C_pushSingleLinkedStack] = pushSingleLinkedStack_stub; + cbc_context->code[C_start_code] = start_code_stub; + cbc_context->code[C_switchuvm_check_pgdirvm_impl] = switchuvm_check_pgdirvm_impl_stub; + cbc_context->code[C_switchuvmvm_impl] = switchuvmvm_impl_stub; + cbc_context->code[C_uva2ka_check_pe_types] = uva2ka_check_pe_types_stub; + cbc_context->code[C_uva2ka_check_pte_ap] = uva2ka_check_pte_ap_stub; + cbc_context->code[C_uva2kavm_impl] = uva2kavm_impl_stub; + cbc_context->code[C_vm_void_ret] = vm_void_ret_stub; + + +#include "dataGearInit.c" + cbc_context->dataNum = 12; +} +``` + +- userinitとforkでそれぞれ初期化している + - userinit + - 最初のuserプロセスが生成されるときによばれる + - fork + - forkしたとき + +```c +void userinit(void) +{ + struct proc* p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + initContext(&p->cbc_context); + + initproc = p; + + if((p->pgdir = kpt_alloc()) == NULL) { + panic("userinit: out of memory?"); + } + + dummy(p, _binary_initcode_start, _binary_initcode_size); + + p->sz = PTE_SZ; + + // craft the trapframe as if + memset(p->tf, 0, sizeof(*p->tf)); + + p->tf->r14_svc = (uint)error_init; + p->tf->spsr = spsr_usr (); + p->tf->sp_usr = PTE_SZ; // set the user stack + p->tf->lr_usr = 0; + + // set the user pc. The actual pc loaded into r15_usr is in + // p->tf, the trapframe. + p->tf->pc = 0; // beginning of initcode.S + + safestrcpy(p->name, "initcode", sizeof(p->name)); + p->cwd = namei("/"); + + p->state = RUNNABLE; +} + +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/02/01.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/01.md Wed Dec 16 15:11:16 2020 +0900 @@ -106,4 +106,7 @@ dummy(p, _binary_initcode_start, _binary_initcode_size); p->sz = PTE_SZ; -``` \ No newline at end of file +``` + +- Gearsの世界だとCbC -> Cの世界はいままで考えられてなかったみたい +- 新しい構文を作る or generate_stubとかを治すなどしてなにか方向性を決めたいところな気がする \ No newline at end of file
--- a/user/anatofuz/note/2020/02/03.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/03.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,7 +1,51 @@ # きょうのめも - InterfaceをDataとCodeで分けなくてもいいようになった +- QueueのInterfaceの記述をなおした ## やったこと - [[../02]]で書いた正規表現ルーチンがわりと使えそうだったので、これを導入した - stubを作るところとcontext.hを作るところの2箇所に記述 -- stubの方はポインタ(`*`)を取り外して型情報を登録する必要があるため、微妙に正規表現が異なっている \ No newline at end of file +- stubの方はポインタ(`*`)を取り外して型情報を登録する必要があるため、微妙に正規表現が異なっている + +## 導入したリポジトリ +- Gears +- Xv6 + - mainの方だけ(membersの方はいれてない) + +# ためしていたスクリプト + +- `List::Util`のuniqを使えば楽だったので導入したときは直している + +```perl +#!/usr/bin/env perl +use strict; +use warnings; +use DDP {deparse => 1}; + +my $file_name = shift // "vm.h"; +open my $fh, '<', $file_name; + +my @res = (); + +while (my $line = <$fh>) { + if ($line =~ /__code (\w+)/) { + my $args = $'; + #$args eq (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + while ($args =~ /((?:struct|union|const)\s+)?([\w*\[\]_]+)\s*(\w+),?/g) { + my $const_type = $1; + my $type = $2; + my $vname = $3; + my $val = "$type $vname"; + push(@res, $const_type ? "$const_type$val" : $val); + } + } +} + +my @uniq = uniq(@res); +p @uniq; + +sub uniq { + my %seen; + return grep { !$seen{$_}++ } @_; +} +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/02/04.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/04.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,300 @@ # 研究目的 -TBD... \ No newline at end of file +TBD... + +# 進捗 +- Growiにいくつか記事を移植/新規で書いた +- 環境付きgotoをGearsにいれようとしてあまりだめだった... +- Interfaceの引数を取らなくても良くなった +- Interfaceの引数で `const`が来ても大丈夫なように修正した + + +## Growiにいくつか記事を移植/新規で書いた +- 移植系 + - GGJ + - ソースコード読み回関連の資料 + - Haskell + - QEMU + - pypy + - CbCコンパイラのビルド周り + - GCC + - LLVM + - ARM GCC +- 新規 + - おすすめツール + - fedoraのdebug buildのansible実行方法 + - FreeMindが固まる問題の解決方法 + +## Interfaceの引数を取らなくても良くなった + +### いままで + +- Input/OutputなDataGearは予め宣言しておく必要があった + - generate_stubとcontext生成系の都合 + +```c +typedef struct vm<Type,Impl> { + union Data* vm; + uint low; + uint hi; + struct proc* p; + pde_t* pgdir; + char* init; + uint sz; + char* addr; + struct inode* ip; + uint offset; + uint oldsz; + uint newsz; + char* uva; + uint va; + void* pp; + uint len; + uint phy_low; + uint phy_hi; + __code init_vmm(Impl* vm, __code next(...)); + __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...)); + __code kpt_alloc(Impl* vm ,__code next(...)); + __code switchuvm(Impl* vm ,struct proc* p, __code next(...)); + __code init_inituvm(Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + __code loaduvm(Impl* vm,pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)); + __code allocuvm(Impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...)); + __code clearpteu(Impl* vm, pde_t* pgdir, char* uva, __code next(...)); + __code copyuvm(Impl* vm, pde_t* pgdir, uint sz, __code next(...)); + __code uva2ka(Impl* vm, pde_t* pgdir, char* uva, __code next(...)); + __code copyout(Impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...)); + __code paging_int(Impl* vm, uint phy_low, uint phy_hi, __code next(...)); + __code next(...); +} vm; +``` + + +- 問題点 + - 最初書くときに「引数以外も書いていい」と誤解を与えやすい + - 単純に2回書かないといけないので、様々な間違いを発生させやすい + +### これから + +- `__code`内でしっかり書いておけば問題ないようになった + - javaとかgolangっぽい? +- 静的に定義していた場合は`__code`の中身は利用されない(従来通りの動き) + +```c +typedef struct vm <Type,Impl> { + __code init_vmm(Impl* vm, __code next(...)); + __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...)); + __code kpt_alloc(Impl* vm ,__code next(...)); + __code switchuvm(Impl* vm ,struct proc* p, __code next(...)); + __code init_inituvm(Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + __code loaduvm(Impl* vm,pde_t* pgdir, char* addr, struct inode* ip, uint offset, uint sz, __code next(...)); + __code allocuvm(Impl* vm, pde_t* pgdir, uint oldsz, uint newsz, __code next(...)); + __code clearpteu(Impl* vm, pde_t* pgdir, char* uva, __code next(...)); + __code copyuvm(Impl* vm, pde_t* pgdir, uint sz, __code next(...)); + __code uva2ka(Impl* vm, pde_t* pgdir, char* uva, __code next(...)); + __code copyout(Impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...)); + __code paging_int(Impl* vm, uint phy_low, uint phy_hi, __code next(...)); + __code void_ret(Impl* vm); + __code next(...); +} vm; +``` + +### こういう感じのスクリプトでためしてました + +```perl +#!/usr/bin/env perl +use strict; +use warnings; +use DDP {deparse => 1}; + +my $file_name = shift // "vm.h"; +open my $fh, '<', $file_name; + +my @res = (); + +while (my $line = <$fh>) { + if ($line =~ /__code (\w+)/) { + my $args = $'; + #$args eq (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + while ($args =~ /((?:struct|union|const)\s+)?([\w*\[\]_]+)\s*(\w+),?/g) { + my $const_type = $1; + my $type = $2; + my $vname = $3; + my $val = "$type $vname"; + push(@res, $const_type ? "$const_type$val" : $val); + } + } +} + +my @uniq = uniq(@res); +p @uniq; + +sub uniq { + my %seen; + return grep { !$seen{$_}++ } @_; +} +``` + +- わりとちゃんとキャプチャ出来たので実装してみた + +### 直した箇所 +- generate_stub.pl + - Interfaceに記述があるfieldなのかを判定するルーチン +- generate_context.pl + - context.hを生成する際に利用していたライブラリ(以前書き加えたもの) + +#### gen_stub + +- `%var`にInterface名(`$name`)と型名(`$ttype`),変数名(`$tname`)を登録する必要がある + - この時点で`$ttype`は`*`を落とさないと駄目らしい + - また`struct| union`も型名にいれては駄目 + - constが来ている場合は逆に型に追加しないといけないので、周辺の正規表現をいくつか直しています + +```perl + $dataGear{$name} .= $_; + if (/^\s*(.*)\s+(\w+);$/ ) { + my $ttype = $1; + my $tname = $2; + if ($ttype =~ /^(union|struct)?\s*(\w+)/) { + $ttype = $2; + } + $described_data_gear = 1; + $var{$name}->{$tname} = $ttype; + } + if (/__code (\w+)/) { + next if $described_data_gear; + my $args = $'; + while ($args =~ /\s*(struct|union|const)?\s*([\w\[\]_]+)\*?\s*(\w+),?/g) { + #$args eq (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + my $const_type = $1; + my $ttype = $2; + my $tname = $3; + + $ttype =~ s/(Impl|Isa|Type)/Data/; + if ($const_type eq 'const') { + $ttype = "const $ttype"; + } + $var{$name}->{$tname} = $ttype; + } + } + if (/^}/) { + $inTypedef = 0; + } +``` + + +## 環境付きgoto + +- CbC -> Cにはreturnするか環境付きgotoをする必要がある +- 今のxv6はreturnしている +- せっかくなので環境付きgotoでいけるか試してみた + +--- +- 現在のgenerate_stub.plはgotoをすべてgoto metaに置換してしまう +- 下の書き方だと、引数のCbC_returnに対してgotoしなければならないので、現状のルーチンでは難しそう + +```patch +diff -r 40b1b7476e77 src/impl/vm_impl.cbc +--- a/src/impl/vm_impl.cbc Tue Jan 28 17:14:44 2020 +0900 ++++ b/src/impl/vm_impl.cbc Sat Feb 01 14:28:28 2020 +0900 +@@ -35,7 +35,7 @@ + vm_impl->copyout_loopvm_impl = C_copyout_loopvm_impl; + vm_impl->switchuvm_check_pgdirvm_impl = C_switchuvm_check_pgdirvm_impl; + vm_impl->init_inituvm_check_sz = C_init_inituvm_check_sz; +- vm->void_ret = C_vm_void_ret; ++ vm->void_ret = C_void_retvm_impl; + vm->init_vmm = C_init_vmmvm_impl; + vm->kpt_freerange = C_kpt_freerangevm_impl; + vm->kpt_alloc = C_kpt_allocvm_impl; +@@ -149,6 +149,15 @@ + goto paging_intvmvm_impl(vm, phy_low, phy_hi, next(...)); + } + +-__code vm_void_ret(struct vm_impl* vm) { +- return; ++ ++__code void_retvm_impl(struct Context* cbc_context, struct vm_impl* vm, void (*return_func)(int, void*), int ret_val, void* cbc_env) { ++ goto return_func(ret_val, cbc_env); + } ++ ++__code void_retvm_impl_stub(struct Context* cbc_context) { ++ vm_impl* vm = (vm_impl*)GearImpl(cbc_context, vm, vm); ++ void (*return_func)(int, void*); ++ return_func = Gearef(cbc_context, vm)->return_func; ++ void* cbc_env = Gearef(cbc_context, vm)->cbc_env; ++ goto void_retvm_impl(cbc_context, vm, return_func, cbc_env); ++} +diff -r 40b1b7476e77 src/interface/vm.h +--- a/src/interface/vm.h Tue Jan 28 17:14:44 2020 +0900 ++++ b/src/interface/vm.h Sat Feb 01 14:28:28 2020 +0900 +@@ -17,6 +17,8 @@ + uint len; + uint phy_low; + uint phy_hi; ++ void* cbc_env; ++ void (*return_func)(int, void*); + __code init_vmm(Impl* vm, __code next(...)); + __code kpt_freerange(Impl* vm, uint low, uint hi, __code next(...)); + __code kpt_alloc(Impl* vm ,__code next(...)); +@@ -29,6 +31,6 @@ + __code uva2ka(Impl* vm, pde_t* pgdir, char* uva, __code next(...)); + __code copyout(Impl* vm, pde_t* pgdir, uint va, void* pp, uint len, __code next(...)); + __code paging_int(Impl* vm, uint phy_low, uint phy_hi, __code next(...)); +- __code void_ret(Impl* vm); ++ __code void_ret(Impl* vm, void (*return_func)(int, void*), int ret_val, void* cbc_env); + __code next(...); + } vm; +diff -r 40b1b7476e77 src/proc.cbc +--- a/src/proc.cbc Tue Jan 28 17:14:44 2020 +0900 ++++ b/src/proc.cbc Sat Feb 01 14:28:28 2020 +0900 +@@ -117,16 +117,20 @@ + //PAGEBREAK: 32 + // hand-craft the first user process. We link initcode.S into the kernel + // as a binary, the linker will generate __binary_initcode_start/_size +-void dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[]) ++int dummy(struct proc *p, char _binary_initcode_start[], char _binary_initcode_size[]) + { + // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); +- goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); ++ void (*ret)(int, void*); ++ void *env; ++ ret = _CbC_return; ++ env = _CbC_environment; ++ goto cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size, ret, env); + + } + + + +-__ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz){//:skip ++__ncode cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz, void (*ret)(int, void*), void* env){//:skip + + struct vm* vm = createvm_impl(cbc_context); + // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret); +@@ -134,7 +138,9 @@ + Gearef(cbc_context, vm)->pgdir = pgdir; + Gearef(cbc_context, vm)->init = init; + Gearef(cbc_context, vm)->sz = sz ; +- Gearef(cbc_context, vm)->next = C_vm_void_ret ; ++ Gearef(cbc_context, vm)->cbc_env = env; ++ Gearef(cbc_context, vm)->return_func = ret; ++ Gearef(cbc_context, vm)->next = C_void_retvm_impl; + goto meta(cbc_context, vm->init_inituvm); + } + +@@ -152,6 +158,8 @@ + panic("userinit: out of memory?"); + } + ++ void (*ret)(int, void*); ++ void *env; + dummy(p, _binary_initcode_start, _binary_initcode_size); + + p->sz = PTE_SZ; + ``` + + + ## 今週 + +- 必要が出てきたので`.cbc`の中身を見て`.h`をupdteするスクリプトを実装 +- vmとfs.cの書き換え/デバッグ.... +- OSの質問対応とか \ No newline at end of file
--- a/user/anatofuz/note/2020/02/06.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/06.md Wed Dec 16 15:11:16 2020 +0900 @@ -2,6 +2,18 @@ # panickedをContextに持たせたいやつ + global変数(+static)だったので、Contextにもたせたい + + +```c +typedef struct ConsoleArg <Type, Impl> { + int panicked; + struct spinlock lock; + int locking; +} ConsoleArg; +``` +とりあえず👆のCodeGearを書いてみた + - かいたはいいがpanic出来ず死がまっていた - procが0x00のときにアクセスに行って死んでいた @@ -127,4 +139,6 @@ // Copy process state from p. if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){ -``` \ No newline at end of file +``` + +- https://twitter.com/shinji_kono/status/1225392229646102528 \ No newline at end of file
--- a/user/anatofuz/note/2020/02/08.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/08.md Wed Dec 16 15:11:16 2020 +0900 @@ -7,7 +7,7 @@ - `Gearef(cbc_context,vm)`で死んでる ## 解決 -- 生成したCodeGearをContextに書き戻してなかった +- 生成したDataGearをContextに書き戻してなかった - createでやってると思ってたのでコメントにしてた... ```patch @@ -19,4 +19,10 @@ Gearef(cbc_context, vm)->p = proc; Gearef(cbc_context, vm)->next = C_vm_void_ret ; goto meta(cbc_context, vm->switchuvm); -``` \ No newline at end of file +``` + +## CbCの鉄則 +- createなんとかでDataGearは生成される + - ただの構造体だから!! +- Contextのスロットに保存するにはGearefで参照する必要がある +- 複数実装を共存させるにはCotextのスロットを増やさないとだめそう \ No newline at end of file
--- a/user/anatofuz/note/2020/02/11.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/11.md Wed Dec 16 15:11:16 2020 +0900 @@ -15,7 +15,6 @@ - vm(メモリ関連)の書き換え時に「なにか処理をして引数があってない状況などでpanic」したいケースが多かった - panicもgotoで飛ばしたい -- panicすると、 ## panic自体
--- a/user/anatofuz/note/2020/02/12.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/12.md Wed Dec 16 15:11:16 2020 +0900 @@ -31,4 +31,86 @@ updated_at: Sat, 26 May 2018 08:02:05 UTC +00:00, uid: "k188580", vm_limit: 0> +``` + +## 作業 + +### dalmoreのオブジェクトを取得 + +``` + #<IpAddress:0x000055601865e190 + id: 2514, + user_id: 666, + affiliation: "cr", + domain: "os", + assigned_address: "10.0.0.146", + mac_address: "a0:36:9f:67:6f:60", + created_at: Sat, 26 May 2018 08:10:06 UTC +00:00, + updated_at: Sat, 26 May 2018 08:14:45 UTC +00:00, + vlan: 62>, + #<IpAddress:0x000055601865da38 + id: 1953, + user_id: 35, + affiliation: "cr", + domain: "cinnamon", + assigned_address: "10.0.0.55", + mac_address: "08:00:37:30:7a:47", + created_at: Tue, 23 May 2017 07:29:41 UTC +00:00, +``` + +### 先生のUserオブジェクトを取得 + +``` +[21] pry(main)> User.find_by(uid:"kono") +=> #<User:0x000055601a244cb0 + id: 35, + created_at: Sat, 05 Sep 2015 23:45:51 UTC +00:00, + updated_at: Sat, 05 Sep 2015 23:45:51 UTC +00:00, + uid: "kono", + vm_limit: 0> +[22] pry(main)> IpAddress.find(2514) +=> #<IpAddress:0x0000556019f77898 + id: 2514, + user_id: 666, + affiliation: "cr", + domain: "os", + assigned_address: "10.0.0.146", + mac_address: "a0:36:9f:67:6f:60", + created_at: Sat, 26 May 2018 08:10:06 UTC +00:00, + updated_at: Sat, 26 May 2018 08:14:45 UTC +00:00, + vlan: 62> + ``` + +### dalmoreのuidを書き換える + + ``` +[23] pry(main)> dalmore = IpAddress.find(2514) +=> #<IpAddress:0x0000556018532dc0 + id: 2514, + user_id: 666, + affiliation: "cr", + domain: "os", + assigned_address: "10.0.0.146", + mac_address: "a0:36:9f:67:6f:60", + created_at: Sat, 26 May 2018 08:10:06 UTC +00:00, + updated_at: Sat, 26 May 2018 08:14:45 UTC +00:00, + vlan: 62> +[24] pry(main)> dalmore.user_id +=> 666 +[25] pry(main)> dalmore.user_id = 35 +=> 35 +[26] pry(main)> dalmore +=> #<IpAddress:0x0000556018532dc0 + id: 2514, + user_id: 35, + affiliation: "cr", + domain: "os", + assigned_address: "10.0.0.146", + mac_address: "a0:36:9f:67:6f:60", + created_at: Sat, 26 May 2018 08:10:06 UTC +00:00, + updated_at: Sat, 26 May 2018 08:14:45 UTC +00:00, + vlan: 62> +[27] pry(main)> dalmore.save! +=> true +[28] pry(main)> ``` \ No newline at end of file
--- a/user/anatofuz/note/2020/02/15.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/02/15.md Wed Dec 16 15:11:16 2020 +0900 @@ -33,4 +33,30 @@ ## やること - generate_contextでのstruct回収ルーチンの修正 - - parseに失敗したらskipするようにする \ No newline at end of file + - parseに失敗したらskipするようにする + - おわった +- file Interfaceの残骸の削除 + + +# generate_contextでのstruct回収ルーチンの修正 +- Gears::Utilの`_parse`でパースしている +- `typedef struct (.*) <.*> .* {`に引っかからなかった場合、 対象から落とすようにした + - 構文木みたいなのを作るタイミングで落としている +- .hか.dgがみつからなかった場合でも落とす + +```diff + map { + if ($new_dgs->{$kind}->{$_} =~ /^\d+$/) { +- croak "failed: not found $_.(h|dg)\n"; ++ carp "failed: not found $_.(h|dg)\n"; ++ delete $new_dgs->{$kind}->{$_}; + } + } keys %{$new_dgs->{$kind}}; +``` +- 理論上は`//:skip`を書かなくてもすむようになった気がする + +# __codeの引数に構造体があるケース +- DataGearになっている場合は、 `D_struct_name`になる都合上、 `struct`とか`union`が`stubの時点で落とされる +- `struct hoge`を引数にいれている場合は `hoge = Gearef(cbc_context, hoge)`になるみたいな +- 対処療法的に`typedef`しているが、DataGearをいれる構文を入れたほうが早そう + - とはいえgenerate_stub, generate_contextを直さないといけなさそう \ No newline at end of file
--- a/user/anatofuz/note/2020/03/01.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/01.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,5 +1,28 @@ +# 研究目的 +- コンピュータ上でプログラムを実行したい場合、 ほとんどのプログラムはOSの上で動作する +- 前提となっているOSは高い信頼性を持つことが期待されている +- しかし資源管理や並列処理を頻繁に行うOSでは、テストによってバグを完全に発見することは難しい +- そこでBasicBlock単位で処理が記述できる言語CbCを用いてOSを実装し、 定理証明支援器を使った上での検証を容易にしたい +- すでに完成しているUNIX OSであるxv6をCbCで再実装し、 検証を行いたい + +# 進捗 +- GCCのmerge +- Gearsで生成するcontextにinclude guardを追加した +- 生成スクリプトの整理 +- IO Interfaceを追加した + +## 最近やりたいこと +- GearsOSの仕様の明確化 +- モデル検査もすると良さそうな気がしてきた + +--- + # CbC LLVM +コンパイラの集中講義で作業はある程度されている。 +すでにmergeはされてそう + +## 以前までのバージョンの確認 CbCがありそうなバージョンに戻す `hg update -r 146 -C` @@ -87,9 +110,353 @@ ## 最新バージョンのCbCLLVM内のCbC -3ファイルしかない +CbCでgrepしたところ、3ファイルしかない ``` clang/test/SemaCXX/crashes.cpp tools/clang/lib/Parse/ParseCbC.cpp tools/clang/lib/Parse/CbCHelper.h +``` + +昔のコミットみつつ修正する必要がありそう + +# CbC gccのmerge + +pullしたらheadが2つあるらしい +- 9.2の方の親がoriginalの親のcommitを指しているため + +とりあえず`hg merge`した + +```sh +hg merge +merging configure +merging gcc/Makefile.in +merging gcc/aclocal.m4 +merging gcc/c-family/c-common.c +merging gcc/c-family/c-common.h +merging gcc/c-family/c-pretty-print.c +merging gcc/c/c-decl.c +merging gcc/c/c-parser.c +merging gcc/c/c-tree.h +merging gcc/c/c-typeck.c +merging gcc/calls.c +merging gcc/cfgexpand.c +merging gcc/config.in +merging gcc/config/i386/i386.c +merging gcc/config/i386/i386.md +merging gcc/config/rs6000/rs6000.md +merging gcc/configure +merging gcc/configure.ac +merging gcc/function.c +merging gcc/gcc.c +merging gcc/gimple.c +merging gcc/gimple.h +merging gcc/gimplify.c +merging gcc/ipa-inline.c +merging gcc/passes.c +merging gcc/tree-ssa-operands.c +merging gcc/tree.c +merging gcc/tree.h +warning: conflicts while merging gcc/c-family/c-common.c! (edit, then use 'hg resolve --mark') +warning: conflicts while merging gcc/c/c-decl.c! (edit, then use 'hg resolve --mark') +warning: conflicts while merging gcc/c/c-parser.c! (edit, then use 'hg resolve --mark') +warning: conflicts while merging gcc/calls.c! (edit, then use 'hg resolve --mark') +warning: conflicts while merging gcc/config/i386/i386.c! (edit, then use 'hg resolve --mark') +warning: conflicts while merging gcc/gimple.c! (edit, then use 'hg resolve --mark') +warning: conflicts while merging gcc/ipa-inline.c! (edit, then use 'hg resolve --mark') +38881 files updated, 21 files merged, 2490 files removed, 7 files unresolved +use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon +``` + + + +## GCCのコンフリクト解消 + +- 激しく問題になる箇所は無かった +- ソースコードを追っていてたら、前回のCbCGCCよりC++っぽくなっている + - 構造体を使うのではなくclassにするなど + + +### ipa-inline.c + +- nodeからinlined_toにアクセスする仕方が異なっていた +- 空気を読んで修正 + +#### 変更前 + +```c++ +/* Inline NODE to all callers. Worker for cgraph_for_node_and_aliases. + DATA points to number of calls originally found so we avoid infinite + recursion. */ + +static bool +inline_to_all_callers_1 (struct cgraph_node *node, void *data, + hash_set<cgraph_node *> *callers) +{ + int *num_calls = (int *)data; + bool callee_removed = false; +<<<<<<< working copy +#ifndef noCbC + bool tail_call_f = false; + if (node->callees) { + if (node->callees->call_stmt) { + if (node->callees->call_stmt->vdef) + tail_call_f = gimple_call_tail_p (as_a <gcall *> (node->callees->call_stmt->vdef->ssa_name.def_stmt)); + } + } + while (node->callers && !node->global.inlined_to && !tail_call_f) + { +#else + while (node->callers && !node->global.inlined_to) +======= + + while (node->callers && !node->inlined_to) +>>>>>>> merge rev + { +#endif + struct cgraph_node *caller = node->callers->caller; + + if (!can_inline_edge_p (node->callers, true) + || !can_inline_edge_by_limits_p (node->callers, true) + || node->callers->recursive_p ()) + { +``` + +#### 変更後 + +```c++ +static bool +inline_to_all_callers_1 (struct cgraph_node *node, void *data, + hash_set<cgraph_node *> *callers) +{ + int *num_calls = (int *)data; + bool callee_removed = false; +#ifndef noCbC + bool tail_call_f = false; + if (node->callees) { + if (node->callees->call_stmt) { + if (node->callees->call_stmt->vdef) + tail_call_f = gimple_call_tail_p (as_a <gcall *> (node->callees->call_stmt->vdef->ssa_name.def_stmt)); + } + } + while (node->callers && !node->inlined_to && !tail_call_f) + { +#else + while (node->callers && !node->inlined_to) + { +#endif + struct cgraph_node *caller = node->callers->caller; + ``` + + ### i386 + + - コンフリクトが発生しているが、範囲が関数単位になっている + + ```cpp + ======= +>>>>>>> merge rev +/* Return true if the function being called was marked with attribute + "noplt" or using -fno-plt and we are compiling for non-PIC. We need + to handle the non-PIC case in the backend because there is no easy + interface for the front-end to force non-PLT calls to use the GOT. + This is currently used only with 64-bit or 32-bit GOT32X ELF targets + to call the function marked "noplt" indirectly. */ + +static bool +ix86_nopic_noplt_attribute_p (rtx call_op) +{ + if (flag_pic || ix86_cmodel == CM_LARGE + || !(TARGET_64BIT || HAVE_AS_IX86_GOT32X) + || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF + || SYMBOL_REF_LOCAL_P (call_op)) + return false; + +``` + +#### 解消 + +- `construct_plt_address`などが`gcc/config/i386/i386.c`から`gcc/config/i386/i386-expand.c`に移動していたのが原因 + +```text +$ rg construct_plt_address +gcc/ChangeLog-2007 +26585: * config/i386/i386-protos.h (construct_plt_address): Declare. +26596: (construct_plt_address): New function. + +gcc/ChangeLog-2012 +19809: * config/i386/i386.c (construct_plt_address): Make static. +19810: * config/i386/i386-protos.h (construct_plt_address): Remove. +30371: (construct_plt_address): Assert that Pmode == DImode. + +gcc/ChangeLog-2013 +30685: (construct_plt_address): Likewise. +34395: (construct_plt_address): Don't assert for x64 pe-coff targets. + +gcc/ChangeLog-2019 +27308: (construct_plt_address): Use gen_add2_insn instead of ix86_gen_add3. + +gcc/config/i386/i386-expand.c +7866:construct_plt_address (rtx symbol) +7998: fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0))); +``` + +- i386-expand.cの方に書き直した + +--- + +# Gearsの設計 + +Interfaceの実装側を複数のCodeGearに分けた場合、gotoの直前で実装側の構造体に代入をし直す必要がある +- すべてgoto metaにする場合 +- interfaceの呼び出し時と同じ方針 + +この方針の場合、実装側の入力と出力がなんであるかが明確化されない + +## 実装から変数を取得する方法 + +この場合`i`や`sz`などはvm_implのメンバであるため、引数に書く必要がないといえば無い +- Perl5に近い値の取得方法が可能 + +```c +__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, uint i, uint sz,__code next(int ret, ...)) { + if (i < sz) { + goto loaduvm_check_pgdir(vm_impl, next(ret, ...)); + } + + goto loaduvm_exit(vm_impl, next(ret, ...)); +} + +``` +```c +__code loaduvm_loopvm_impl(struct vm_impl* vm_impl) { + uint i = vm_impl->i; + uint sz = vm_impl->sz; + __code next = vm_impl->next; + int ret = vm_impl->ret; + if (i < sz) { + goto loaduvm_check_pgdir(vm_impl, next(ret, ...)); + } + + goto loaduvm_exit(vm_impl, next(ret, ...)); +} +``` +この代入文をPerlスクリプトで生成するアプローチもありそう + +## 引数を構造体にしてしまう案 + +引数自体を構造体にする + +``` +__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, uint i, uint sz,__code next(int ret, ...)) { + +struct loaduvm_loopvm_arg { + uint i; + uint sz; + enum Code next; + int ret; +} + +struct vm_impl { + struct loaduvm_loopvm_arg loaduvm_arg; + struct hoge_arg hoge_arg; +} + +``` + +goto する直前でgotoする対象の引数の構造体に書き込む + +```c +__code loaduvm_loopvm_impl(struct vm_impl* vm_impl, struct loaduvm_loopvm_arg* arg) { + /* + Gearef(other_arg)->n = n; + */ + goto other(vm_impl); +} +``` + +--- + +# CodeGear + +Gearsで使用される基本的な処理のまとまり。 + +CbCの`__code`のこと + +## 宣言 + +```c +__code cg_name(struct hoge* foo) +``` + +# Interface + +Gearsでのモジュール化の仕組み。JavaのInterface, Haskellの型クラスに相当する。 + +InterfaceはAPIの定義になっており、満たすべきCodeGearと入力を記述する。 + +## 記述 + +### 今現在 + +```c +typedef struct IO <Type, Impl> { + __code read(Impl* io, struct file* file, char* addr, int n, __code next(...)); + __code write(Impl* io, struct file* file, char* addr, int n, __code next(...)); + __code close(Impl* io, struct file* file, int fd, __code next(...)); + __code next(...); +} IO; +``` + + +### 案1 + +- 先頭に`interface`と書き、`<>`の中に利用したいデータ型を書く + - Typeは自分自身の型, Implは実装の型になる + +```c +interface IO <Type, Impl> { + __code read(Impl* io, struct file* file, char* addr, int n, __code next(...)); + __code write(Impl* io, struct file* file, char* addr, int n, __code next(...)); + __code close(Impl* io, struct file* file, int fd, __code next(...)); + __code next(...); +}; +``` + + +## CbCレベルでの表現 + +Interfaceは構造体に変換される。 + +変換される構造体は次のfieldを持つ。 + +- 実装へのポインタ +- 定義したCodeGearの名前に対応したenum Code +- CodeGearの引数 + +上のIOの場合は次のような構造体に変換される。 + +```c +struct IO { + union Data* io; + struct file* file; + char* addr; + int n; + int fd; + enum Code read; + enum Code write; + enum Code close; + enum Code next; +} IO; +``` + +# Interfaceの実装 + +宣言したInterfaceは実装を持つ事ができる。 + + +# Interfaceを使うCodeGearの宣言 + +```c +__code test_code1(IO *io, char* args, __code next(...)) { + goto io->write(args, next); +} ``` \ No newline at end of file
--- a/user/anatofuz/note/2020/03/11.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/11.md Wed Dec 16 15:11:16 2020 +0900 @@ -139,3 +139,73 @@ clang/include/clang/AST/CanonicalType.h clang/include/clang/Basic/Specifiers.h ``` + +## 今のバージョンにないファイル + +`cat ../cbc_llvm_tmp/tmp | perl -lne 'if (!-f ) { print }' > no_found.txt` + +```text +include/llvm/LinkAllPasses.h +lib/IR/Core.cpp +lib/IR/LLVMContextImpl.cpp +lib/IR/ValueTypes.cpp +lib/CodeGen/TargetPassConfig.cpp +lib/IR/AsmWriter.cpp +lib/IR/LLVMContextImpl.h +lib/IR/Type.cpp +include/llvm/Target/TargetOptions.h +include/llvm/IR/Type.h +include/llvm/IR/IRBuilder.h +include/llvm/Transforms/Scalar.h +include/llvm/CodeGen/TargetPassConfig.h +lib/Target/NVPTX/NVPTXAsmPrinter.cpp +lib/Target/NVPTX/NVPTXISelLowering.cpp +lib/Target/XCore/XCoreISelLowering.cpp +lib/Target/Hexagon/HexagonTargetObjectFile.cpp +lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +lib/ExecutionEngine/MCJIT/MCJIT.cpp +lib/Bitcode/Writer/BitcodeWriter.cpp +lib/Transforms/IPO/PassManagerBuilder.cpp +lib/Transforms/Utils/FunctionComparator.cpp +lib/Transforms/Scalar/Scalar.cpp +lib/Transforms/Scalar/SROA.cpp +lib/Transforms/Scalar/TailRecursionElimination.cpp +lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +clang/lib/Analysis/FormatString.cpp +clang/lib/Parse/ParseCbC.cpp +clang/lib/Parse/CbCHelper.h +``` + +## 発見できなったのはこれっぽい + +```text +llvm/include/llvm/LinkAllPasses.h +llvm/lib/IR/Core.cpp +llvm/lib/IR/LLVMContextImpl.cpp +llvm/lib/IR/ValueTypes.cpp +llvm/lib/CodeGen/TargetPassConfig.cpp +llvm/lib/IR/AsmWriter.cpp +llvm/lib/IR/LLVMContextImpl.h +llvm/lib/IR/Type.cpp +llvm/include/llvm/Target/TargetOptions.h +llvm/include/llvm/IR/Type.h +llvm/include/llvm/IR/IRBuilder.h +llvm/include/llvm/Transforms/Scalar.h +llvm/include/llvm/CodeGen/TargetPassConfig.h +llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +llvm/lib/Target/XCore/XCoreISelLowering.cpp +llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp +llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp +llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +llvm/lib/Transforms/Utils/FunctionComparator.cpp +llvm/lib/Transforms/Scalar/Scalar.cpp +llvm/lib/Transforms/Scalar/SROA.cpp +llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +llvm/clang/lib/Analysis/FormatString.cpp +llvm/clang/lib/Parse/ParseCbC.cpp +llvm/clang/lib/Parse/CbCHelper.h +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/03/12.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/12.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,227 @@ +# llvm + +ビルドスクリプト +```sh +cmake3 -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=$PWD -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,/usr/local/gcc9/lib64 -L$HOME/usr/local/gcc9/lib64" ~/src/CbC_llvm/llvm +``` + +ここのオプションでlibcを作るとエラーが発生する(CMakeレベルで) + +``` +-DLLVM_ENABLE_PROJECTS="clang;libgcc;libcxx;libcxxabi" +``` + +## clang/lib/Parse/ParseDecl.cpp + +まさかの上半分をすっ飛ばしていた +- reverして復旧 + + +## PrettyDeclStackTree.hが無い + ``` /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:9:10: fatal error: clang/Sema/PrettyDeclStackTrace.h: No such file or directory 9 | #include "clang/Sema/PrettyDeclStackTrace.h" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` + +SemaからASTに変更されているらしい + +```sh +$ fd PrettyDeclStackTrace.h +clang/include/clang/AST/PrettyDeclStackTrace.h +``` + +# でたエラー + +```log +[2484/3841] Building CXX object tools/clang/lib/Lex/CMakeFiles/obj.clangLex.dir/PPDirectives.cpp.o +FAILED: tools/clang/lib/Lex/CMakeFiles/obj.clangLex.dir/PPDirectives.cpp.o +/usr/local/gcc9/bin/g++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/clang/lib/Lex -I/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex -I/mnt/dalmore-home/one/src/CbC_llvm/clang/include -Itools/clang/include -I/usr/include/libxml2 -Iinclude -I/mnt/dalmore-home/one/src/CbC_llvm/llvm/include -fPIC -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -fdiagnostics-color -fno-common -Woverloaded-virtual -fno-strict-aliasing -g -fno-exceptions -fno-rtti -std=c++14 -MD -MT tools/clang/lib/Lex/CMakeFiles/obj.clangLex.dir/PPDirectives.cpp.o -MF tools/clang/lib/Lex/CMakeFiles/obj.clangLex.dir/PPDirectives.cpp.o.d -o tools/clang/lib/Lex/CMakeFiles/obj.clangLex.dir/PPDirectives.cpp.o -c /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex/PPDirectives.cpp +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex/PPDirectives.cpp: In member function 'bool clang::Preprocessor::IncludeHeader(clang::Token, const char*)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex/PPDirectives.cpp:3120:28: error: 'angle_string_literal' is not a member of 'clang::tok'; did you mean 'wide_string_literal'? + 3120 | FilenameTok.setKind(tok::angle_string_literal); + | ^~~~~~~~~~~~~~~~~~~~ + | wide_string_literal +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex/PPDirectives.cpp:3131:65: error: no matching function for call to 'clang::Preprocessor::LookupFile(clang::SourceLocation&, llvm::StringRef&, bool&, const clang::DirectoryLookup*&, std::nullptr_t, const clang::DirectoryLookup*&, std::nullptr_t, std::nullptr_t, clang::ModuleMap::KnownHeader*, bool*)' + 3131 | &SuggestedModule, &IsMapped); + | ^ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex/PPDirectives.cpp:721:24: note: candidate: 'llvm::Optional<clang::FileEntryRef> clang::Preprocessor::LookupFile(clang::SourceLocation, llvm::StringRef, bool, const clang::DirectoryLookup*, const clang::FileEntry*, const clang::DirectoryLookup*&, llvm::SmallVectorImpl<char>*, llvm::SmallVectorImpl<char>*, clang::ModuleMap::KnownHeader*, bool*, bool*, bool)' + 721 | Optional<FileEntryRef> Preprocessor::LookupFile( + | ^~~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Lex/PPDirectives.cpp:721:24: note: candidate expects 12 arguments, 10 provided +[2523/3841] Building CXX object tools/clang/lib/Parse/CMakeFiles/obj.clangParse.dir/ParseCbC.cpp.o +FAILED: tools/clang/lib/Parse/CMakeFiles/obj.clangParse.dir/ParseCbC.cpp.o +/usr/local/gcc9/bin/g++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/clang/lib/Parse -I/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse -I/mnt/dalmore-home/one/src/CbC_llvm/clang/include -Itools/clang/include -I/usr/include/libxml2 -Iinclude -I/mnt/dalmore-home/one/src/CbC_llvm/llvm/include -fPIC -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -fdiagnostics-color -fno-common -Woverloaded-virtual -fno-strict-aliasing -g -fno-exceptions -fno-rtti -std=c++14 -MD -MT tools/clang/lib/Parse/CMakeFiles/obj.clangParse.dir/ParseCbC.cpp.o -MF tools/clang/lib/Parse/CMakeFiles/obj.clangParse.dir/ParseCbC.cpp.o.d -o tools/clang/lib/Parse/CMakeFiles/obj.clangParse.dir/ParseCbC.cpp.o -c /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::ExprResult clang::Parser::Prepare__envForGotoWithTheEnvExpr()': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:260:166: error: cannot bind rvalue reference of type 'clang::ParsedAttributes&&' to lvalue of type 'clang::ParsedAttributes' + 260 | star_DS.getRestrictSpecLoc(),star_DS.getAtomicSpecLoc(),star_DS.getUnalignedSpecLoc()),star_DS.getAttributes(),SourceLocation()); + | ~~~~~~~~~~~~~~~~~~~~~^~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:2199:66: note: initializing argument 2 of 'void clang::Declarator::AddTypeInfo(const clang::DeclaratorChunk&, clang::ParsedAttributes&&, clang::SourceLocation)' + 2199 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, + | ~~~~~~~~~~~~~~~~~~~^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::StmtResult clang::Parser::CreateAssignmentStmt(clang::IdentifierInfo*, clang::IdentifierInfo*, bool, bool, clang::IdentifierInfo*, clang::IdentifierInfo*)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:288:106: error: invalid new-expression of abstract class type 'ExternalSpace::StatementFilterCCC' + 288 | std::unique_ptr<ExternalSpace::StatementFilterCCC> Validator(new ExternalSpace::StatementFilterCCC(Next)); + | ^ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:47:9: note: because the following virtual functions are pure within 'ExternalSpace::StatementFilterCCC': + 47 | class StatementFilterCCC : public CorrectionCandidateCallback { + | ^~~~~~~~~~~~~~~~~~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/ExternalSemaSource.h:17, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:47, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:25, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/TypoCorrection.h:320:56: note: 'virtual std::unique_ptr<clang::CorrectionCandidateCallback> clang::CorrectionCandidateCallback::clone()' + 320 | virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0; + | ^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:289:149: error: no matching function for call to 'clang::Sema::ClassifyName(clang::Scope*, clang::CXXScopeSpec&, clang::IdentifierInfo*&, clang::SourceLocation&, clang::Token&, bool, std::remove_reference<std::unique_ptr<ExternalSpace::StatementFilterCCC>&>::type)' + 289 | Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, LHSII, Loc, Next, false, SS.isEmpty() ? std::move(Validator) : 0); + | ^ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:25, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2111:22: note: candidate: 'clang::Sema::NameClassification clang::Sema::ClassifyName(clang::Scope*, clang::CXXScopeSpec&, clang::IdentifierInfo*&, clang::SourceLocation, const clang::Token&, clang::CorrectionCandidateCallback*)' + 2111 | NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, + | ^~~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2111:22: note: candidate expects 6 arguments, 7 provided +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::StmtResult clang::Parser::CreateDeclStmt(clang::IdentifierInfo*, bool, bool, clang::DeclSpec::TST, clang::IdentifierInfo*, clang::DeclSpec::TQ)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:332:141: error: cannot bind rvalue reference of type 'clang::ParsedAttributes&&' to lvalue of type 'clang::ParsedAttributes' + 332 | FDS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), FDS.getUnalignedSpecLoc()), FDS.getAttributes(), SourceLocation()); + | ~~~~~~~~~~~~~~~~~^~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:2199:66: note: initializing argument 2 of 'void clang::Declarator::AddTypeInfo(const clang::DeclaratorChunk&, clang::ParsedAttributes&&, clang::SourceLocation)' + 2199 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, + | ~~~~~~~~~~~~~~~~~~~^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:372:156: error: no matching function for call to 'clang::DeclaratorChunk::getFunction(bool&, bool, clang::SourceLocation&, llvm::SmallVectorTemplateCommon<clang::DeclaratorChunk::ParamInfo, void>::pointer, size_t, clang::SourceLocation&, clang::SourceLocation&, unsigned int, bool&, clang::SourceLocation&, clang::SourceLocation&, clang::SourceLocation&, clang::SourceLocation&, clang::SourceLocation, clang::ExceptionSpecificationType&, clang::SourceLocation, llvm::SmallVectorTemplateCommon<clang::OpaquePtr<clang::QualType>, void>::pointer, llvm::SmallVectorTemplateCommon<clang::SourceRange, void>::pointer, size_t, clang::Expr*, clang::CachedTokens*&, const llvm::NoneType&, clang::SourceLocation&, clang::SourceLocation&, clang::ParsingDeclarator&, clang::TypeResult&)' + 372 | NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0, ExceptionSpecTokens, None, Loc, Loc, D, TrailingReturnType), + | ^ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:1621:26: note: candidate: 'static clang::DeclaratorChunk clang::DeclaratorChunk::getFunction(bool, bool, clang::SourceLocation, clang::DeclaratorChunk::ParamInfo*, unsigned int, clang::SourceLocation, clang::SourceLocation, bool, clang::SourceLocation, clang::SourceLocation, clang::ExceptionSpecificationType, clang::SourceRange, clang::ParsedType*, clang::SourceRange*, unsigned int, clang::Expr*, clang::CachedTokens*, llvm::ArrayRef<clang::NamedDecl*>, clang::SourceLocation, clang::SourceLocation, clang::Declarator&, clang::TypeResult, clang::DeclSpec*)' + 1621 | static DeclaratorChunk getFunction(bool HasProto, + | ^~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:1621:26: note: candidate expects 23 arguments, 26 provided +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::ExprResult clang::Parser::LookupNameAndBuildExpr(clang::IdentifierInfo*, bool)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:509:126: error: invalid new-expression of abstract class type 'ExternalSpace::CastExpressionIdValidator' + 509 | std::unique_ptr<ExternalSpace::CastExpressionIdValidator> Validator(new ExternalSpace::CastExpressionIdValidator(false,true)); + | ^ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:26:9: note: because the following virtual functions are pure within 'ExternalSpace::CastExpressionIdValidator': + 26 | class CastExpressionIdValidator : public CorrectionCandidateCallback { + | ^~~~~~~~~~~~~~~~~~~~~~~~~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/ExternalSemaSource.h:17, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:47, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:25, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/TypoCorrection.h:320:56: note: 'virtual std::unique_ptr<clang::CorrectionCandidateCallback> clang::CorrectionCandidateCallback::clone()' + 320 | virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0; + | ^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:511:112: error: cannot convert 'std::remove_reference<std::unique_ptr<ExternalSpace::CastExpressionIdValidator>&>::type' {aka 'std::unique_ptr<ExternalSpace::CastExpressionIdValidator>'} to 'clang::CorrectionCandidateCallback*' + 511 | return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, false, IsAddressOfOperand, std::move(Validator)); + | ~~~~~~~~~^~~~~~~~~~~ + | | + | std::remove_reference<std::unique_ptr<ExternalSpace::CastExpressionIdValidator>&>::type {aka std::unique_ptr<ExternalSpace::CastExpressionIdValidator>} +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:25, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:4611:36: note: initializing argument 7 of 'clang::ExprResult clang::Sema::ActOnIdExpression(clang::Scope*, clang::CXXScopeSpec&, clang::SourceLocation, clang::UnqualifiedId&, bool, bool, clang::CorrectionCandidateCallback*, bool, clang::Token*)' + 4611 | CorrectionCandidateCallback *CCC = nullptr, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'void clang::Parser::Create__CbC_envStruct(clang::SourceLocation, clang::AccessSpecifier)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:562:79: error: 'struct clang::Parser::ParsedAttributesWithRange' has no member named 'getList' + 562 | SDS.getTypeSpecScope(), Name, Loc, attrs.getList(), AS, + | ^~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:567:89: error: no matching function for call to 'clang::PrettyDeclStackTraceEntry::PrettyDeclStackTraceEntry(clang::Sema&, clang::Decl*&, clang::SourceLocation&, const char [26])' + 567 | PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, Loc, "parsing struct/union body"); + | ^ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:9: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/AST/PrettyDeclStackTrace.h:37:3: note: candidate: 'clang::PrettyDeclStackTraceEntry::PrettyDeclStackTraceEntry(clang::ASTContext&, clang::Decl*, clang::SourceLocation, const char*)' + 37 | PrettyDeclStackTraceEntry(ASTContext &Ctx, Decl *D, SourceLocation Loc, + | ^~~~~~~~~~~~~~~~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/AST/PrettyDeclStackTrace.h:37:41: note: no known conversion for argument 1 from 'clang::Sema' to 'clang::ASTContext&' + 37 | PrettyDeclStackTraceEntry(ASTContext &Ctx, Decl *D, SourceLocation Loc, + | ~~~~~~~~~~~~^~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:575:77: error: 'struct clang::Parser::ParsedAttributesWithRange' has no member named 'getList' + 575 | Actions.ActOnFields(getCurScope(),Loc, TagDecl, FieldDecls,Loc, Loc,attrs.getList()); + | ^~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::Decl* clang::Parser::Create__CbC_envBody(clang::Decl*, clang::DeclSpec::TST, clang::SourceLocation, const char*)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:599:48: error: cannot bind rvalue reference of type 'clang::ParsedAttributes&&' to lvalue of type 'clang::ParsedAttributes' + 599 | DS.getAttributes(),SourceLocation()); + | ~~~~~~~~~~~~~~~~^~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:2199:66: note: initializing argument 2 of 'void clang::Declarator::AddTypeInfo(const clang::DeclaratorChunk&, clang::ParsedAttributes&&, clang::SourceLocation)' + 2199 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, + | ~~~~~~~~~~~~~~~~~~~^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'void clang::Parser::CreateRetCS(clang::IdentifierInfo*)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:701:77: error: no matching function for call to 'clang::DeclaratorChunk::getFunction(bool&, bool&, clang::SourceLocation&, llvm::SmallVectorTemplateCommon<clang::DeclaratorChunk::ParamInfo, void>::pointer, size_t, clang::SourceLocation&, clang::SourceLocation&, unsigned int, bool&, clang::SourceLocation&, clang::SourceLocation&, clang::SourceLocation&, clang::SourceLocation&, clang::SourceLocation, clang::ExceptionSpecificationType&, clang::SourceLocation, llvm::SmallVectorTemplateCommon<clang::OpaquePtr<clang::QualType>, void>::pointer, llvm::SmallVectorTemplateCommon<clang::SourceRange, void>::pointer, size_t, clang::Expr*, clang::CachedTokens*&, const llvm::NoneType&, clang::SourceLocation&, clang::SourceLocation&, clang::ParsingDeclarator&, clang::TypeResult&)' + 701 | Loc, Loc, D, TrailingReturnType), FnAttrs, Loc); + | ^ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:1621:26: note: candidate: 'static clang::DeclaratorChunk clang::DeclaratorChunk::getFunction(bool, bool, clang::SourceLocation, clang::DeclaratorChunk::ParamInfo*, unsigned int, clang::SourceLocation, clang::SourceLocation, bool, clang::SourceLocation, clang::SourceLocation, clang::ExceptionSpecificationType, clang::SourceRange, clang::ParsedType*, clang::SourceRange*, unsigned int, clang::Expr*, clang::CachedTokens*, llvm::ArrayRef<clang::NamedDecl*>, clang::SourceLocation, clang::SourceLocation, clang::Declarator&, clang::TypeResult, clang::DeclSpec*)' + 1621 | static DeclaratorChunk getFunction(bool HasProto, + | ^~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:1621:26: note: candidate expects 23 arguments, 26 provided +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:736:44: error: cannot bind rvalue reference of type 'clang::ParsedAttributes&&' to lvalue of type 'clang::ParsedAttributes' + 736 | starDS.getAttributes(), + | ~~~~~~~~~~~~~~~~~~~~^~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:2199:66: note: initializing argument 2 of 'void clang::Declarator::AddTypeInfo(const clang::DeclaratorChunk&, clang::ParsedAttributes&&, clang::SourceLocation)' + 2199 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, + | ~~~~~~~~~~~~~~~~~~~^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:782:37: error: cannot bind rvalue reference of type 'clang::ParsedAttributes&&' to lvalue of type 'clang::ParsedAttributes' + 782 | ljDS.getAttributes(), + | ~~~~~~~~~~~~~~~~~~^~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:2199:66: note: initializing argument 2 of 'void clang::Declarator::AddTypeInfo(const clang::DeclaratorChunk&, clang::ParsedAttributes&&, clang::SourceLocation)' + 2199 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, + | ~~~~~~~~~~~~~~~~~~~^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::ExprResult clang::Parser::IIToExpr(clang::IdentifierInfo*, clang::tok::TokenKind)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:815:109: error: invalid new-expression of abstract class type 'ExternalSpace::StatementFilterCCC' + 815 | std::unique_ptr<ExternalSpace::StatementFilterCCC> CCCValidator(new ExternalSpace::StatementFilterCCC(Next)); + | ^ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:817:130: error: no matching function for call to 'clang::Sema::ClassifyName(clang::Scope*, clang::CXXScopeSpec&, clang::IdentifierInfo*&, clang::SourceLocation&, clang::Token&, bool, std::remove_reference<std::unique_ptr<ExternalSpace::StatementFilterCCC>&>::type)' + 817 | Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, II, Loc, Next, false, std::move(CCCValidator)); + | ^ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:25, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2111:22: note: candidate: 'clang::Sema::NameClassification clang::Sema::ClassifyName(clang::Scope*, clang::CXXScopeSpec&, clang::IdentifierInfo*&, clang::SourceLocation, const clang::Token&, clang::CorrectionCandidateCallback*)' + 2111 | NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, + | ^~~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2111:22: note: candidate expects 6 arguments, 7 provided +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::ParmVarDecl* clang::Parser::CreateParam(clang::IdentifierInfo*, int, clang::DeclSpec::TST)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:864:56: error: cannot bind rvalue reference of type 'clang::ParsedAttributes&&' to lvalue of type 'clang::ParsedAttributes' + 864 | pointerDS.getAttributes(),SourceLocation()); + | ~~~~~~~~~~~~~~~~~~~~~~~^~ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:24, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/DeclSpec.h:2199:66: note: initializing argument 2 of 'void clang::Declarator::AddTypeInfo(const clang::DeclaratorChunk&, clang::ParsedAttributes&&, clang::SourceLocation)' + 2199 | void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, + | ~~~~~~~~~~~~~~~~~~~^~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'void clang::Parser::setTST(clang::DeclSpec*, clang::DeclSpec::TST, clang::IdentifierInfo*, clang::DeclSpec::TQ)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:894:61: error: 'struct clang::Parser::ParsedAttributesWithRange' has no member named 'getList' + 894 | SS, Name, Loc, attrs.getList(), AS_none, + | ^~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:904:111: error: invalid new-expression of abstract class type 'ExternalSpace::StatementFilterCCC' + 904 | std::unique_ptr<ExternalSpace::StatementFilterCCC> CCCValidator(new ExternalSpace::StatementFilterCCC(Next)); + | ^ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:905:134: error: no matching function for call to 'clang::Sema::ClassifyName(clang::Scope*, clang::CXXScopeSpec&, clang::IdentifierInfo*&, clang::SourceLocation&, clang::Token&, bool, std::remove_reference<std::unique_ptr<ExternalSpace::StatementFilterCCC>&>::type)' + 905 | Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, Loc, Next, false, std::move(CCCValidator)); + | ^ +In file included from /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Parse/Parser.h:25, + from /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:3: +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2111:22: note: candidate: 'clang::Sema::NameClassification clang::Sema::ClassifyName(clang::Scope*, clang::CXXScopeSpec&, clang::IdentifierInfo*&, clang::SourceLocation, const clang::Token&, clang::CorrectionCandidateCallback*)' + 2111 | NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS, + | ^~~~~~~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2111:22: note: candidate expects 6 arguments, 7 provided +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp: In member function 'clang::StmtResult clang::Parser::ParseCbCGotoStatement(clang::Parser::ParsedAttributesWithRange&, clang::Parser::StmtVector&)': +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:964:48: error: 'ACK_Any' was not declared in this scope + 964 | gotoRes = ParseStatementOrDeclaration(Stmts, ACK_Any); + | ^~~~~~~ +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:977:66: error: 'struct clang::Parser::ParsedAttributesWithRange' has no member named 'getList' + 977 | gotoRes = Actions.ProcessStmtAttributes(gotoRes.get(), Attrs.getList(), Attrs.Range); ``` \ No newline at end of file
--- a/user/anatofuz/note/2020/03/14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/14.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,11 @@ +# 同人誌を書くやつ +- お腹が空いて力がでない... + + +# LLVMとか + + + エラーっぽい ```text @@ -28,6 +36,9 @@ なんかこの関数の呼び出しで死んでそうな気がする +`./clang/include/clang/Sema/DeclSpec.h` + + `DeclaratorInfo.AddTypeInfo(DeclaratorChunk::getPointer(star_DS.getTypeQualifiers(), Loc,star_DS.getConstSpecLoc(),star_DS.getVolatileSpecLoc(),`
--- a/user/anatofuz/note/2020/03/17.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/17.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,113 @@ # 今週やったこと - LLVMのmerge +- dalmoreにこっそりripgrepとfdをいれた - LLVMでの`CbCParse.cpp`のソースコード読み - そんな出来てない -- Rakuの同人誌書く作業 \ No newline at end of file +- Rakuの同人誌書く作業 +- Desktopの整備 +- OS研究会どうしよう... + +# LLVM +- 70ちょいのファイルをひたすらコピペする作業をした +- `clang/lib/Parse/ParseCbC.cpp`と`CbCHelper.h`以外は意外とすんなり言っている + - ParseCbC.cppが結構たいへんそう + +## ParseCbC.cpp +- 大体の処理は環境付きgotoの手続き +- CodeSegmentの引数処理も存在している +- 当時の他のコードを参考にしつつ書いていたみたいだが、 バージョンアップの際にかなりAPIが変わっており変更点が多い + + + +## 現状問題になってる箇所 + +### ヘッダファイルの変更 + +PrettyDeclStackTree.hが無い + +``` +/mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:9:10: fatal error: clang/Sema/PrettyDeclStackTrace.h: No such file or directory + 9 | #include "clang/Sema/PrettyDeclStackTrace.h" + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` +SemaからASTに変更されているらしい + +``` +$ fd PrettyDeclStackTrace.h +clang/include/clang/AST/PrettyDeclStackTrace.h +``` + + +### setjmp関連 +- `void Parser::CheckTheSjHeader()`でまず死んでいる +- setjmpをincludeしているか確認して、includeしていなかったらincludeする(トークンを発行する) + - `PP.IncludeHeader`が使用しているLLVMのAPIが存在していない(バージョンアップのタイミングで無くなった) + +- setjmp使わない方針で実装しなおすなら、この関数は治す必要がない + - どっちの方針で行くかによって違いそう +```cpp +/// CheckTheSjHeader - Check whether setjmp.h has been already included or not. +/// If not, include it. +void Parser::CheckTheSjHeader(){ + SourceLocation Loc = Tok.getLocation(); + LookupResult R(Actions, CreateIdentifierInfo("setjmp", Loc), Loc, Actions.LookupOrdinaryName, Actions.ForVisibleRedeclaration); + if (!Actions.LookupName(R, getCurScope())){ // look up the setjmp + if (PP.IncludeHeader(Tok, "setjmp.h")) + ConsumeToken(); + } +} +``` + +### 他多数... + +- 地道になおしていくしかない... +- 変更前の最後のchangesetが146なので、これを指定してupdateしたllvmと見比べつつ治す + +# dalmore + +ripgrep(rg)とfdをいれました +- わりと趣味ですが... + +## ripgrep + +Rustで書かれている早いgrep + +grepみたいに使えるが、コマンド自体が再帰的に検索する + +```shell= +$rg CbC -g '*.h' -g '*.cpp' +llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +1269:#ifndef noCbC + +llvm/lib/Target/Hexagon/HexagonTargetObjectFile.cpp +333:#ifndef noCbC + +llvm/lib/Target/XCore/XCoreISelLowering.cpp +1887:#ifndef noCbC + +llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +288:#ifndef noCbC +299:#ifndef noCbC +``` + +## fd + +Rustで書かれている早いfind + +```shell +$fd CbC +crdocs/CbC on LLVM.mm +clang/lib/Parse/CbCHelper.h +clang/lib/Parse/ParseCbC.cpp +``` + +# OS研究会 +- XV6の話で出す? + - 去年の坂本くんはみつきさんのreadの話 + - 一応優さんのページングのやつも出てはいる +- 今回の内容 + - Interface追加した + - これは部分的に出来ている + - モデル検査 or Agdaでの検証...? (間に合う?) + \ No newline at end of file
--- a/user/anatofuz/note/2020/03/19.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/19.md Wed Dec 16 15:11:16 2020 +0900 @@ -28,4 +28,61 @@ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); if (Tok.is(tok::semi)) ConsumeToken(); - ``` \ No newline at end of file + ``` + + # ビルドは通った + + - コンパイル時にSemaで死ぬ + +```log +clang-11: /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2052: clang::ExprResult clang::Sema::NameClassification::getExpression() const: Assertion `Kind == NC_ContextIndependentExpr' failed. +Stack dump: +0. Program arguments: /mnt/dalmore-home/one/build/anatofuz/llvm/bin/clang-11 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name test1.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fdenormal-fp-math=ieee,ieee -fdenormal-fp-math-f32=ieee,ieee -ffp-contract=on -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /mnt/dalmore-home/one/build/anatofuz/llvm/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem /mnt/dalmore-home/one/build/anatofuz/llvm/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /mnt/dalmore-home/one/build/anatofuz/llvm/tmp -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/test1-8dd959.o -x c /mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c +1. /mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c:117:17 <Spelling=/mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c:2:18>: current parser token '_CbC_return' +2. /mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c:106:1: parsing function body 'main' +3. /mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c:106:1: in compound statement ('{}') +4. /mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c:117:17 <Spelling=/mnt/dalmore-home//one/src/CbC_gcc/CbC-examples/test1.c:2:18>: in compound statement ('{}') +^C ++dalmore+one +``` + + + +```text +(gdb) b clang/include/clang/Sema/Sema.h:2052 +Breakpoint 1 at 0x59802d6: file /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h, line 2052. +(gdb) run +Starting program: /mnt/dalmore-home/one/build/anatofuz/llvm/bin/clang-11 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name fizzbuzz.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fdenormal-fp-math=ieee,ieee -fdenormal-fp-math-f32=ieee,ieee -ffp-contract=on -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /mnt/dalmore-home/one/build/anatofuz/llvm/lib/clang/11.0.0 -internal-isystem /usr/local/include -internal-isystem /mnt/dalmore-home/one/build/anatofuz/llvm/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /mnt/dalmore-home/one/build/anatofuz/llvm -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -x c fizzbuzz.c +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/lib64/libthread_db.so.1". +warning: File "/usr/local/gcc9/lib64/libstdc++.so.6.0.28-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load:/usr/bin/mono-gdb.py:/usr/lib/golang/src/runtime/runtime-gdb.py". +To enable execution of this file add + add-auto-load-safe-path /usr/local/gcc9/lib64/libstdc++.so.6.0.28-gdb.py +line to your configuration file "/mnt/dalmore-home//one/.gdbinit". +To completely disable this security protection add + set auto-load safe-path / +line to your configuration file "/mnt/dalmore-home//one/.gdbinit". +For more information about this security protection see the +"Auto-loading safe path" section in the GDB manual. E.g., run from the shell: + info "(gdb)Auto-loading safe path" + +Breakpoint 1, clang::Sema::NameClassification::getExpression (this=0x7fffffff5130) at /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2052 +2052 assert(Kind == NC_ContextIndependentExpr); +Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7_6.3.x86_64 ncurses-libs-5.9-14.20130511.el7_4.x86_64 zlib-1.2.7-18.el7.x86_64 +(gdb) bt +#0 clang::Sema::NameClassification::getExpression (this=0x7fffffff5130) at /mnt/dalmore-home/one/src/CbC_llvm/clang/include/clang/Sema/Sema.h:2052 +#1 0x000000000598b0a9 in clang::Parser::IIToExpr (this=0xe681410, II=0xe64f2a8, Kind=clang::tok::l_paren) + at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:830 +#2 0x000000000598a7de in clang::Parser::CreateRetCS (this=0xe681410, csName=0xe767e68) at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:773 +#3 0x0000000005986a88 in clang::Parser::Prepare__retForGotoWithTheEnvExpr (this=0xe681410) + at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseCbC.cpp:154 +#4 0x00000000059e86f5 in clang::Parser::ParseExpressionList(llvm::SmallVectorImpl<clang::Expr*>&, llvm::SmallVectorImpl<clang::SourceLocation>&, llvm::function_ref<void ()>) (this=0xe681410, Exprs=..., CommaLocs=..., ExpressionStarts=...) at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseExpr.cpp:3146 +#5 0x00000000059e303c in clang::Parser::ParsePostfixExpressionSuffix (this=0xe681410, LHS=...) + at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseExpr.cpp:1922 +#6 0x00000000059e20eb in clang::Parser::ParseCastExpression (this=0xe681410, ParseKind=clang::Parser::AnyCastExpr, isAddressOfOperand=false, + NotCastExpr=@0x7fffffff8e9f: false, isTypeCast=clang::Parser::NotTypeCast, isVectorLiteral=false, NotPrimaryExpression=0x0) + at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseExpr.cpp:1723 +#7 0x00000000059dde6f in clang::Parser::ParseCastExpression (this=0xe681410, ParseKind=clang::Parser::AnyCastExpr, isAddressOfOperand=false, + isTypeCast=clang::Parser::NotTypeCast, isVectorLiteral=false, NotPrimaryExpression=0x0) + at /mnt/dalmore-home/one/src/CbC_llvm/clang/lib/Parse/ParseExpr.cpp:668 +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/03/23.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/23.md Wed Dec 16 15:11:16 2020 +0900 @@ -8,8 +8,12 @@ ## ビルド方法 - dalmoreでやる + +### とりあえずmake - `$cmake` で試す - - gccが新しすぎてコンパイルできなかった -- 古めのgcc(gcc-4)くらいで試す - - dalmoreの場合は`/usr/bin/gcc`が古いgcc - - cmakeの実行時にオプションで渡しておく \ No newline at end of file + - gccが新しすぎてビルドできなかった + +### 古めのgcc(gcc-4)くらいで試す +- dalmoreの場合は`/usr/bin/gcc`が古いgcc +- cmakeの実行時にオプションで渡しておく +- `cmake3 -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_C_COMPILER=/usr/bin/gcc -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:PATH=$PWD --sysroot=/usr/arm-linux-gnu/sys-root ~/src/anatofuz/old_llvm/CbC_llvm/`
--- a/user/anatofuz/note/2020/03/31.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/03/31.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,7 +4,7 @@ - dalmoreにこっそりripgrepとfdをいれた - LLVMでの`CbCParse.cpp`のソースコード読み - そんな出来てない -- Rakuの同人誌書く作業 +- Rakuの同人誌と商業誌書く作業 - PDFから時間割の作成プログラムの整備 - OS研究会どうしよう... @@ -22,6 +22,37 @@ ## 現状問題になってる箇所 +- TailCallElimPassが最適化のレベルによって読まれていなかったので強制的に呼ぶようにしてみた + +```diff +--- a/llvm/lib/Passes/PassBuilder.cpp Tue Mar 24 17:35:46 2020 +0900 ++++ b/llvm/lib/Passes/PassBuilder.cpp Tue Mar 31 17:50:47 2020 +0900 +@@ -1197,6 +1197,11 @@ + // Run a second time to clean up any type tests left behind by WPD for use + // in ICP. + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); ++#ifndef noCbC ++ MPM.addPass(SROA()); ++ ++ MPM.addPass(TailCallElimPass()); ++#endif + return MPM; + } + +@@ -1267,6 +1272,11 @@ + // in ICP (which is performed earlier than this in the regular LTO + // pipeline). + MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); ++#ifndef noCbC ++ MPM.addPass(SROA()); ++ ++ MPM.addPass(TailCallElimPass()); ++#endif + return MPM; + } +``` + +- `Pass.run(IR, AM, ExtraArgs...);`がなにか問題らしい ```text [185/1225] Building CXX object lib/Passes/CMakeFiles/LLVMPasses.dir/PassBuilder.cpp.o @@ -58,6 +89,14 @@ 115 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); ``` +## とりあえず +- 古いLLVMをdalmoreでビルドしたので同時に動かしながら見ている + +# 時間割のプログラム +- 大学の時間割のHTMLを取得 & 値を取り出して、学科サイトのHTMLを出力するやつ +- 今年は時間割配当表のPDFから自動で分析するとこまで実装したい +- PDFからgolangで情報を抜き出すのに成功したので今日仕上げられそう + # dalmore ripgrep(rg)とfdをいれました
--- a/user/anatofuz/note/2020/04/07.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/04/07.md Wed Dec 16 15:11:16 2020 +0900 @@ -2,4 +2,359 @@ - 授業時間割の作成コマンドの作成 - growiのバックアップ/投稿コマンドの作成 - LDAPの障害対応 -- LLVMのコンパイルエラー取り \ No newline at end of file +- インストール大会 +- xinu qemu-armをビルドした +- LLVMのコンパイルエラー取り +- 講義番号と教室と必修/選択は奇跡的に無傷だったのでセーフ + +### 実装状況 +- PDF, HTMLのそれぞれのパースはだいたい想定している書式で来ていれば問題なくパース可能になった +- 最悪JSONに情報を記述すれば静的に出力可能 +- とりあえず前期のものは生成できたので終了 +- 後期に向けてぼちぼち... + +# LDAPの障害 + +- 4/1のタイミングで卒業生のパスワードをセンターがランダムパスワードに変更していた + - `userPassword`がどうもパスワードらしい + - `modifyTimestamp`が`20200401181009Z`のものがセンターが変えたもの + +``` +mail: e165713@ie.u-ryukyu.ac.jp +radiusTunnelPrivateGroupId: 56 +ldapFirstName: Takahiro +gidNumber: 1001 +sambaNTPassword: d5db51decee22417b9b952b23b1ca902 +shadowWarning: -1 +shadowInactive: -1 +sambaSID: S-1-5-21-2540173566-2588308781-2214262875-30538 +gecos: Itsuki Takahiro +sn:: 5LiA5pyo +ldapLastName: Itsuki +homeDirectory: /home/student/e16/e165713 +ou: e16 +structuralObjectClass: inetOrgPerson +entryUUID: 35782c0c-8ce4-1035-97bc-ffc8ce6642e3 +creatorsName: cn=Manager,ou=ie,o=u-ryukyu,c=jp +createTimestamp: 20160402060221Z +loginShell: /bin/bash +userPassword:: e1NTSEF9IVJFN2pCbnl2MEdnQnh5NHhyOVhGL1hKeU0zdjkwSVVXN2s5aXZBPT0 + = +entryCSN: 20200401181009.004532Z#000000#000#000000 +modifiersName: cn=Manager,ou=ie,o=u-ryukyu,c=jp +modifyTimestamp: 20200401181009Z +``` +- それが学科のLDAPツリーに同期されて、卒業生がmattermostにログインできない障害が発生 + +## 修正手順 +- とりあえずPerlスクリプト書いて変更があった人々をリスト化 +- LDAPツリーを卒業生のものに移動 +- パスワードを3月25日くらいのものにldifファイル(ldapの設定変更スクリプト)を生成してldapmodifyで復旧する + +## userPassword:: +- `userPassword:` で変更できるかなと思い、こういう感じのスクリプトを生成していた + +``` +dn: uid=k188584,ou=graduate,ou=ie,o=u-ryukyu,c=jp +changetype: modify +replace: userPassword +userPassword: e1NTSEF9d1NlMWJFL2k3TG91b2U4R3RuVDM0dGdiREpSLzJPWGs= +``` + +- これだと、このパスワードがハッシュ化されて登録されてしまう +- ネットの記事をいろいろ見た感じ、 `userPassword::` と`:` を2つつけるとハッシュ化されず上書きができるらしい + +## 現状 +- ある程度の復旧はできた +- まだログインできない人が結構いるらしく、これに関しては原因究明中 + +# growiのバックアップスクリプト + +- goで実装しようと考えている +- mercurialリポジトリで管理するのを前提で処理を組む +- APIがいくつか存在していて、記事の最終更新日が取得可能 + - hgリポジトリの最終commitより新しい更新日時のエントリをpullする仕様 +- 投稿のAPIもあったので、なんとなく2日くらい頑張ればできそう + +# インストール大会 +- mac osがcatalinaとmojaveが混同している問題 +- なんかwindows持ってくる人が4人くらいいた + - windowsの場合は設定を工夫(再起動したり証明書を確認しないようにする)しないと、ie-ryukyu-fastにつながらない + - unixな環境どうするか問題があるが、多分WSL(Windows Subsystem for Linux)が後々入りそう + - pythonはminicondaを直接いれてvscodeで編集してもらう方式 +- 今年から全員mattermostに + +# xinu arm + +- xinu組み込み向けに作られた教育用OS +- Ethernetとusbの実装が存在しているのでなんとなく読んでみたかった +- 実装はunix系と異なる箇所が多い + +## ビルド +- mac osだと何故かうまく行かなかった +- 安定のdalmoreで実行してみた + +```log +git clone https://github.com/xinu-os/xinu +cd xinu +make -C compile PLATFORM=arm-qemu +qemu-system-arm -M versatilepb -cpu arm1176 -m 128M -nographic -kernel xinu.boot +cd compile +qemu-system-arm -M versatilepb -cpu arm1176 -m 128M -nographic -kernel xinu.boot +``` + +- qemuで起動可能 + +``` ++dalmore+one qemu-system-arm -M versatilepb -cpu arm1176 -m 128M -nographic -kernel xinu.boot + +(process:88031): GLib-WARNING **: 16:59:25.770: gmem.c:489: custom memory allocation vtable not supported +pulseaudio: pa_context_connect() failed +pulseaudio: Reason: Connection refused +pulseaudio: Failed to initialize PA contextaudio: Could not init `pa' audio driver +ALSA lib confmisc.c:767:(parse_card) cannot find card '0' +ALSA lib conf.c:4555:(_snd_config_evaluate) function snd_func_card_driver returned error: No such file or directory +ALSA lib confmisc.c:392:(snd_func_concat) error evaluating strings +ALSA lib conf.c:4555:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory +ALSA lib confmisc.c:1246:(snd_func_refer) error evaluating name +ALSA lib conf.c:4555:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory +ALSA lib conf.c:5034:(snd_config_expand) Evaluate error: No such file or directory +ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM default +sdl: SDL_OpenAudio failed +sdl: Reason: No available audio device +sdl: SDL_OpenAudio failed +sdl: Reason: No available audio device +audio: Failed to create voice `lm4549.out' +(Embedded Xinu) (arm-qemu) #0 (one@dalmore) Tue Apr 7 16:58:58 JST 2020 + + 134217728 bytes physical memory. + 65536 bytes reserved system area. + 66235 bytes Xinu code. + 8192 bytes stack space. + 134057856 bytes heap space. + + +-------------------------------------- + ____ ___.__ + \ \/ /|__| ____ __ __ + \ / | |/ \| | \ + / \ | | | \ | / + /___/\ \|__|___| /____/ + \_/ \/ v2.0 +-------------------------------------- + +Welcome to the wonderful world of Xinu! +xsh$ +``` + +## デバッグ + +- `qemu-system-arm -gdb tcp::12800 -S -M versatilepb -cpu arm1176 -m 128M -nographic -kernel xinu.boot` + - gdbのポートを空けつつ起動する +- `arm-none-eabi-gdb ./xinu.elf` + - gdb起動した後に target remoreで接続するとデバッグ可能 + + +# LLVM + +- エラーが起きているのは(たぶん)`llvm/lib/Passes/PassBuilder.cpp` なPassBuilder + - こちらの方は以前のLLVMのバージョンでは`#ifndef CbC`が無い + - もう1つのPassBuilderな` llvm/lib/Transforms/IPO/PassManagerBuilder.cpp `は問題なさそう + +- 挿入した部分は次のコード + +```cpp + if (Level == OptimizationLevel::O3) + FPM.addPass(AggressiveInstCombinePass()); + FPM.addPass(InstCombinePass()); + + if (!Level.isOptimizingForSize()) + FPM.addPass(LibCallsShrinkWrapPass()); + + invokePeepholeEPCallbacks(FPM, Level); + + // For PGO use pipeline, try to optimize memory intrinsics such as memcpy + // using the size value profile. Don't perform this when optimizing for size. + if (PGOOpt && PGOOpt->Action == PGOOptions::IRUse && + (Level.getSpeedupLevel() > 1 && !Level.isOptimizingForSize())) + FPM.addPass(PGOMemOPSizeOpt()); + + // TODO: Investigate the cost/benefit of tail call elimination on debugging. +#ifndef noCbC + FPM.addPass(SROA()); + FPM.addPass(TailCallElimPass()); +#else + if (Level.getSpeedupLevel() > 1) + FPM.addPass(TailCallElimPass()); +#endif + FPM.addPass(SimplifyCFGPass()); +``` + +- 直前で実行している +`FPM.addPass(PGOMemOPSizeOpt());`は正しいので、`PGOMemOPSizeOpt`の型を確認する + +``` +llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h +86:class PGOMemOPSizeOpt : public PassInfoMixin<PGOMemOPSizeOpt> { +88: PGOMemOPSizeOpt() = default; + +llvm/utils/gn/secondary/llvm/lib/Transforms/Instrumentation/BUILD.gn +25: "PGOMemOPSizeOpt.cpp", +``` + +- 見た感じ`PassInfoMixin`なclassっぽい + +``` +/// The indirect function call promotion pass. +class PGOIndirectCallPromotion : public PassInfoMixin<PGOIndirectCallPromotion> { +public: + PGOIndirectCallPromotion(bool IsInLTO = false, bool SamplePGO = false) + : InLTO(IsInLTO), SamplePGO(SamplePGO) {} + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + bool InLTO; + bool SamplePGO; +}; +``` + +- ` llvm/include/llvm/Transforms/Scalar/TailRecursionElimination.h`な方 + +``` +struct TailCallElimPass : PassInfoMixin<TailCallElimPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; +} +``` +- runメソッドの引数の型が異なっている + + +``` +pt -l 'PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);' | pbcopy +./llvm/include/llvm/Analysis/PostDominators.h +./llvm/include/llvm/Analysis/DemandedBits.h +./llvm/include/llvm/Analysis/PhiValues.h +./llvm/include/llvm/Analysis/RegionInfo.h +./llvm/include/llvm/Analysis/StackSafetyAnalysis.h +./llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h +./llvm/include/llvm/Analysis/CFGPrinter.h +./llvm/include/llvm/Analysis/MemorySSA.h +./llvm/include/llvm/Analysis/AssumptionCache.h +./llvm/include/llvm/Analysis/ScalarEvolution.h +./llvm/include/llvm/Analysis/DominanceFrontier.h +./llvm/include/llvm/Analysis/BranchProbabilityInfo.h +./llvm/include/llvm/Analysis/BlockFrequencyInfo.h +./llvm/include/llvm/Analysis/LoopInfo.h +./llvm/include/llvm/IR/SafepointIRVerifier.h +./llvm/include/llvm/IR/Verifier.h +./llvm/include/llvm/IR/Dominators.h +./llvm/include/llvm/CodeGen/ExpandReductions.h +./llvm/include/llvm/CodeGen/UnreachableBlockElim.h +./llvm/include/llvm/Transforms/InstCombine/InstCombine.h +./llvm/include/llvm/Transforms/Utils/LoopSimplify.h +./llvm/include/llvm/Transforms/Utils/EntryExitInstrumenter.h +./llvm/include/llvm/Transforms/Utils/BreakCriticalEdges.h +./llvm/include/llvm/Transforms/Utils/AddDiscriminators.h +./llvm/include/llvm/Transforms/Utils/Mem2Reg.h +./llvm/include/llvm/Transforms/Utils/PredicateInfo.h +./llvm/include/llvm/Transforms/Utils/KnowledgeRetention.h +./llvm/include/llvm/Transforms/Utils/LowerInvoke.h +./llvm/include/llvm/Transforms/Utils/InjectTLIMappings.h +./llvm/include/llvm/Transforms/Utils/LCSSA.h +./llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h +./llvm/include/llvm/Transforms/Instrumentation/PoisonChecking.h +./llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h +./llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h +./llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h +./llvm/include/llvm/Transforms/Scalar/LowerWidenableCondition.h +./llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h +./llvm/include/llvm/Transforms/Scalar/LowerMatrixIntrinsics.h +./llvm/include/llvm/Transforms/Scalar/SpeculativeExecution.h +./llvm/include/llvm/Transforms/Scalar/GVN.h +./llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h +./llvm/include/llvm/Transforms/Scalar/MergeICmps.h +./llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h +./llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h +./llvm/include/llvm/Transforms/Scalar/PartiallyInlineLibCalls.h +./llvm/include/llvm/Transforms/Scalar/DCE.h +./llvm/include/llvm/Transforms/Scalar/SROA.h +./llvm/include/llvm/Transforms/Scalar/BDCE.h +./llvm/include/llvm/Transforms/Scalar/JumpThreading.h +./llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h +./llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h +./llvm/include/llvm/Transforms/Scalar/LoopFuse.h +./llvm/include/llvm/Transforms/Scalar/LowerGuardIntrinsic.h +./llvm/include/llvm/Transforms/Scalar/Scalarizer.h +./llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h +./llvm/include/llvm/Transforms/Scalar/Float2Int.h +./llvm/include/llvm/Transforms/Scalar/TailRecursionElimination.h +./llvm/include/llvm/Transforms/Scalar/SCCP.h +./llvm/include/llvm/Transforms/Scalar/CorrelatedValuePropagation.h +./llvm/include/llvm/Transforms/Scalar/Sink.h +./llvm/include/llvm/Transforms/Scalar/EarlyCSE.h +./llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h +./llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h +./llvm/include/llvm/Transforms/Scalar/NaryReassociate.h +./llvm/include/llvm/Transforms/Scalar/WarnMissedTransforms.h +./llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h +./llvm/include/llvm/Transforms/Scalar/GuardWidening.h +./llvm/include/llvm/Transforms/Scalar/MemCpyOptimizer.h +./llvm/include/llvm/Transforms/Scalar/LoopUnrollPass.h +./llvm/include/llvm/Transforms/Scalar/MakeGuardsExplicit.h +./llvm/include/llvm/Transforms/Scalar/LoopLoadElimination.h +./llvm/include/llvm/Transforms/Scalar/LoopDistribute.h +./llvm/include/llvm/Transforms/Vectorize/LoadStoreVectorizer.h +./llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h +./llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h +``` + +``` +pt -l 'PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);' +./llvm/include/llvm/Analysis/StackSafetyAnalysis.h +./llvm/include/llvm/Analysis/LazyCallGraph.h +./llvm/include/llvm/Analysis/CGSCCPassManager.h +./llvm/include/llvm/Analysis/CallGraph.h +./llvm/include/llvm/Analysis/ProfileSummaryInfo.h +./llvm/include/llvm/IR/Verifier.h +./llvm/include/llvm/CodeGen/PreISelIntrinsicLowering.h +./llvm/include/llvm/Transforms/IPO/ThinLTOBitcodeWriter.h +./llvm/include/llvm/Transforms/IPO/GlobalSplit.h +./llvm/include/llvm/Transforms/IPO/LowerTypeTests.h +./llvm/include/llvm/Transforms/IPO/FunctionImport.h +./llvm/include/llvm/Transforms/IPO/SampleProfile.h +./llvm/include/llvm/Transforms/IPO/FunctionAttrs.h +./llvm/include/llvm/Transforms/IPO/MergeFunctions.h +./llvm/include/llvm/Transforms/IPO/Internalize.h +./llvm/include/llvm/Transforms/IPO/InferFunctionAttrs.h +./llvm/include/llvm/Transforms/IPO/HotColdSplitting.h +./llvm/include/llvm/Transforms/IPO/GlobalOpt.h +./llvm/include/llvm/Transforms/IPO/SCCP.h +./llvm/include/llvm/Transforms/IPO/CrossDSOCFI.h +./llvm/include/llvm/Transforms/IPO/Attributor.h +./llvm/include/llvm/Transforms/Utils/SymbolRewriter.h +./llvm/include/llvm/Transforms/Utils/CanonicalizeAliases.h +./llvm/include/llvm/Transforms/Utils/NameAnonGlobals.h +./llvm/include/llvm/Transforms/Instrumentation/PoisonChecking.h +./llvm/include/llvm/Transforms/Instrumentation/InstrOrderFile.h +./llvm/include/llvm/Transforms/Instrumentation/GCOVProfiler.h +./llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h +./llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h +./llvm/include/llvm/Transforms/Instrumentation/SanitizerCoverage.h +./llvm/include/llvm/Transforms/Instrumentation/MemorySanitizer.h +./llvm/include/llvm/Transforms/Instrumentation/ThreadSanitizer.h +./llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h +./llvm/include/llvm/Transforms/Instrumentation/CGProfile.h +./llvm/include/llvm/Transforms/Scalar/RewriteStatepointsForGC.h +``` + +違いを取った + +``` +z$ perl hoge.pl ff.txt mm.txt | grep -v 1 +./llvm/include/llvm/IR/Verifier.h : 2 +./llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h : 2 +./llvm/include/llvm/Transforms/Instrumentation/AddressSanitizer.h : 2 +./llvm/include/llvm/Analysis/StackSafetyAnalysis.h : 2 +./llvm/include/llvm/Transforms/Instrumentation/PoisonChecking.h : 2 +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/04/14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/04/14.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,9 +1,171 @@ # 2020/04/14 +# CbCXV6上の状態遷移ベースでのプロトコルの実装 + + + +# 研究目的 +- 検証を利用して信頼性を確保するGearsOSを開発中 +- xv6をベースにGearsOSの実装が進んでいる +- 現在のOSに欠かせないネットワーク通信/USBなどのプロトコルを高信頼性で実装したい +- プロコトルは巨大な状態遷移マシンと捉えると、CbC/Gearsでの記述に適している +- 実際にxv6上にCbCベースでプロトコルを実装し、検証可能かどうかを試作する + +# やったこと +- LLVMのバグ撮り +- growi backup関連の調査など +- シス管issue関連 +- OS研究会のネタ決め +- 雑誌執筆 + # OS研究会 +- タイトルと概要考えました +- 証明に適した実装と実装に適した実装を切り替えるところまで書くべき? +- とはいえ証明に適した実装が何なのかが怪しい気がする + - CodeGearの入出力をすべて記憶しておく? ## title -「継続を用いたxv6 kernelのモジュール化」 +~~「継続を中心とした言語によるxv6のモジュール化」~~ + +「xv6の構成要素の継続の分析」 + + +## 概要 + +OS自体そのものは高い信頼性が求められるが、 OSを構成するすべての処理をテストするのは困難である。 +テストを利用して信頼性を高めるのではなく、 OSの状態を状態遷移を基本としたモデルに変換し形式手法を用いて信頼性を高めたい。 + +状態遷移単位での記述に適した言語であるCbCを用いて、小さなunixであるxv6 kernelの書き換えを行う。 +この際に、すべてのOSの処理を状態遷移単位での記述を行うと、プログラミングする上での実装が煩雑になってしまう。 +そこで状態遷移の集合をモジュール化することで拡張性を保証、かつ実装が簡易化されるInterfaceを導入した。 + +本稿ではxv6kernelに導入したCbCInterfaceの解説及び、 xv6 kernelへの実装について述べる。 + + +# Pintos + +- xv6的な小さなx86向けのOSらしい + - https://github.com/reedcozart/pintos +- usbのプロトコルを載せているものもあった +https://www.cse.iitd.ernet.in/~sbansal/os/previous_years/2014/pintos/doc/pintos_html/usb_8c-source.html + +# LLVM + +## TailCallElim +- 先週はTailCallElimをPassに加える際の型が異なっておりコンパイルできなかった +``` +/// The indirect function call promotion pass. +class PGOIndirectCallPromotion : public PassInfoMixin<PGOIndirectCallPromotion> { +public: + PGOIndirectCallPromotion(bool IsInLTO = false, bool SamplePGO = false) + : InLTO(IsInLTO), SamplePGO(SamplePGO) {} + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + bool InLTO; + bool SamplePGO; +}; +``` + +- ` llvm/include/llvm/Transforms/Scalar/TailRecursionElimination.h`な方 + +``` +struct TailCallElimPass : PassInfoMixin<TailCallElimPass> { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; +} +``` +- passの追加は2種類の追加の方法があるらしい + - 今の所使われているものがこの2種類 + - コンパイル時に`run`の型がどうのこうの言われた場合、この追加の方法が逆になっているらしい + +``` + FPM.addPass(TailCallElimPass()); + PM.add(createTailCallEliminationPass(true)); +``` + +## 現状 -## 概要 \ No newline at end of file +- OptLevelが関係している部分を修正して回っているが、効果がない + - 修正すべき箇所を見逃している説がありそう +```diff +--- a/clang/lib/CodeGen/BackendUtil.cpp Tue Apr 14 15:43:20 2020 +0900 ++++ b/clang/lib/CodeGen/BackendUtil.cpp Tue Apr 14 17:43:32 2020 +0900 +@@ -315,6 +315,10 @@ + PM.add(createGVNPass()); + PM.add(createInstructionCombiningPass()); + PM.add(createDeadStoreEliminationPass()); ++#ifndef noCbC ++ } else { ++ PM.add(createTailCallEliminationPass(true)); ++#endif + } + } + +diff -r 980e56f2e095 llvm/lib/Passes/PassBuilder.cpp +--- a/llvm/lib/Passes/PassBuilder.cpp Tue Apr 14 15:43:20 2020 +0900 ++++ b/llvm/lib/Passes/PassBuilder.cpp Tue Apr 14 17:43:32 2020 +0900 +@@ -451,7 +451,6 @@ + + // TODO: Investigate the cost/benefit of tail call elimination on debugging. + #ifndef noCbC +- FPM.addPass(SROA()); + FPM.addPass(TailCallElimPass()); + #else + if (Level.getSpeedupLevel() > 1) +@@ -610,6 +609,9 @@ + FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies. + FPM.addPass(SimplifyCFGPass()); // Merge & remove basic blocks. + FPM.addPass(InstCombinePass()); // Combine silly sequences. ++#ifndef noCbC ++ FPM.addPass(TailCallElimPass()); ++#endif + invokePeepholeEPCallbacks(FPM, Level); + + CGPipeline.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); +@@ -1161,8 +1163,15 @@ + MPM.addPass(LowerTypeTestsPass(nullptr, ImportSummary)); + } + +- if (Level == OptimizationLevel::O0) ++ if (Level == OptimizationLevel::O0) { ++#ifndef noCbC ++ FunctionPassManager FPM(DebugLogging); ++ FPM.addPass(TailCallElimPass()); ++ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); ++ MPM.addPass(ForceFunctionAttrsPass()); ++#endif + return MPM; ++ } +``` +- `TailCallElimPass()`の追加でない可能性が存在している気がする +- 具体的なPassの種類の特定はまだできていない + - 以前発見したPassの一覧を出すコマンドはあまり効果が無かったような... + +# growi backup +- 一応web越しでbackupはできるが、コマンドベースでgrowiの階層に則ってmarkdownを撮りたい +- APIを実際に叩いて検証してみたところ、publicなエントリはダウンロードできる + - 公開範囲が設定されているエントリはダウンロードできないらしい + - 一応issueを書いて相談している + - backupツール書くならpublicなものという制約は付きそう + - 使ってるの僕とryokkaさんの修論とかくらいだからまぁ... +- 元気があるときにぼちぼち + +# minio +- mattermostの外部ファイルを逃がす目的でいれたs3互換なオブジェクトストレージ +- golangで書かれている +- 元気に今の頃動いている +- ユーザーからは次の順で外部ファイルにアクセスがいく +- mattermostのAPIに対してアクセス +- mattermost側がDBからminioのオブジェクトを特定 +- mattermostがminioのオブジェクトgetしてユーザーにかえしている + - その為一般ユーザーからはminioの存在が認知できない + +# 時間割スクリプト +- コロナ騒ぎでシラバスに更新があるケースがあるらしく、 時間割のhtmlを取得するとこをサブコマンド化した +- goroutineで取得する +- 爆速すぎるのでsleepをしたほうが良いのではという気がしている + +
--- a/user/anatofuz/note/2020/04/21.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/04/21.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,7 +1,110 @@ -# +# 2020/04/21 + +# xv6の構成要素の継続の分析 + +# 研究目的 +- OS自体そのものは高い信頼性が求められるが、 OSを構成するすべての処理をテストするのは困難である。 +- テストを利用する以外の手法で信頼性を高めたい。 +- OSの状態を状態遷移を基本としたモデルに変換し形式手法を用いて信頼性を高める手法を検討する +- 小さなunixであるxv6 kernelを、状態遷移を基本とした単位でのプログラミングに適したCbCで再実装を行っている +- このためには現状のxv6kernelの処理の状態遷移の分析が必要である。 + - その結果を、 継続ベースでのプログラミングに変換していく必要がある。 +- xv6kernelの構成要素の一部に着目し、状態遷移系の分析と状態遷移系を元に継続ベースでxv6の再実装を行う。 # やったこと +- zoom黙々配信的なもの + - LLVMは敗れ去りました... - OS研究会の申し込み - システム管周りの細々したタスク - 自宅のインターネット強化 - 寄稿するPerlの記事を書く作業 + +# LLVM +- ヘッダーファイルに変更を加えた場合は`ninja-build clean`ではだめで、潔く`rm -rf`しないとだめらしい +- grepしてLevelに関係がありそうなものに`TailCallElimination`を追加する方針でやったがあまり意味がない +- やはりpass一覧を出してやるしかなさそう + +```diff +--- a/clang/lib/CodeGen/BackendUtil.cpp Tue Apr 14 15:43:20 2020 +0900 ++++ b/clang/lib/CodeGen/BackendUtil.cpp Tue Apr 21 16:59:10 2020 +0900 +@@ -315,6 +315,10 @@ + PM.add(createGVNPass()); + PM.add(createInstructionCombiningPass()); + PM.add(createDeadStoreEliminationPass()); ++#ifndef noCbC ++ } else { ++ PM.add(createTailCallEliminationPass(true)); ++#endif + } + } +``` +- CGCallのところは後ほど実装するという感じでコメントにしていたので、しっかり実装した +- とは言え現在の最適化しないとエラーが出る処理とはあんまり関係性が無かった + +```diff +diff -r 980e56f2e095 clang/lib/CodeGen/CGCall.cpp +--- a/clang/lib/CodeGen/CGCall.cpp Tue Apr 14 15:43:20 2020 +0900 ++++ b/clang/lib/CodeGen/CGCall.cpp Tue Apr 21 16:59:10 2020 +0900 +@@ -4440,6 +4440,33 @@ + terminates local variable pointer life time here. + cf. CodeGenFunction::PopCleanupBlock at clang/lib/CodeGen/CGCleanup.cpp + */ ++ ++ if (this->FnRetTy.getTypePtr()->is__CodeType() && CallInfo.getReturnType().getTypePtr()->is__CodeType() && ! EHStack.empty() ) { ++ EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); ++ auto *CleanupSource = reinterpret_cast<char *>(Scope.getCleanupBuffer()); ++ alignas(EHScopeStack::ScopeStackAlignment) char ++ CleanupBufferStack[8 * sizeof(void *)]; ++ std::unique_ptr<char[]> CleanupBufferHeap; ++ size_t CleanupSize = Scope.getCleanupSize(); ++ EHScopeStack::Cleanup *Fn; ++ ++ if (CleanupSize <= sizeof(CleanupBufferStack)) { ++ memcpy(CleanupBufferStack, CleanupSource, CleanupSize); ++ Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferStack); ++ } else { ++ CleanupBufferHeap.reset(new char[CleanupSize]); ++ memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize); ++ Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferHeap.get()); ++ } ++ ++ EHScopeStack::Cleanup::Flags cleanupFlags; ++ if (Scope.isNormalCleanup()) ++ cleanupFlags.setIsNormalCleanupKind(); ++ if (Scope.isEHCleanup()) ++ cleanupFlags.setIsEHCleanupKind(); ++ Fn->Emit(*this, cleanupFlags); ++ } ++ + #endif +``` + +# OS研究会 +- 「xv6の構成要素の継続の分析」で出しました +- 内容としては優さんの修論と坂本くんの卒論をmixした内容 + - 修論/卒論では具体的な分析までは行ってなかったので、行う必要がある +- 卒論/修論ではInterface周りの話が中心でしたが、 今回はあまり触れない + - どちらかというとInterfaceに分割した処理の内容の方をフォーカスしていこうと思います + +## 修論/卒論時点での書き換え方針 +- もともとあった関数内で、basic block単位でCodeGearに変換していく +- かなり愚直に変換した為、 CodeGearの引数にループindexが含まれてたりしていた + - 特別Gears用のAPIがある訳ではない + - 現状はInterface化したが、実装は1つしか存在していない +- この時点では具体的に各CodeGearの意味までは考えられてなかった + - 今回の論文はこのあたりが主軸になりそう + +## やること +- メモリ関連(vm.c)とファイルシステム関連(fs.c)の読み直し +- 修論/卒論でのCbCの実装を確認しつつ、状態遷移図がしっかり説明できる単位で状態を切り分けていく +- CbCとxv6なのでB4と一緒にやるのもいいかもねみたいな気がする ( or 院の講義でやってしまう) +- ...というのを論文を書きながら進めていく + + +# シス管周りのほそぼそ系 +- 消しちゃったVM復旧させたりとか... +- B2とzoomでつなぎながら作業 + - アカウントの作成とか +- mattermostサーバーのメンテンス + - スペック強化、 ntp(`chrony`)クライアントの追加とうとう + - 実際に作業してもらったのは宮平くん
--- a/user/anatofuz/note/2020/04/28.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/04/28.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,7 +1,96 @@ +# 2020/04/28 + +# xv6の構成要素の継続の分析 + +# 研究目的 +- OS自体そのものは高い信頼性が求められるが、 OSを構成するすべての処理をテストするのは困難である。 +- テストを利用する以外の手法で信頼性を高めたい。 +- OSの状態を状態遷移を基本としたモデルに変換し形式手法を用いて信頼性を高める手法を検討する +- 小さなunixであるxv6 kernelを、状態遷移を基本とした単位でのプログラミングに適したCbCで再実装を行っている +- このためには現状のxv6kernelの処理の状態遷移の分析が必要である。 + - その結果を、 継続ベースでのプログラミングに変換していく必要がある。 +- xv6kernelの構成要素の一部に着目し、状態遷移系の分析と状態遷移系を元に継続ベースでxv6の再実装を行う。 + +# やったこと +- 使っているキーボードが壊れて落ち込む +- sigosのmindmap作成と論文の書き始め +- リモートTA +- 雑誌に投稿するPerlの記事を書く作業 + - なんか出版社の人もコロナ騒ぎで大変らしい +- macOSでのCbCgccのビルド +- 自宅のネットワークが強化された + +# Gears関連 +- xv6とGearsで共通して使っているGearsToolsをいい感じに統一したい + - いろいろなPerlスクリプトをcmakeで動かしてたり、手で動かしたりしている + - ところどころPerlのライブラリとして実装しているので、無理なことはないが… + - 誰かと一緒にやる or 誰かにやってもらえると良さそう + +# sigos +- mindmapはとりあえず書きながら作業しています +- 序章とかは多分書けるので、論文も書きながらネタを考えています +- 文章校正にtexlint使いたいが、 LaTeXだとうまく動かないので一度markdownにするのがいいかもしれない + - あとでsigos用のテンプレートリポジトリ作っておきたい気もする + +## 必要となってきそうな要素 +- プロセスの状態を持つcontext + - 現在の実装ではプロセス構造体にcbc_contextを埋め込んでいる + - プロセス構造体 -> contextに完全に切り替えるのを考えると、「どこまでがプロセスが持つ情報/状態」かというのが重要そう +- kernelの状態を持つcotnext + - 今まで実装していた中で必要だったのは、割り込みが来ているかどうかのフラグ、ファイルシステム内のinodeのキャッシュなど + - inodeのキャッシュそのものをcontext化するのも良さそうだが、特別CodeGearがついてくる必要はなさそう + - その場合はオブジェクト指向OSっぽい実装になりそうだけど、そういうわけではなさそう + +- 論文出すまでにどこまで実装するかみたいなところ + - ファイルシステムの実装を変えていくのがいいかもしれない + # GCCのビルド - mac環境だといろいろと大変なところがあるが、最新のGCC9だとわりとスムーズにビルドができるらしい - CbCGCCも9にアップデート済みだった +## macOSでのビルド + +- [このサイト](https://solarianprogrammer.com/2019/10/12/compiling-gcc-macos/)の通りにやればだいたいできる +- catalina(high sierraくらい?)からgmpなどのライブラリを個別でビルドしなければGCCのビルドができなかった + - gcc9からGCCのリポジトリに自動でこのあたりのライブラリをインストールする`contrib/download_prerequisites`が追加されていて便利になっていた + +```sh +$contrib/download_prerequisites +(GCCのトップディレクトリで行わないといけない) +``` + +- `/usr/include/`が抜けた問題があるので、`sys_root`を自前で用意する必要がある + - 一部のincludeファイルにmacOSのパッチを与える必要があるらしい(必要ないかも) + +```sh +$cd sys_root +$ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/Library . +$ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System . +$mkdir usr && cd usr +$ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/bin . +$ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib . +$ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/libexec . +$ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share . +$cp -r /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include include +$vim include/Availability.h +``` + +- あとはConfigureを実行する + - `--with-sysroot`を指定しておかないと、`/usr/include`が無いエラーが発生する + - `--with-sysroot`は絶対パスで与えないといけない + +```sh +../CbC_gcc/configure --prefix=$PWD --disable-nls --disable-bootstrap --enable-checking=tree,rtl,assert,types CFLAGS="-g3 -O0" --enable-languages=c,lto --no-create --no-recursion --disable-multilib --with-sysroot=/Users/anatofuz/workspace/cr/CbC/latest_gcc/sys_root +``` + +- ここで何故かMafikefileでなく`config.status`なシェルスクリプトが生成される + - このシェルスクリプトを実行するとMakefileが生成される + - あとは `make -j`すれば良い(`-j`だと一部がうまく動かないので、`make`の方が良いかもしれない) + +## TODO +- ARM版GCCのビルド + - linux(dalmore), macOSともに成功していないので... + - xv6関連で使いたい # 家のインターネット - レキオス光レジデンスからレキオス光 スマートウェイに
--- a/user/anatofuz/note/2020/05/12.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/05/12.md Wed Dec 16 15:11:16 2020 +0900 @@ -18,4 +18,23 @@ - 論文提出 - 研究計画書を書いた - 基幹システムの復旧 -- pro3の相談対応 \ No newline at end of file +- pro3の相談対応 +- なんとなくgolangでインタプリタを書き始めた + +## 論文提出 +- おつかれさまでした....(ありがとうございました...) +- textlint使いたかったのでmarkdown2latexなやつを書いてつかっていた + - 素直にpandoc使えというのはあるのですが... +- スライド(こんな感じの資料)をそろそろ作り始める +- 去年書き変えた箇所はわりと`generate_stub.pl`の仕様で人力で書いた箇所が多い + - `goto meta`手書きとか、 `Gearef(cbc_context, hoge)->foo = `みたいなのを手書きとか + - このあたりをきれいなコード(論文で書いたコード)で表現し直したい + - `goto next_private(...)`で統一したい + - そろそろやります + +## 基幹システムの復旧 +- おつかれさまでした +- dalmore上のVMは今の所使えない + - pro3でちょっと被害があった? + +
--- a/user/anatofuz/note/2020/05/19.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/05/19.md Wed Dec 16 15:11:16 2020 +0900 @@ -21,4 +21,238 @@ - 最後の親知らずを抜歯する - Gearsで下記散らかしていたPerlスクリプトを整理した - golangでインタプリタを書き始めた - - Gears(CbC)でも実装し直していますが、う〜ん... \ No newline at end of file + - Gears(CbC)でも実装し直していますが、う〜ん... +- growi/hackmdのhttps対応 + - ついでに自分の個人サイトもリニューアル + +# Gearsの整理 +- 自分で書いてて当時なぜ実装したのか覚えてないPerスクリプトが多数放置されていた + - とりあえずrmした(hgで管理してるし...) + - Pod書いてたスクリプトはちゃんと理解できた + - SYNOPSISは大事ですね... +- わりとGears忘れているのでリハビリ中... + - そもそも今までどういう文法だったかをparallel_executionからおさらい + - とりあえずxv6の書き換えを進めていきます + +# golang製のインタプリタ +- 積んでいた[Writing An Interpreter In Go](https://interpreterbook.com/)をやり始めた +- [monkey](https://monkeylang.org/)インタプリタを実装する + - 頑張って写経してレキサーまでは実装した + - ただ実装するだけだと面白くないのでGearsに変換するのを考えている + +```go lexer.go +package lexer + +import "firefly/hg/Members/anatofuz/monkey/token" + +// Lexer model +type Lexer struct { + input string + position int // current position in input (points to current char) + readPosition int // current reading position in input(after current char) + ch byte +} + +// New create Lexer instance and start lex +func New(input string) *Lexer { + l := &Lexer{input: input} + l.readChar() + return l +} + +func (l *Lexer) readChar() { + if l.readPosition >= len(l.input) { + l.ch = 0 + } else { + l.ch = l.input[l.readPosition] + } + + l.position = l.readPosition + l.readPosition++ +} + +//NextToken is create token.Token after read from input +func (l *Lexer) NextToken() token.Token { + var tok token.Token + + l.skipWhitespace() + + switch l.ch { + case '=': + tok = newToken(token.ASSIGN, l.ch) + case '+': + tok = newToken(token.PLUS, l.ch) + case '-': + tok = newToken(token.MINUS, l.ch) + case '!': + tok = newToken(token.BANG, l.ch) + case '/': + tok = newToken(token.SLASH, l.ch) + case '*': + tok = newToken(token.ASTERISK, l.ch) + case '<': + tok = newToken(token.LT, l.ch) + case '>': + tok = newToken(token.GT, l.ch) + case ';': + tok = newToken(token.SEMICOLON, l.ch) + case ',': + tok = newToken(token.COMMA, l.ch) + case '(': + tok = newToken(token.LPAREN, l.ch) + case ')': + tok = newToken(token.RPAREN, l.ch) + case '{': + tok = newToken(token.LBRACE, l.ch) + case '}': + tok = newToken(token.RBRACE, l.ch) + case 0: + tok.Literal = "" + tok.Type = token.EOF + + default: + if isLetter(l.ch) { + tok.Literal = l.readIdentifier() + tok.Type = token.LookupIdent(tok.Literal) + return tok + } else if isDigit(l.ch) { + tok.Type = token.INT + tok.Literal = l.readNumber() + return tok + } else { + tok = newToken(token.ILLEGAL, l.ch) + } + + } + + l.readChar() + return tok +} + +func newToken(tokenType token.TokenType, ch byte) token.Token { + return token.Token{Type: tokenType, Literal: string(ch)} +} + +func (l *Lexer) readIdentifier() string { + position := l.position + for isLetter(l.ch) { + l.readChar() + } + return l.input[position:l.position] +} + +func isLetter(ch byte) bool { + return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' +} + +func (l *Lexer) skipWhitespace() { + for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' { + l.readChar() + } +} + +func (l *Lexer) readNumber() string { + positon := l.position + for isDigit(l.ch) { + l.readChar() + } + return l.input[positon:l.position] +} + +func isDigit(ch byte) bool { + return '0' <= ch && ch <= '9' +} +``` + +``` +package token + +const ( + ILLEGAL = "ILLEGAL" + EOF = "EOF" + + IDENT = "IDENT" + INT = "INT" + + // Operators + ASSIGN = "=" + PLUS = "+" + MINUS = "-" + BANG = "!" + ASTERISK = "*" + SLASH = "/" + + LT = "<" + GT = ">" + + COMMA = "," + SEMICOLON = ";" + + LPAREN = "(" + RPAREN = "(" + LBRACE = "{" + RBRACE = "}" + + // Keywords + FUNCTION = "FUNCTION" + LET = "LET" + TRUE = "TRUE" + FALSE = "FALSE" + IF = "IF" + ELSE = "ELSE" + RETURN = "RETURN" +) + +type TokenType string + +type Token struct { + Type TokenType + Literal string +} + +var keywords = map[string]TokenType{ + "fn": FUNCTION, + "let": LET, + "true": TRUE, + "false": FALSE, + "if": IF, + "else": ELSE, + "return": RETURN, +} + +//LookupIdent is jugde ident or defined keywords +func LookupIdent(ident string) TokenType { + if tok, ok := keywords[ident]; ok { + return tok + } + return IDENT +} +``` + +# Gears製のインタプリタ +- `parallel_execution`以下に例題として実装していく路線で... +- とりあえずlexerのInterfaceとTokenのInterfaceを考えていた + - 入出力はDataGearなので、 `__code next(int len, ...)` みたいなのはできない + - 引数で `__code hoge(Impl* foo, const char* ch)` みたいにプリミティブ型を指定するのもダメそう + + +```c +typedef struct lexer <Type, Impl> { + __code read_char(Impl* lexer, string ch, __code next(... )); + __code eat_whitespace(Impl* lexer, string ch, __code next(... )); + __code next_token(Impl* lexer, __code next(struct token* tok, ...)); + __code next(....); +} lexer; +``` + +- いろいろ考えると`next_token`だけで良さそう + - 呼び出すたびに`token`が生成される + - 呼び出すたびに`lexer`自体の状態が変化するのがちょっとアレな気はする + - `map`みたいなオペレーションが必要? +- Gearsのリハビリも兼ねてとりあえず実装してみます + + +# growi/hackmdのhttps対応 +- firefoxでhttpのページにアクセスすると危険みたいな主張が激しくなっていて、つらそうだったので対応した +- https://anatofuz.hatenablog.com/entry/2020/05/17/113049 +- 雑にLet'sEncrypt \ No newline at end of file
--- a/user/anatofuz/note/2020/05/26.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/05/26.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,10 +1,67 @@ # 2020/05/26 +# 研究目的 +- アプリケーションの信頼性を向上させるたい + - その為には土台となる OS 自体の信頼性を高く保証したい +- OSそのものも巨大なプログラムである + - テストコードを用いた方法で信頼性を確保する事が可能 +- しかし並列並行処理などに起因するバグや、そもそもOSを構成する処理が巨大 + - テストで完全にバグを発見するのは困難 + - テスト以外の方法でOSの信頼性を高めたい + +# 今週の進捗 +- brewでCbCGCCをcatalinaでビルドチャレンジ +- シス管関連/プロ3の質問対応 +- 雑誌の投稿が編集部から返ってきたので編集 +- 発表資料作成 +- ゼミの初期を決めるルーレット作成 +- mkくんのgolangのコードを見たりした + -## bottle化 +# 小ネタ +- PLDIがオンライン開催らしい + - 無料で登録できるらしいのでしておいた + - https://conf.researchr.org/home/pldi-2020 + +# brewでCbCGCCをcatalinaでビルドチャレンジ +- ヘッダファイル関連のエラーを取り除きたいこともあり、 GCCをupdateしました + - GCC_original, CbCGCCともにupdateしてます + - CbCGCCのmergeは特にconflictが発生しなかった +- catalinaで手でやったところ無事ビルドできました + +# bottle化 +- mojaveのやつがそのまま使えはするが、`/usr/include`が無いのでコンパイラを使用する際にオプションで指定する必要がある +- `--with-sysroot`でsdkを指定すれば解決するので、その方法でビルドする -```zsh +## 手作業でのビルド + +- gcc10.1.0から直接sdkを引数で指定すれば良いらしい + - 以前は一回パッチをヘッダに当てる必要があった + +``` + ../CbC_gcc/configure --prefix=$PWD --disable-nls --disable-bootstrap --enable-checking=tree,rtl,assert,types CFLAGS="-g3 -O0" --enable-languages=c --no-create --no-recursion --disable-multilib --with-sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk +``` + +- `--with-sysroot`で指定するsdkがぐぐると大体2種類存在する + - `/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk` + - `/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/` + - こっちの方は` xcrun --sdk macosx --show-sdk-path`した際に返ってくるもの + +Applications以下のものはよく見るとシンボリックリンクになってる +- `/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/` + + +## brewでのビルド +- brewの場合`/Library`のものを指定するとエラーが出る + - xcodeのバージョンの関係? + - 今朝Command Line Toolsのアップデートが入ってたので修正されてたかも +- brewでビルドしようとするとヘッダファイル関連でエラーが出てあまりうまく行かない + - `libstd++`のビルドが原因 + +## ボトルを作成する + +``` +ikoma+anatofuz$ brew install --build-bottle AnaTofuz/homebrew-ie/cbcgcc Updating Homebrew... ==> Installing cbcgcc from anatofuz/ie @@ -33,6 +90,13 @@ ==> Summary 🍺 /usr/local/Cellar/cbcgcc/10.0.1: 674 files, 243.3MB, built in 30 minutes 37 seconds +``` + +- bottle化 + - build番号が2になっている + - 見なかったことに..... + +``` +ikoma+anatofuz$ brew bottle AnaTofuz/homebrew-ie/cbcgcc ==> Determining anatofuz/ie/cbcgcc bottle rebuild... ==> Bottling cbcgcc--10.0.1.catalina.bottle.2.tar.gz... @@ -43,4 +107,11 @@ rebuild 2 sha256 "9465b16d6e5443290600bf9bb11c8d2c46f1d3992bcd5d56f85bd2c698e2e6eb" => :catalina end -``` \ No newline at end of file +``` + + +## 発表資料 +- marpつかってやってます + - https://github.com/marp-team/marp-cli +- 今までのスライドジェネレーターよりまともに動くので研究室のテーマを作りたい + - まともに動く(空白のでかいページができない) \ No newline at end of file
--- a/user/anatofuz/note/2020/06/01.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/01.md Wed Dec 16 15:11:16 2020 +0900 @@ -3,4 +3,6 @@ - CbCのファイルパスで自動でcを開くやつ - ビルドが別ディレクトリの場合でも対応 - cleanとcmakeとmakeをワンコマンドで実行する - - ビルドターゲットは引数で指定可能にしたい \ No newline at end of file + - ビルドターゲットは引数で指定可能にしたい +- 雛形生成 + - 作り出すまでが長いので \ No newline at end of file
--- a/user/anatofuz/note/2020/06/02.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/02.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,4 +5,404 @@ - marpのslideテーマ作りました - LLVMちょっとやったりしていた - Gearsのデバッグ - - 雛形生成とビルド関連のコマンドを作りたい気がする \ No newline at end of file + - ビルド関連のコマンドを作りました + - 雛形生成とかもしたい + - mercurialのラッパーコマンドも作成している +- Perl5.31.10で入った連鎖比較(chained comparisons)の実装を見ていた +- Perlの雑誌の印刷所入稿が今日終わりました + +# おしらせ +- 今週末kernel/vm探検隊 + - https://connpass.com/event/175388/ +- PLDI2020が5日まで登録をすると無料らしい + - https://pldi20.sigplan.org/ + +# OS研究会 +- zoomなのでいつもよりは緊張しなかった + - しなかったわけではないですが... +- こころなし普段より疲れた気がする +- return less kernelというものがあるらしい + - 攻撃から守るために特定の命令を検知して書き換える手法 + - 論文読みます... + +# marp +- node.js製のスライドジェネレーター + - 以前electron製のものがり、それのリストア + - slideshowよりは生成するスライドが良心的 +- CLIベースのものとvscodeベースのものがある + - CLIベースのものはバイナリが配布されている +- 研究室のロゴを右下にあてただけのテーマとmakefile等を作った + - cssあまりかけないのでかなり雑な作りですが... + +# Gears +- 以前のGearsでは`example`以下のディレクトリで生成したインターフェイスは無視されていた + +```perl +} elsif(/^#interface "(.*)"/) { + # use interface + my $interfaceHeader = $1; + next if ($interfaceHeader =~ /context.h/); + if (-f $interfaceHeader) { + &getDataGear("$interfaceHeader"); + &getCodeGear("$interfaceHeader"); + } +``` +- perlの `if (-f)`はファイルがあればtrueをかえす +- generate_stubを実行しているディレクトリから見えないと無視される + +- 今はビルドしている.cbcと同じディレクトリにあるものは含めるようにした + +```perl +} elsif(/^#interface "(.*)"/) { + # use interface + my $interfaceHeader = $1; + next if ($interfaceHeader =~ /context.h/); + if (-f $interfaceHeader) { + &getDataGear("$interfaceHeader"); + &getCodeGear("$interfaceHeader"); + } else { + if ($filename =~ /([\w\/]+)\/(.+)$/) { + $interfaceHeader = "$1/$interfaceHeader"; + if (-f $interfaceHeader) { + &getDataGear("$interfaceHeader"); + &getCodeGear("$interfaceHeader"); + } + } + } +``` + +- とりあえずはmonkeyをCbCに移植したpiposaruを動かすのを目的 + - `par goto`がどう変換してくれるかがいまいちつかめず... + - interface中の引数で独自定義したenumとかを使うとcontext.hにincludeされない問題 + - 生成Perlスクリプトで頑張る + +# Gears関連のコマンド +- いちいちビルドした.cとcbcを確認する際に行ったり来たりするのがめんどう + - araganeコマンドをつくった + +- `aragane cbc2c main.cbc`でビルドしたcのパスを表示する +- `aragane cbc2c editor main.cbc`で.cをエディタで開く + +- なんとなくgolangのcobraをつかっている + - なぜかzsh補完も勝手に作ってくれるので便利... +- 今の所Gearsにしか対応していないので、xv6とかにも対応させたい + - make一発でrmとcmake再実行までしてくれる的な + +# hg + +- cloneするのがめんどう + - forkするのもめんどうなのでコマンド作りたいみたいな... + +# 比較連鎖 + +Perl5.32で取り入れられる(厳密には5.31からですが)のおもしろ機能として[連鎖比較](https://metacpan.org/pod/release/XSAWYERX/perl-5.32.0-RC0/pod/perldelta.pod#Chained-comparisons-capability)(<i>Chained comparisons</i>)が存在します。 + + +今までPerlで数値などが特定の範囲に含まれているかどうかをif文で判定するには次の様に書く必要がありました。 + +```perl +if (10 < $n && $n <= 20) +``` + +これがこう書ける様になります!!! + +```perl +if ( 10 < $n <= 20 ) {...} +``` + +便利!!!!!!!!!!!!!!!!!!!!!!!! + +...........というわけで、この便利な連鎖比較がどの様に実装されているかを探検してみます。 + + +# リポジトリから探す + +まずはPerl5のgitリポジトリを雑にcommit logを検索します。 +とりあえずは`chained comparisons`あたりで検索してみます。 + + +``` +$ git log --grep='chained comparisons' +commit 88c28b3819570e2ea7914875b25f0f40654c570d +Author: Dan Book <grinnz@grinnz.com> +Date: Tue Apr 28 15:18:18 2020 -0400 + + perlop - Add more examples for chained comparisons + + The distinction between how many times an expression may be evaluated and how many times its result may be fetched is somewhat confusing. This calls out the + +commit e8a86671097b355fe5e0d9da2473a926929d87c4 +Author: Zefram <zefram@fysh.org> +Date: Fri Feb 7 09:30:21 2020 +0000 + + pod/perlop.pod: expand doc on chained comparisons + +commit 02b85d3dab092d678cfc958a2dc252405333ed25 +Author: Zefram <zefram@fysh.org> +Date: Wed Feb 5 07:43:14 2020 +0000 + + chained comparisons +``` + +この内前2つはそれぞれperlopのpodの更新のコミットであり、 連鎖比較の実装そのものの変更ではありませんでした。 + + +``` +commit 02b85d3dab092d678cfc958a2dc252405333ed25 +Author: Zefram <zefram@fysh.org> +Date: Wed Feb 5 07:43:14 2020 +0000 + + chained comparisons +``` + +このコミットで連鎖比較の実装が行われています。 + + +# 連鎖比較の実装のコミットを探る + +というわけで上の`02b85d3dab092d678cfc958a2dc252405333ed25`の変更を見ていきます。 + +webから見たい方は[GitHubから見れます](https://github.com/Perl/perl5/commit/02b85d3dab092d678cfc958a2dc252405333ed25) + +## 変更があったファイル一覧 + +`$ git log -p 02b85d3dab092d678cfc958a2dc252405333ed25 --stat`とかで表示出来るらしいので見てみます。 + +```sh +$ git log -p 02b85d3dab092d678cfc958a2dc252405333ed25 --stat +commit 02b85d3dab092d678cfc958a2dc252405333ed25 +Author: Zefram <zefram@fysh.org> +Date: Wed Feb 5 07:43:14 2020 +0000 + + chained comparisons +--- + MANIFEST | 1 + + embed.fnc | 4 + + embed.h | 3 + + ext/Opcode/Opcode.pm | 4 +- + lib/B/Deparse.pm | 58 +++++ + lib/B/Deparse.t | 27 ++ + lib/B/Op_private.pm | 2 + + op.c | 115 +++++++++ + opcode.h | 16 +- + opnames.h | 4 +- + perly.act | 772 ++++++++++++++++++++++++++++++-------------------------- + perly.h | 88 +++---- + perly.tab | 1790 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------- + perly.y | 47 +++- + pod/perlop.pod | 41 ++- + pp.c | 24 ++ + pp_proto.h | 2 + + proto.h | 14 ++ + regen/opcodes | 3 + + t/op/cmpchain.t | 170 +++++++++++++ + toke.c | 50 ++-- + 21 files changed, 1930 insertions(+), 1305 deletions(-) +``` + +結構いろいろなファイルが変更されているのがわかりますね。 + +`lib/B`以下のファイル群はPerlのBモジュール(Perlのバックエンドをいい感じにスクリプトから使えるくん)関連です。 + + +## とりあえずテストから見る + +連鎖比較の実装を追う前に、そもそもどういう使用感なのかをテストから探ります。 +連鎖比較のテストは `t/op/cmpchain.t`に記述されています。 + + +全体で1749ものテストが存在するので、全てでは無いですが一部を取り出してみます。 +実行には5.32.0-RC0を利用しています。 + + +``` +$ prove -v t/op/cmpchain.t +t/op/cmpchain.t .. +1..1749 +ok 1 - <=> <=> non-associative +ok 2 - <=> cmp non-associative +ok 3 - <=> ~~ non-associative +ok 4 - cmp <=> non-associative +ok 5 - cmp cmp non-associative +ok 6 - cmp ~~ non-associative +ok 7 - ~~ <=> non-associative +ok 8 - ~~ cmp non-associative + +ok 273 - isa ge ge non-associative +ok 274 - ge ge isa non-associative +ok 275 - == == legal +ok 276 - == != legal +ok 277 - == eq legal +ok 278 - == ne legal +ok 279 - != == legal + + +ok 1724 - 5 < 7 <= 8 > 5 with side effects +ok 1725 - operand evaluation order +ok 1726 - 5 == 7 != 8 == 6 +ok 1727 - 5 < 7 <= 8 > 6 +ok 1728 - 5 == 7 != 8 == 6 with side effects +ok 1729 - operand evaluation order + +ok 1746 - 5 == 7 != 8 == 9 with side effects +ok 1747 - operand evaluation order +ok 1748 - 5 < 7 <= 8 > 9 with side effects +ok 1749 - operand evaluation order +ok +All tests successful. +Files=1, Tests=1749, 0 wallclock secs ( 0.12 usr 0.01 sys + 0.05 cusr 0.01 csys = 0.19 CPU) +Result: PASS +``` + +テストを見ると連鎖比較は `0 < $n < 10` のような3条件以外にも `5 < 7 <= 8 > 9`の様にさらに複数連鎖可能な様です。 +さらに大小以外にも`cmp`や`~~`なども使えるみたいですね。 + +## perly.(h|tab|y) + +まず最初に見るのは`perly.(h|tab|y)`系のファイルです。 + +このファイルはPerlの心臓部と言ってもいいであろう構文解析系の実装を担当しています。 +Perlは構文解析ではYacc(Bison)を利用しており、perly.yがその定義ファイル、 perly.tab及びperly.hはbisonが生成してくれるファイルです。 + +その為人間が変更したファイルであるperly.hの変更点を見てみましょう。 + +```diff +diff --git a/perly.y b/perly.y +index 0325d663c0..c90b8b41b8 100644 +--- a/perly.y ++++ b/perly.y +@@ -56,7 +56,7 @@ + %token <ival> GIVEN WHEN DEFAULT + %token <ival> LOOPEX DOTDOT YADAYADA + %token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP +-%token <ival> RELOP EQOP MULOP ADDOP ++%token <ival> MULOP ADDOP + %token <ival> DOLSHARP DO HASHBRACK NOAMP + %token <ival> LOCAL MY REQUIRE + %token <ival> COLONATTR FORMLBRACK FORMRBRACK +@@ -76,6 +76,7 @@ + %type <opval> refgen_topic formblock + %type <opval> subattrlist myattrlist myattrterm myterm + %type <opval> termbinop termunop anonymous termdo ++%type <opval> termrelop relopchain termeqop eqopchain + %type <ival> sigslurpsigil + %type <opval> sigvarname sigdefault sigscalarelem sigslurpelem + %type <opval> sigelem siglist siglistornull subsigguts subsignature optsubsignature +@@ -97,8 +98,8 @@ + %left <ival> ANDAND + %left <ival> BITOROP + %left <ival> BITANDOP +-%nonassoc EQOP +-%nonassoc RELOP ++%left <ival> CHEQOP NCEQOP ++%left <ival> CHRELOP NCRELOP + %nonassoc UNIOP UNIOPSUB + %nonassoc REQUIRE + %left <ival> SHIFTOP +@@ -1028,10 +1029,10 @@ termbinop: term ASSIGNOP term /* $x = $y, $x += $y */ + { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } + | term SHIFTOP term /* $x >> $y, $x << $y */ + { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } +- | term RELOP term /* $x > $y, etc. */ +- { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } +- | term EQOP term /* $x == $y, $x eq $y */ +- { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } ++ | termrelop %prec PREC_LOW /* $x > $y, etc. */ ++ { $$ = $1; } ++ | termeqop %prec PREC_LOW /* $x == $y, $x cmp $y */ ++ { $$ = $1; } + | term BITANDOP term /* $x & $y */ + { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } + | term BITOROP term /* $x | $y */ +@@ -1048,6 +1049,38 @@ termbinop: term ASSIGNOP term /* $x = $y, $x += $y */ + { $$ = bind_match($2, $1, $3); } + ; ++termrelop: relopchain %prec PREC_LOW ++ { $$ = cmpchain_finish($1); } ++ | term NCRELOP term ++ { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } ++ | termrelop NCRELOP ++ { yyerror("syntax error"); YYERROR; } ++ | termrelop CHRELOP ++ { yyerror("syntax error"); YYERROR; } ++ ; ++ ++relopchain: term CHRELOP term ++ { $$ = cmpchain_start($2, $1, $3); } ++ | relopchain CHRELOP term ++ { $$ = cmpchain_extend($2, $1, $3); } ++ ; ++ ++termeqop: eqopchain %prec PREC_LOW ++ { $$ = cmpchain_finish($1); } ++ | term NCEQOP term ++ { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } ++ | termeqop NCEQOP ++ { yyerror("syntax error"); YYERROR; } ++ | termeqop CHEQOP ++ { yyerror("syntax error"); YYERROR; } ++ ; ++ ++eqopchain: term CHEQOP term ++ { $$ = cmpchain_start($2, $1, $3); } ++ | eqopchain CHEQOP term ++ { $$ = cmpchain_extend($2, $1, $3); } ++ ; ++ + +``` + +結構いろいろ変更点がありますね。上から見ていきましょう。 + +```diff +@@ -56,7 +56,7 @@ + %token <ival> GIVEN WHEN DEFAULT + %token <ival> LOOPEX DOTDOT YADAYADA + %token <ival> FUNC0 FUNC1 FUNC UNIOP LSTOP +-%token <ival> RELOP EQOP MULOP ADDOP ++%token <ival> MULOP ADDOP + %token <ival> DOLSHARP DO HASHBRACK NOAMP + %token <ival> LOCAL MY REQUIRE + %token <ival> COLONATTR FORMLBRACK FORMRBRACK +``` + +このdiffを確認すると `%token <ival> RELOP EQOP MULOP ADDOP`の中の`RELOP`と`EQOP`が削除されています。 + +これはYACC中のトークンとして`RELOP` `MULOP`などを宣言し、トークンが持つ値の型として`ival`を宣言しています。 +ivalそのものやyaccの宣言部分で`I32`型として宣言されています。 + +削除された`RELOP`と`EQOP`が何であるかを見てみましょう。 +実際にYACC内でこのトークンがどういうものかを定義している構文規則部分を見てみましょう。 + +```yacc + term RELOP term /* $x > $y, etc. */ + { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } + term EQOP term /* $x == $y, $x eq $y */ + { $$ = newBINOP($2, 0, scalar($1), scalar($3)); } +``` + +コメントからなんとなく雰囲気がわかるかと思いますが、 `RELOP`は左右を`term`で囲う文法規則です。 + + + + +``` +@@ -76,6 +76,7 @@ + %type <opval> refgen_topic formblock + %type <opval> subattrlist myattrlist myattrterm myterm + %type <opval> termbinop termunop anonymous termdo ++%type <opval> termrelop relopchain termeqop eqopchain + %type <ival> sigslurpsigil + %type <opval> sigvarname sigdefault sigscalarelem sigslurpelem + %type <opval> sigelem siglist siglistornull subsigguts subsignature optsubsignature +@@ -97,8 +98,8 @@ + %left <ival> ANDAND + %left <ival> BITOROP + %left <ival> BITANDOP +-%nonassoc EQOP +-%nonassoc RELOP ++%left <ival> CHEQOP NCEQOP ++%left <ival> CHRELOP NCRELOP + %nonassoc UNIOP UNIOPSUB + %nonassoc REQUIRE +```
--- a/user/anatofuz/note/2020/06/04.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/04.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,2 @@ -# /user/anatofuz/note/2020/06/04 \ No newline at end of file +# 2020/06/04 +![camelia-logo.png](/attachment/5ed90703be90980047fddcbc) \ No newline at end of file
--- a/user/anatofuz/note/2020/06/09.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/09.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,161 @@ # 2020/06/09 -# \ No newline at end of file +# 研究目的 +- アプリケーションの信頼性を向上させたい + - その為には土台となる OS 自体の信頼性が重要である +- OSそのものも巨大なプログラムである +- 並列並行処理などに起因するバグや、そもそもOSを構成する処理が巨大 + - テストコードを用いた方法で信頼性を確保することが困難 + - テストではなく定理証明とモデル検査でOSの信頼性を高めたい + + +# 今週の進捗 +- growiのdockerのvolumeと戦っていた +- Gearsのスクリプトの修正と機能追加 + - 作っているプロジェクトは今日ビルドが通ったが、セグフォした... + +# docker-composeのvolume +- dockerではデータ永続化の為などでホストのディレクトリなどをマウントできる + - volumeと呼ばれる + +- docker-composeの場合は次のように書く + +```yaml + image: mongo:3.6 + restart: unless-stopped + volumes: + - mongo_configdb:/data/configdb + - mongo_db:/data/db + restart: always + +volumes: + mongo_db: +``` + +- 最後の`volumes`にパスを書いていない + - その場合は`/var/lib/docker/volumes`のコンテナに対応したディレクトリに保存される + - この方法だと`docker prune`とかした時に間違って消える可能性があるらしい + - ホームディレクトリとかにおいて自前で管理したい + +# データベース関連のバックアップ + +- mongodbのバックアップ + - ` docker exec -d growi_mongo_1 mongodump --gzip --archive=mongodb.gz` + - `docker cp growi_mongo_1:/mongodb.gz .` + +- mysqlのバックアップ + - `docker exec -it growi_mariadb_1 mysqldump -u hackmd -panatofuz_hackmd_pass hackmd > dump.archive` + +- mongodbのバックアップからのリストア + -`` docker cp mongodb.gz growi_mongo_1:/` + - `docker exec -it growi_mongo_1 mongorestore --gzip --drop --archive=mongodb.gz` +- mysqlのリストア + - 微妙に`docker exec`ではできなかったので、bashを立ち上げて内部でやる + - `docker exec -it growi_mariadb_1 bash` + +# Gears関連 + +- interfaceの定義時などで呼び出した自前のヘッダファイルをcontextに含める機能を実装 + +```c +#include "piposaru.h" + +typedef struct token <Type, Impl> { + __code add(Impl* token, enum TokenKind tk, char* datum, __code next(...)); + __code next(....); +} token; +``` + +- こういうふうに書いておくと + +``` +#define GET_WAIT_LIST(dseg) (GET_META(dseg)->wait) + +#define Gearef(context, t) (&(context)->data[D_##t]->t) + +// (SingleLinkedStack *)context->data[D_Stack]->Stack.stack->Stack.stack + +#define GearImpl(context, intf, name) (Gearef(context, intf)->name->intf.name) + +#include "c/enumCode.h" + +enum Relational { + EQ, + GT, + LT, +}; + +#include "c/enumData.h" +// use /Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/../parallel_execution/examples/piposaru/token.h + +#include "/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/../parallel_execution/examples/piposaru/piposaru.h" +struct Context { + enum Code next; + struct Worker* worker; + struct TaskManager* taskManager; + int codeNum; + __code (**code) (struct Context*); + union Data **data; + void* heapStart; +``` + +- こんな感じで読み込まれる + +- `enum`がgenerate_stubで上手く回収できなかったので修正した + - `enum TokenKind tk = Gearef(context, token)->TokenKind;`みたいになる問題 + +```diff +@@ -155,15 +159,15 @@ + if (/__code (\w+)/) { + next if $described_data_gear; + my $args = $'; +- while ($args =~ /\s*(struct|union|const)?\s*([\w\[\]_]+)\*?\s*(\w+),?/g) { ++ while ($args =~ /\s*(struct|union|const|enum)?\s*([\w\[\]_]+)\*?\s*(\w+),?/g) { + #$args eq (Impl* vm, pde_t* pgdir, char* init, uint sz, __code next(...)); + my $const_type = $1; + my $ttype = $2; + my $tname = $3; + + $ttype =~ s/(Impl|Isa|Type)/Data/; +- if ($const_type eq 'const') { +- $ttype = "const $ttype"; ++ if ($const_type =~ /(const|enum)/) { ++ $ttype = "$1 $ttype"; + } + $var{$name}->{$tname} = $ttype; + } +@@ -447,12 +451,12 @@ + for my $arg (@args) { + $arg =~ s/^\s*//; + last if ($arg =~ /\.\.\./); +- $arg =~ s/^(struct|union|const)?\s*(\w+)(\**)\s(\w+)//; ++ $arg =~ s/^(struct|union|const|enum)?\s*(\w+)(\**)\s(\w+)//; + my $structType = $1; + my $typeName = $2; + my $ptrType = $3; + my $varName = $4; +- if ($structType =~ /const/) { ++ if ($structType =~ /(const|enum)/) { + $typeName = "$structType $typeName"; + } + my $typeField = lcfirst($typeName); +``` + +- とりあえず生成されるようになった + +``` +__code add_token_impl_stub(struct Context* context) { + token_impl* token = (token_impl*)GearImpl(context, token, token); + enum TokenKind tk = Gearef(context, token)->tk; + char* datum = Gearef(context, token)->datum; + enum Code next = Gearef(context, token)->next; + goto add_token_impl(context, token, tk, datum, next); +} +``` + +## やること +- GearsのTaskManager周りを理解していないことがわかった + - par goto含めて修正していく + - Gearsのコンパイラ作成 + - スクリプト作ろうとしてましたが、コンパイラを目指す方針で + - Cコンパイラ? \ No newline at end of file
--- a/user/anatofuz/note/2020/06/16.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/16.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,17 @@ # 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する +--- +- CbCの変換スクリプトなどはPerlで実装されており煩雑 +- CbCを用いたプログラミング言語を作りたい + - GearsOS用の内部言語 + - Cに依存しないCbCのsyntaxを作成する +- 実装のプロトタイプとしてCbCを用いてインタプリタ/コンパイラを作成する # 今週の進捗 - Gearsの例題と格闘していた @@ -9,18 +20,131 @@ - 静的サイト化 - 投稿サイトの作成 - スイッチ撮影会 + +# Gears +- 作っているコンパイラ/インタプリタをビルドしたい + - なんかセグフォしていたので原因を探っていた +- 書いていたコード + +```c +__code createTask1(struct LoopCounter* loopCounter, struct TaskManager* taskManager) { + Lexer* lexer = createlexer_impl(context); + goto lexer->printtest(exit_code); +} +``` +- lexerのnextに`exit_code`が積まれていてほしい +- 生成されたコード + +```c +__code createTask1(struct Context *context,struct LoopCounter* loopCounter, struct TaskManager* taskManager) { + Lexer* lexer = createlexer_impl(context); + Gearef(context, Lexer)->lexer = (union Data*) lexer; + Gearef(context, Lexer)->lexer = exit_code; + context->before = C_createTask1; + goto meta(context, lexer->printtest); +} +``` +- 意図と反して`Gearef(context, Lexer)->lexer = exit_code`になっている + - nextにCodeGearが適切に積まれていないので、enumで0番くらいのCodeGearが設定されてセグフォしていた + - xv6側でも起こっていたので使い方の問題かスクリプトのミスっぽい + - generate_stubのデバッグがんばります + + +- なんかデバッグしてるとlldbがセグフォする + - 構造体ポインタの実態にアクセスすると死ぬケースがたまにある + +``` +(lldb) down +frame #0: 0x0000000100004443 piposaru`takeSynchronizedQueue(context=0x0000000100404080, queue=0x000000011412e6dc, next=C_getTaskCPUWorker, O_data=0x00000001d2cf1314) at SynchronizedQueue.c:87:21 + 84 Data* data __attribute__((unused)) = *O_data; + 85 struct Element* top = queue->top; + 86 struct Element* last = queue->last; +-> 87 struct Element* nextElement = top->next; + 88 if (top != queue->top) { + 89 context->before = C_takeSynchronizedQueue; + 90 goto meta(context, C_takeSynchronizedQueue); +(lldb) p top +(Element *) $0 = 0x000000011412e714 +(lldb) p top->next +error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory +(lldb) p *top +error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory +(lldb) p top +Stack dump: +0. Program arguments: /Applications/Xcode.app/Contents/Developer/usr/bin/lldb piposaru +0 lldb 0x000000010e75ff08 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 +1 lldb 0x000000010e75f4c5 llvm::sys::RunSignalHandlers() + 85 +2 lldb 0x000000010e760550 SignalHandler(int) + 272 +3 libsystem_platform.dylib 0x00007fff6fa1d5fd _sigtramp + 29 +4 libsystem_platform.dylib 000000000000000000 _sigtramp + 2422090272 +5 LLDB 0x000000011263ece9 clang::ASTNodeImporter::ImportDeclContext(clang::DeclContext*, bool) + 1145 +6 LLDB 0x00000001126630a9 clang::ASTImporter::ImportDefinition(clang::Decl*) + 233 +7 LLDB 0x000000010f117c1c lldb_private::ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(clang::Decl*, clang::Decl*) + 60 +8 LLDB 0x000000010f117a54 lldb_private::ClangASTImporter::CompleteTagDecl(clang::TagDecl*) + 276 +9 LLDB 0x000000010f2b1203 lldb_private::ClangASTSource::CompleteType(clang::TagDecl*) + 659 +10 LLDB 0x000000010f0fe259 GetCompleteQualType(clang::ASTContext*, clang::QualType, bool) + 617 +11 LLDB 0x000000010f10345a lldb_private::ClangASTContext::GetNumChildren(void*, bool, lldb_private::ExecutionContext const*) + 858 +12 LLDB 0x000000010f10341e lldb_private::ClangASTContext::GetNumChildren(void*, bool, lldb_private::ExecutionContext const*) + 798 +13 LLDB 0x000000010f052134 lldb_private::ValueObjectConstResult::CalculateNumChildren(unsigned int) + 68 +14 LLDB 0x000000010f046b47 lldb_private::ValueObject::GetNumChildren(unsigned int) + 87 +15 LLDB 0x000000010f05e843 lldb_private::FormatManager::ShouldPrintAsOneLiner(lldb_private::ValueObject&) + 371 +16 LLDB 0x000000010f074156 lldb_private::ValueObjectPrinter::PrintChildrenIfNeeded(bool, bool) + 134 +17 LLDB 0x000000010f0733f6 lldb_private::ValueObjectPrinter::PrintValueObject() + 374 +18 LLDB 0x000000010f04d57a lldb_private::ValueObject::Dump(lldb_private::Stream&, lldb_private::DumpValueObjectOptions const&) + 90 +19 LLDB 0x000000010f62cd6c lldb_private::CommandObjectExpression::EvaluateExpression(llvm::StringRef, lldb_private::Stream*, lldb_private::Stream*, lldb_private::CommandReturnObject*) + 1452 +20 LLDB 0x000000010f62d9ce lldb_private::CommandObjectExpression::DoExecute(llvm::StringRef, lldb_private::CommandReturnObject&) + 1630 +21 LLDB 0x000000010f0d0b9d lldb_private::CommandObjectRaw::Execute(char const*, lldb_private::CommandReturnObject&) + 413 +22 LLDB 0x000000010f0c89fe lldb_private::CommandInterpreter::HandleCommand(char const*, lldb_private::LazyBool, lldb_private::CommandReturnObject&, lldb_private::ExecutionContext*, bool, bool) + 2798 +23 LLDB 0x000000010f0cc38e lldb_private::CommandInterpreter::IOHandlerInputComplete(lldb_private::IOHandler&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&) + 606 +24 LLDB 0x000000010f00c331 lldb_private::IOHandlerEditline::Run() + 289 +25 LLDB 0x000000010eff45b9 lldb_private::Debugger::ExecuteIOHandlers() + 105 +26 LLDB 0x000000010f0cce9c lldb_private::CommandInterpreter::RunCommandInterpreter(bool, bool, lldb_private::CommandInterpreterRunOptions&) + 156 +27 LLDB 0x000000010ee6d3c1 lldb::SBDebugger::RunCommandInterpreter(bool, bool) + 209 +28 lldb 0x000000010e748d96 Driver::MainLoop() + 2694 +29 lldb 0x000000010e74a41f main + 1679 +30 libdyld.dylib 0x00007fff6f824cc9 start + 1 +31 libdyld.dylib 0x0000000000000002 start + 2424156986 +zsh: segmentation fault lldb piposaru +``` + +# Gears on XV6 +- なんやかんやシステムコールを中心に書き換えていくのが良さそう + - メモリ管理系の書き換えをすると、どうしても既存のAPIに乗っかってしまう + - 全体的に書き換えるならディスパッチから書き換えるのが良さそう # GearsTools - Gearsのビルドで使われるPerlのツール - 主に2種類 - `generate_stub.pl` - CbCで書かれたファイルを元にCファイル(実際はCbC)を作成する + - 生成されたファイルはビルドディレクトリの`c`以下に配置される - `hoge_stub`みたいなメタ計算に該当するCodeGearも生成される - `generate_context.pl` - context.hとproject-context.c及び各種enumを作成する - context.hの作成時に別で作ったPerlモジュールを利用するようになっている +- この2つはCMake側で実行される # GearsToolの差分 - +- 歴史的にはGearsのスクリプトをxv6に移植している +- いくつかの問題が発生していたので、 xv6側の方はパッチがあたっている + - xv6側の`context`構造体と名前が衝突 + - ヘッダファイル`stdio`をincludeさせないようにする + - free/mallocする関数と構造体の抑制 +- どちらかのスクリプトを修正すると片方を追従しないといけない + - コピペと削除を毎回する必要がありめんどう + +# 作業 +- オプション解析をしているモジュールを`Getopt::Std`から`Getopt::Long`に変更 + - 新しく`--project`オプションを足した + - デフォルトでgearsの設定、 `--project xv6`するとxv6のテンプレが利用される +- contextの名前などをオプションに応じて変更するように修正 +- テンプレートの動的ロード機能の実装 + - 使ったモジュールが(コアモジュールなのに)無かったのでyumでinstallした +# 今後 +- Gears,xv6でperlスクリプトに変更があった場合はコピってくればok + - submoduleみたいなのにまとめておく? +# シス管関連 +- 詳しくは明日のミーティングで... +- 学科webサイト関連の調査と実装、スイッチの撮影会をしていました \ No newline at end of file
--- a/user/anatofuz/note/2020/06/23.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/23.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,51 +1,171 @@ # 2020/06/23 -## 起こっていたこと +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する +--- + +- CbCの変換スクリプトなどはPerlで実装されており煩雑 +- CbCを用いたプログラミング言語を作りたい + - GearsOS用の内部言語 + - Cに依存しないCbCのsyntaxを作成する +- 実装のプロトタイプとしてCbCを用いてインタプリタ/コンパイラを作成する + +# 進捗 +- Gearsの例題の修正とgenerate_stubの修正 +- 様々な理由でperlインタプリタを読んでいた +- xv6そろそろやりはじめた +- シス管関係...... +- ~~明日寄稿した雑誌が発売します!!~~ + +# Gearsの例題 + +## インタプリタ/コンパイラ +- 実装に進める段階までコードを直した(セグフォしなくなった) + - Gearsのプログラムを停止させる場合は次のCodeGearを呼び出す必要がある + +```c +__code code2(struct TaskManager* taskManager) { + goto taskManager->shutdown(exit_code); +} + +__code code2_stub(struct Context* context) { + goto code2(context, &Gearef(context, TaskManager)->taskManager->TaskManager); +} +``` + +- `exit_code`はtaskManager経由で呼び出さないとセグフォする + - 今までは`par goto`が全て終了したタイミングで`code2`が実行されていた + +## generate_stubのバグ修正 ``` -__code createTask1(struct LoopCounter* loopCounter, struct TaskManager* taskManager, char* arg) { +__code createTask1(struct LoopCounter* loopCounter, struct TaskManager* taskManager) { Lexer* lexer = createLexerImpl(context); - goto lexer->lex(arg, code2); + goto lexer->test(code2); } ``` こういうCodeGearを書いた場合次のマクロが生成されてほしい ```c -Gearef(context, lexer)->lexer = lexer; +__code createTask1(struct Context *context,struct LoopCounter* loopCounter, struct TaskManager* taskManager) { + Lexer* lexer = createLexerImpl(context); + Gearef(context, Lexer)->lexer = (union Data*) lexer; + Gearef(context, Lexer)->next = C_code2; + context->before = C_createTask1; + goto meta(context, lexer->printtest); +} +``` + +...が、`Gearef(context, Lexer)->next`が生成されず、`Gearef(context, Lexer)->lexer`に代入されてしまっていた + +### `hoge->next`に値摘んでくれない問題 +- `generate_stub`の527行目くらいが問題そう + - 実際にgoto文を生成している場所 + +```perl + } elsif (/^(.*)goto (\w+)\-\>(\w+)\((.*)\);/) { + # handling goto statement + # convert it to the meta call form with two arugments, that is context and enum Code + my $prev = $1; + my $next = $2; + my $method = $3; + my $tmpArgs = $4; + #$tmpArgs =~ s/\(.*\)/\(\)/; + my @args = split(/,/,$tmpArgs); + if (! defined $dataGearVarType{$codeGearName}) { + print $fd $_ ; + next ; + } + my @types = @{$dataGearVarType{$codeGearName}}; + my $ntype; + my $ftype; + for my $v (@{$dataGearVar{$codeGearName}}) { + my $t = shift @types; + if ($v eq $next || $v eq "O_$next") { + $ntype = $t; + $ftype = lcfirst($ntype); + } + } + if (!defined $ntype) { + $ntype = $localVarType{$next}; + $ftype = lcfirst($ntype); + } + print $fd "\tGearef(${context_name}, $ntype)->$ftype = (union Data*) $next;\n"; + # Put interface argument + my $prot = $code{$ntype}->{$method}; + my $i = 1; + for my $arg (@args) { + my $pType; + my $pName; + my $p = @$prot[$i]; + next if ($p eq $arg); + $p =~ s/^(.*)\s(\w+)//; + $pType = $1; + $pName = $2; + $arg =~ s/^(\s)*(\w+)/$2/; + if ($pType =~ s/\_\_code$//) { + if ($arg =~ /(\w+)\(.*\)/) { + print $fd "\tGearef(${context_name}, $ntype)->$pName = $1;\n"; + } else { + print $fd "\tGearef(${context_name}, $ntype)->$pName = C_$arg;\n"; + } + } elsif ($pType =~ /Data\**$/){ + print $fd "\tGearef(${context_name}, $ntype)->$pName = (union $pType) $arg;\n"; + } else { + print $fd "\tGearef(${context_name}, $ntype)->$pName = $arg;\n"; + } + $i++; + } + print $fd "${prev}context->before = C_$codeGearName;\n"; + print $fd "${prev}goto meta(context, $next->$method);\n"; + next; ``` -- `hoge->next`に値摘んでくれない問題 - - `generate_stub`の527行目くらいが問題そう +- デバッグしたところ問題となってるのがこのところ ```perl - } elsif (/^(.*)goto (\w+)\-\>(\w+)\((.*)\);/) { - # handling goto statement - # convert it to the meta call form with two arugments, that is context and enum Code - my $prev = $1; - my $next = $2; - my $method = $3; - my $tmpArgs = $4; - #$tmpArgs =~ s/\(.*\)/\(\)/; - my @args = split(/,/,$tmpArgs); - if (! defined $dataGearVarType{$codeGearName}) { - print $fd $_ ; - next ; - } - my @types = @{$dataGearVarType{$codeGearName}}; - my $ntype; - my $ftype; - for my $v (@{$dataGearVar{$codeGearName}}) { - my $t = shift @types; - if ($v eq $next || $v eq "O_$next") { - $ntype = $t; - $ftype = lcfirst($ntype); - } - } + print $fd "\tGearef(${context_name}, $ntype)->$ftype = (union Data*) $next;\n"; + # Put interface argument + my $prot = $code{$ntype}->{$method}; + my $i = 1; + for my $arg (@args) { + my $pType; + my $pName; + my $p = @$prot[$i]; + next if ($p eq $arg); + $p =~ s/^(.*)\s(\w+)//; + $pType = $1; + $pName = $2; + $arg =~ s/^(\s)*(\w+)/$2/; + if ($pType =~ s/\_\_code$//) { + if ($arg =~ /(\w+)\(.*\)/) { + print $fd "\tGearef(${context_name}, $ntype)->$pName = $1;\n"; + } else { + print $fd "\tGearef(${context_name}, $ntype)->$pName = C_$arg;\n"; + } + } elsif ($pType =~ /Data\**$/){ + print $fd "\tGearef(${context_name}, $ntype)->$pName = (union $pType) $arg;\n"; + } else { + print $fd "\tGearef(${context_name}, $ntype)->$pName = $arg;\n"; + } + $i++; + } + print $fd "${prev}context->before = C_$codeGearName;\n"; + print $fd "${prev}goto meta(context, $next->$method);\n"; + next; ``` -- ここで`%code`の中身から次のCodeGearを取り出すなどの処理がある - - なんかデバッガでdumpしたら明らかにおかしい結果に... +- `$next`は次のCodeGearの名前じゃなくて、インスタンスが入っている +- ` my $prot = $code{$ntype}->{$method};`でInterfaceのメソッド一覧を取り出している + - `$ntype`は現在のinterface名、 `$method`は`->`で呼び出す先 + +- なんかデバッガでdumpしたら`%code`が明らかにおかしい結果に... + - `Lexer`と`Lexer `が混在している - ここが関係していそう ```perl @@ -92,4 +212,156 @@ ], shutdown [ -``` \ No newline at end of file +``` + +### 原因 + +- InterfaceからCodeGearを取り出す箇所のキャプチャがおかしかった + +書いていたInteface + +```c +typedef struct Lexer <Type, Impl> { + __code read_char(Impl* lexer, char* ch, __code next(... )); + __code eat_whitespace(Impl* lexer, char* ch, __code next(... )); + __code next_token(Impl* lexer, __code next(struct token* tok, ...)); + __code printtest(Impl* lexer, __code next(...)); + __code next(....); +} Lexer; +``` + +ここの`typedef struct Lexer <Type`の行をキャプチャしにいっていたが... + + +- ` elsif(/^typedef struct (.*)<.*>\s*{/) {` + - `(.*)`でキャプチャしていたので、空白も含まれる状態に.... + - `(\w+)`に書き直すことでなんとなかなった + +```diff +--- a/src/parallel_execution/generate_stub.pl Tue Jun 16 21:09:01 2020 +0900 ++++ b/src/parallel_execution/generate_stub.pl Mon Jun 22 09:17:31 2020 +0900 +@@ -203,10 +203,10 @@ + open my $fd,"<",$filename or die("can't open $filename $!"); + my ($name,$impln); + while (<$fd>) { +- if (/^(\w+)(\*)+ create(\w+)\(/) { ++ if (/^(\w+)\s*(\*)+ create(\w+)\(/) { + $name = $1; + $impln = $3; +- } elsif(/^typedef struct (.*)<.*>\s*{/) { ++ } elsif(/^typedef struct (\w+)\s*<.*>\s*{/) { + $name = $1; + } + if (defined $name) { +``` + +- xv6側もその実装だったので、去年あったマクロがずれるとかの問題も影響していそう... + +# xv6側 + +- システムコール呼び出し側から実装していく + - 去年書いたコードは使えなさそうな気がする..... + +```c +void syscall(void) +{ + int num; + int ret; + + num = proc->tf->r0; + + if (num == 5) + num = 22; + //cprintf ("syscall(%d) from %s(%d)\n", num, proc->name, proc->pid); + + if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) { + proc->cbc_arg.cbc_console_arg.num = num; + goto (cbccodes[num])(cbc_ret); + //goto meta(&proc->cbc_context, cbccodes[num]); + } + + + if((num > 0) && (num < NELEM(syscalls)) && syscalls[num]) { + ret = syscalls[num](); + + // in ARM, parameters to main (argc, argv) are passed in r0 and r1 + // do not set the return value if it is SYS_exec (the user program + // anyway does not expect us to return anything). + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + } else { + cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); + proc->tf->r0 = -1; + } +} +``` + +- 現状は`cbc_read`だけgotoする様になっている + - `cbc_read`自体は`__ncode`で書かれていてIntertface化されていない + +- とりあえずSyscall Interfaceを書いてそれを各システムコールで実装する + - `file->read()`とかにするとかっこいいけれど、それはシステムコールディスパッチしてから記述する + - syscallの実装をContextに持っておかないと行けないので、kernelのContextを最初に作らないとダメそう + +## kernelのContext +- システムコールディスパッチの箇所や、例外処理などで必要そう + - context間通信みたいなのを実装すれば必要無い可能性はある +- どのタイミングで生成する? + - 仮想メモリ自体も管理したいなら、仮想メモリマネージャーを作る前で作成する必要がある + - 具体的に言うと`main.c`の`init_vmm`の実行前にするべき? +- どうやって保存する? + - 大域変数が一番楽ではあるけれど...... +- kernelのContextがprocess Contextを管理する形にすると良さそう + +--- + +- とりあえずmain.cに大域変数で実装してみている + - シングルトンっぽくなるのであまりやりたくはない.... + +```c +struct Context kernel_context; + +#define MB (1024*1024) + +void kmain (void) +{ + uint vectbl; + + cpu = &cpus[0]; + + uart_init (P2V(UART0)); + + // interrrupt vector table is in the middle of first 1MB. We use the left + // over for page tables + vectbl = P2V_WO (VEC_TBL & PDE_MASK); + + init_vmm (); + kpt_freerange (align_up(&end, PT_SZ), vectbl); + kpt_freerange (vectbl + PT_SZ, P2V_WO(INIT_KERNMAP)); + paging_init (INIT_KERNMAP, PHYSTOP); + + kmem_init (); + kmem_init2(P2V(INIT_KERNMAP), P2V(PHYSTOP)); + initContext(&kernel_context); + + trap_init (); // vector table and stacks for models + pic_init (P2V(VIC_BASE)); // interrupt controller + uart_enable_rx (); // interrupt for uart +``` +- `init_vmm`から`kmem_init2`までの一連のルーチンに鑑賞できない点が辛い + - どうにかしたい気がする..... + - ~~諦める?~~ + + + +## 今後の方針 +- kernelのcontextを実装する + - kernelのcontextを初期化する場所を決める + - 新しい変換スクリプトを書く/generateContextに手を加える +- read systemcallのinterface化 + +# Perlインタプリタ + +- 字句解析/構文解析/AST関連を見てた +- 主に連鎖比較関係 \ No newline at end of file
--- a/user/anatofuz/note/2020/06/26.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/26.md Wed Dec 16 15:11:16 2020 +0900 @@ -20,4 +20,8 @@ こんな感じ? - stubなので`struct Context*`だけ引数にしたい気がする - trapframeを受け取るのは仕様上しょうがないので、stubにする意味があるのかどうか - - とはいえ構造体を受けて`__code`にわたすのはstubそのものなので悩ましい \ No newline at end of file + - とはいえ構造体を受けて`__code`にわたすのはstubそのものなので悩ましい + +現状のstub +- generate_contextがexternをまとめて生成している +- 引数は`Context*`決め打ち \ No newline at end of file
--- a/user/anatofuz/note/2020/06/30.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/06/30.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,8 +1,84 @@ +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する +--- + +- CbCの変換スクリプトなどはPerlで実装されており煩雑 +- CbCを用いたプログラミング言語を作りたい + - GearsOS用の内部言語 + - Cに依存しないCbCのsyntaxを作成する +- 実装のプロトタイプとしてCbCを用いてインタプリタ/コンパイラを作成する + # 今週の進捗 - Gearsのプロジェクトで色々実験していた - xv6の書き換え - シス管関係 +## Gearsの実験 + +- Interfaceに乗せている`read_char`からInterface化していない`hello2`を呼ぶとどうなるか検証 + - `read_char`はmainから呼び出している + +```c +__code createTask1(struct LoopCounter* loopCounter, struct TaskManager* taskManager) { + Lexer* lexer = createLexerImpl(context); + goto lexer->read_char("hello!!",code2); +} +``` + +- InterfaceのImpl内部 + + +```c +__code read_char_LexerImpl(struct LexerImpl* lexer, char* ch, __code next(... )) { + printf("%s\n", ch); + goto hello2(next); +} + +__code hello2(struct LexerImpl* lexer, __code next(...)) { + printf("Hello2! Test!\n"); + goto next(...); +} +``` + +- ビルドしたらこんな感じに + +```c +__code read_char_LexerImpl(struct Context *context,struct LexerImpl* lexer, char* ch, enum Code next) { + printf("%s\n", ch); + context->before = C_read_char_LexerImpl; + goto meta(context, C_hello2); +} + +__code read_char_LexerImpl_stub(struct Context* context) { + LexerImpl* lexer = (LexerImpl*)GearImpl(context, Lexer, lexer); + char* ch = Gearef(context, Lexer)->ch; + enum Code next = Gearef(context, Lexer)->next; + goto read_char_LexerImpl(context, lexer, ch, next); +} + +__code hello2(struct Context *context,struct LexerImpl* lexer, enum Code next) { + printf("Hello2! Test!\n"); + context->before = C_hello2; + goto meta(context, next); +} +__code hello2_stub(struct Context* context) { + LexerImpl* lexer = (LexerImpl*)GearImpl(context, Lexer, lexer); + enum Code next = Gearef(context, Lexer)->next; + goto hello2(context, lexer, next); +} +``` +- ちゃんと呼び出しもとで設定したnextを担保して`goto`できる +- とはいえ同一ファイル内で定義すると、全てInterfaceから値を取ってくる + - Implの中で値を使いたかったら、Implに値を積んで`__code`内で取ってくる + - 入出力を構造体にすれば良さそうというのを思いついたけれど、内部の`__code`の入出力に気を配りたいかみたいな問題 + + +- ここまで書けて小さなプロジェクトが動きそうだったのでgrowiに入門記事を軽く書いた +- Gearsの方は今週小さいレキサーを書こうとしています # xv6の書き換え - システムコール周辺から書き換えていく @@ -11,6 +87,7 @@ - 読み会そろそろやるとかいう噂が + # xv6の書き換え方針 - `stub`の変換などで難しそうなルーチン(`generate*`の修正が入りそうなもの)は`__ncode`で宣言する - `__ncode`の場合はenumが生成されないので`goto meta`が現状ではできない @@ -18,6 +95,222 @@ - 引数周りはInterfaceにする - Itnerfaceの内部で使うプライベート変数はImpl側に積んで、各`__code`内で取り出す - 引数も別の構造体にすると良さそうだけど、そこまでまだ追求しない + +## KernelContext +- 大域変数で握ってた各種フラグやシステムコールテーブルなどを持つContext +- 基本的にはプロセスのCotnextと等価 +- 型で別けたほうが良い? と思って型で別けてみている + +```c +typedef struct KernelContext { + struct Context context; + __code (*syscalls[10]) (void); + struct Context* proc_contexts[NPROC]; + struct proc* now_proc; +} KernelContext; +``` + +- 今の所もっているもの + - systemcallテーブル + - 現在走っているプロセス + - 全ユーザープロセスのコンテキストのリスト + +### 初期化のタイミングと置き場所 + +- KernelContext自体はヘッダファイルで大域変数化している + +```c +struct KernelContext* kernel_context; +``` + +- 今の所は仮想メモリ関連の処理が一通り終わった後にkmallocしている + +```c +void userinit(void) +{ + struct proc* p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + initContext(&p->cbc_context); + p->cbc_context.kernel_context = &kernel_context->context; + + initproc = p; +``` + + +- 使いたい時にローカル変数にポインタに代入する + +```c +void userinit(void) +{ + struct proc* p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + struct KernelContext* kernel = &kernel_context; + p = allocproc(); + initContext(&p->cbc_context); + p->cbc_context.kernel_context = &kernel->context; + + initproc = p; +``` + +## システムコールディスパッチの呼び出し +- trapが来たらアセンブラでハンドラがまず呼びだされる + +```asm +# handle SWI, we allow nested SWI +trap_swi: + # build trapframe on the stack + STMFD sp!, {r0-r12, r14} // save context + MRS r2, spsr // copy spsr to r2 + STMFD r13!, {r2} // save r2(spsr) to the stack + STMFD r13!, {r14} // save r14 again to have one uniform trapframe + STMFD r13, {sp, lr}^ // save user mode sp and lr + SUB r13, r13, #8 + + # call traps (trapframe *fp) + MOV r0, r13 // copy r13_svc to r0 + BL swi_handler // branch to the isr_swi +``` + +- trap.c + - 関数呼び出しで`syscall`が呼ばれる + - 現状の実装だとこのスタックフレームに戻らないと死ぬ + +```c +// trap routine +void swi_handler (struct trapframe *r) +{ + if (proc->killed) + exit(); + proc->tf = r; + syscall (); + if (proc->killed) + exit(); +} +``` + +- CbCからスタックフレームを操作するのはダメそう +- ということでハンドラそのものも`__code`にしてしまってここで`goto`すれば解決? + +```c +extern __code exit(void); + + +__ncode cbc_swi_handler(struct trapframe* r) { + struct Context* kernel = &kernel_context->context; + struct Syscall* syscall = Gearef(kernel, Syscall)->syscall; + + if (proc->killed) { + struct KernelRet* kernelret = Gearef(kernel, KernelRet)->kernel_ret; + goto meta(kernel, kernelret->exit); + } + proc->tf = r; + goto meta(kernel, syscall->dispatch); +} +``` + +- システムコールのreturnなどでinterface化しておくのが良さそうな気がしたので、Interfaceにしている + +```c +typedef struct KernelRet <Type, Impl> { + __code cbc_return(Impl* kernel_ret, int ret, __code next(...)); + __code exit(Impl* kernel_ret, __code next(...)); + __code swtch(Impl* kernel_ret, __code next(...)); + __code next(....); +} KernelRet; +``` + +```c +typedef struct KernelRetImpl <Type, Isa> impl KernelRet { + __code next(....); +} KernelRetImpl; +``` + +```c +#include "../context.h" +#interface "KernelRet.h" + +// ---- +// typedef struct KernelRetImpl <Type, Isa> impl KernelRet { +// __code next(....); +// } KernelRetImpl; +// ---- + +KernelRet* createKernelRetImpl(struct Context* cbc_context) { + struct KernelRet* kernel_ret = new KernelRet(); + struct KernelRetImpl* kernel_ret_impl = new KernelRetImpl(); + kernel_ret->kernel_ret = (union Data*)kernel_ret_impl; + kernel_ret->cbc_return = C_cbc_returnKernelRetImpl; + kernel_ret->exit = C_exitKernelRetImpl; + kernel_ret->swtch = C_swtchKernelRetImpl; + return kernel_ret; +} +__code cbc_returnKernelRetImpl(struct KernelRetImpl* kernel_ret, int ret, __code next(...)) { + int num = proc->cbc_arg.cbc_console_arg.num; + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + goto cbc_trap_return(); +} + +extern __code exit(void); +__code exitKernelRetImpl(struct KernelRetImpl* kernel_ret, __code next(...)) { + goto exit(); +} + +extern __code swtch(void); + +__code swtchKernelRetImpl(struct KernelRetImpl* kernel_ret, __code next(...)) { + goto swtch(); +} + +``` + +## Gearsでenumを生成している箇所 + +- 静的にstub書いてたらenumが生成されなくて困った +- `generate_context.pl`で`__stub`の中身を見て生成している + - 入力で与えられた全部の`.c`ファイルを走査する + +```perl +sub getStubInfo { + my ($filename) = @_; + open my $fd,"<",$filename or die("can't open $filename $!"); + while (<$fd>) { + if (/^__code (\w+)_stub\(struct *Context *\* *${context_name}\)/) { + $codeGear{$1} = $filename; + } elsif (/^(\w+)(\*)+ *create(\w+)\(([^]]*)\)/) { + my $interface = $1; + my $implementation = $3; + my $constructorArgs = $4; + $constructor{$implementation} = [$interface, $constructorArgs]; + } + } +``` +- ここでキャプチヤにしている正規表現 + +`if (/^__code (\w+)_stub\(struct *Context *\* *${context_name}\)/) {` +- これが`generate_stub`で自動生成したもの前提になっていたので、簡易化した + - `kernel_context`を引数にいれるとキャプチャできなくなる為 + +```diff +- if (/^__code (\w+)_stub\(struct *Context *\* *${context_name}\)/) { ++ if (/^__code (\w+)_stub\(/) { +``` + +- 実際に生成しているとこはここ + - `enum`に加えたいものがある場合は、ここで静的に書き出せば良い + +```perl + open my $fd,">","$ddir/enumCode.h" or die("can't open $ddir/enumCode.h $!"); + print $fd "enum Code {\n"; + for my $code ( sort keys %codeGear ) { + print $fd " C_${code},\n"; + } + print $fd "};\n"; +``` # CbCからアセンブラを呼ぶ
--- a/user/anatofuz/note/2020/07/07.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/07/07.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,13 @@ # 2020/07/07 # 研究目的 +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する + # 進捗 - xv6軽く読んだ @@ -12,13 +19,615 @@ - wakeup - sleep - ... - - + +# Gears関連 + +## 問答無用で`goto meta`に変換される問題 + +- 変換は`generate_stub.pl`でやっていて、ここの処理が問題 + +```perl + } elsif (/extern\s+_\_code\s+(\w+)\((.*)\)/) { + $localCode{$1} = 1; + } elsif (/^\s\s*_\_code\s+(\w+)\((.*)\)(.*)/) { + $localCode{$1} = 1; + } elsif (/^\s\s*_\_code *\(\s*\*\s*(\w+)\)\((.*)\)(.*)/) { + $localCode{$1} = 1; +``` +- ` __code`(先頭にスペース)があったものはlocalCodeにカウントされる + - `localCode`はhash + - externの部分は今週追加したとこ + +`%localCode`は`goto`が来たタイミングで中身が確認される +- goto先がlocalCodeだったら`goto meta`にしない + +```perl + } elsif (/^(.*)goto (\w+)\((.*)\);/) { + # handling goto statement + # convert it to the meta call form with two arugments, that is context and enum Code + my $prev = $1; + my $next = $2; + my @args = split(/,/, $3); + my $v = 0; + if (defined $localCode{$next}) { + print $fd $_; next; + } + for my $n ( @{$dataGearVar{$codeGearName}} ) { + # continuation arguments + $v = 1 if ( $n eq $next); + } +``` + +デバッグした + +``` + DB<33> c +main::generateDataGear(/mnt/dalmore-home/one/src/cbcxv6/src/gearsTools/generate_stub.pl:650): +650: if (defined $localCode{$next}) { + DB<33> p $_ + goto trapret(); + + DB<34> print Dumper \%localCode; +$VAR1 = { + 'HASH(0x29947c0)' => undef + }; +``` + +- `%localCode`の値がわけわからんものになっている + +```diff + } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) { + $inCode = 1; +- %localCode = {}; ++ $localCode{$inCode} = {}; + %localVarType = {}; + $codeGearName = $1; + my $args = $2; +``` + +- Perlだとハッシュにハッシュリファレンスを代入するとリファレンスの文字列表記がキーになるなしい... + - ということで従来の実装だと`localCode`が死んでいてた + +# xv6の書き換え + +- 読み会やりつつ書き換えていく +- システムコールを中心に書き換える +- Interfaceへの変換は素朴にやる + - `__ncode`を愚直に書き換えていく + +# システムコール呼び出し +- trapした時に呼ばれるハンドラで関数呼び出しをしてシステムコールを読んでいる + - 部分的にスタックがあるので色々と不便 + - とりあえずスタックを追放する路線で実装をすすめる + +# trap_asm.S + +- 書き換えた`cbc_swi_handler`にBL + +```asm +# handle SWI, we allow nested SWI +trap_swi: + # build trapframe on the stack + STMFD sp!, {r0-r12, r14} // save context + MRS r2, spsr // copy spsr to r2 + STMFD r13!, {r2} // save r2(spsr) to the stack + STMFD r13!, {r14} // save r14 again to have one uniform trapframe + STMFD r13, {sp, lr}^ // save user mode sp and lr + SUB r13, r13, #8 + + # call traps (trapframe *fp) + MOV r0, r13 // copy r13_svc to r0 + BL cbc_swi_handler // branch to the isr_swi +``` + -# プロセス関連 -- proc.cbcの中の`__ncode`な部分を優先的に書き換えていく +# trap.cbc + +- もともとのコード + +```c +// trap routine +void swi_handler (struct trapframe *r) +{ + if (proc->killed) + exit(); + proc->tf = r; + syscall (); + if (proc->killed) + exit(); +} +``` +- exitするのはsyscall()の次の継続でやる路線にすれば書き換えられそう +- `goto meta`でkernel使いたいときはとりあえず愚直に書く + - `SyscallDispatch`を毎回初期化するのめんどいので別の場所で初期化したい + - なぜかコンストラクタを`extern`しないと関数呼び出しが落とされる + +```c +extern SyscallDispatch* createSyscallDispatchImpl(struct Context*); +extern KernelRet* createKernelRetImpl(struct Context*); + +__ncode cbc_swi_handler(struct trapframe* r) { + struct Context* kernel = &kernel_context->context; + struct SyscallDispatch* syscall_dispatch = createSyscallDispatchImpl(kernel); + + if (proc->killed) { + struct KernelRet* kernelret = createKernelRetImpl(kernel); + goto meta(kernel, kernelret->exit); + } + proc->tf = r; + goto meta(kernel, syscall_dispatch->dispatch); +} +``` + +``` +Breakpoint 1, cbc_swi_handler (r=0x87fe2fb8) at /mnt/dalmore-home/one/build/cbcxv6/CMakeFiles/kernel.dir/c/trap.c:17 +17 struct Context* kernel = &kernel_context->context; +(gdb) n +18 struct Syscall* syscall = createSyscallImpl(kernel); +(gdb) p kernel +$1 = (struct Context *) 0x87ffd000 +(gdb) n +20 if (proc->killed) { +(gdb) p syscall +$2 = (struct Syscall *) 0x87fe2fb4 +(gdb) p *syscall +$3 = {syscall = 0x0, dispatch = C_allocinode, next = C_copyuvm_loop_bad} +(gdb) quit +``` + +``` +17 struct Context* kernel = &kernel_context->context; +(gdb) x/20i $pc +=> 0x800245e4 <cbc_swi_handler+16>: ldr r3, [pc, #176] ; 0x8002469c <swi_handler+16> + 0x800245e8 <cbc_swi_handler+20>: ldr r3, [r3] + 0x800245ec <cbc_swi_handler+24>: str r3, [r11, #-8] + 0x800245f0 <cbc_swi_handler+28>: ldr r3, [r11, #-8] + 0x800245f4 <cbc_swi_handler+32>: ldr r3, [r3, #28] + 0x800245f8 <cbc_swi_handler+36>: add r3, r3, #40 ; 0x28 + 0x800245fc <cbc_swi_handler+40>: ldr r3, [r3] + 0x80024600 <cbc_swi_handler+44>: ldr r3, [r3] + 0x80024604 <cbc_swi_handler+48>: str r3, [r11, #-12] + 0x80024608 <cbc_swi_handler+52>: ldr r3, [pc, #144] ; 0x800246a0 <swi_handler+20> + 0x8002460c <cbc_swi_handler+56>: ldr r3, [r3] + 0x80024610 <cbc_swi_handler+60>: ldr r3, [r3, #36] ; 0x24 + 0x80024614 <cbc_swi_handler+64>: cmp r3, #0 + 0x80024618 <cbc_swi_handler+68>: beq 0x80024660 <cbc_swi_handler+140> + 0x8002461c <cbc_swi_handler+72>: ldr r3, [r11, #-8] + 0x80024620 <cbc_swi_handler+76>: ldr r3, [r3, #28] + 0x80024624 <cbc_swi_handler+80>: add r3, r3, #20 + 0x80024628 <cbc_swi_handler+84>: ldr r3, [r3] + 0x8002462c <cbc_swi_handler+88>: ldr r3, [r3] + 0x80024630 <cbc_swi_handler+92>: str r3, [r11, #-16] +``` + +# systemcall dispatch + +- dispatchするだけ + +```c +typedef struct SyscallDispatch <Type, Impl> { + __code dispatch(Impl* syscall_dispatch, __code next(...)); + __code next(....); +} SyscallDispatch; +``` + +```c +typedef struct SyscallDispatchImpl <Type, Isa> impl SyscallDispatch { + __code next(....); +} SyscallDispatchImpl; +``` + +```c +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "arm.h" +#include "syscall.h" + +#include "../../kernel.h" +#interface "SyscallDispatch.h" +#interface "KernelRet.h" + +extern int sys_chdir(void); +extern int sys_close(void); +extern int sys_dup(void); +extern int sys_exec(void); +extern int sys_exit(void); +extern int sys_fork(void); +extern int sys_fstat(void); +extern int sys_getpid(void); +extern int sys_kill(void); +extern int sys_link(void); +extern int sys_mkdir(void); +extern int sys_mknod(void); +extern int sys_open(void); +extern int sys_pipe(void); +extern int sys_read(void); +extern int sys_sbrk(void); +extern int sys_sleep(void); +extern int sys_unlink(void); +extern int sys_wait(void); +extern int sys_write(void); +extern int sys_uptime(void); + +extern __code cbc_read(__code(*)(int)); + + +static int (*syscalls[])(void) = { + [SYS_fork] =sys_fork, + [SYS_exit] =sys_exit, + [SYS_wait] =sys_wait, + [SYS_pipe] =sys_pipe, + [SYS_read] =sys_read, + [SYS_kill] =sys_kill, + [SYS_exec] =sys_exec, + [SYS_fstat] =sys_fstat, + [SYS_chdir] =sys_chdir, + [SYS_dup] =sys_dup, + [SYS_getpid] =sys_getpid, + [SYS_sbrk] =sys_sbrk, + [SYS_sleep] =sys_sleep, + [SYS_uptime] =sys_uptime, + [SYS_open] =sys_open, + [SYS_write] =sys_write, + [SYS_mknod] =sys_mknod, + [SYS_unlink] =sys_unlink, + [SYS_link] =sys_link, + [SYS_mkdir] =sys_mkdir, + [SYS_close] =sys_close, +}; + + +static __code (*cbccodes[])(__code (*)(int)) = { + [SYS_cbc_read] = cbc_read, +}; + + + +// ---- +// typedef struct SyscallDispatchImpl <Type, Isa> impl SyscallDispatch { +// __code next(....); +// } SyscallDispatchImpl; +// ---- + +SyscallDispatch* createSyscallDispatchImpl(struct Context* cbc_context) { + struct SyscallDispatch* syscall_dispatch = new SyscallDispatch(); + struct SyscallDispatchImpl* syscall_dispatch_impl = new SyscallDispatchImpl(); + syscall_dispatch->syscall_dispatch = (union Data*)syscall_dispatch_impl; + syscall_dispatch->dispatch = C_dispatchSyscallDispatchImpl; + return syscall_dispatch; +} + +__code dispatchSyscallDispatchImpl(struct SyscallDispatchImpl* syscall_dispatch, __code next(...)) { + KernelContext* kcontext = kernel_context; + kcontext->now_proc = proc; + proc->cbc_context.proc = proc; + + int num = proc->tf->r0; + + if (num == 5) + num = 22; + + struct KernelRet* kernelRet = createKernelRetImpl(cbc_context); + + if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) { + proc->cbc_arg.cbc_console_arg.num = num; + __code *syscalls = kcontext->syscalls; + + goto (cbccodes[num])(cbc_ret); + //goto meta(&proc->cbc_context, cbccodes[num]); + } -# read system call -- 現状の`__ncode`をそのままInterfaceのAPIにする - - とりあえず分割はしないでただInterfaceに乗せるだけにする \ No newline at end of file + if((num > 0) && (num < NELEM(syscalls)) && syscalls[num]) { + int ret = syscalls[num](); + + // in ARM, parameters to main (argc, argv) are passed in r0 and r1 + // do not set the return value if it is SYS_exec (the user program + // anyway does not expect us to return anything). + + goto kernelRet->cbc_return(ret); + + } + + cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); + goto kernelRet->cbc_return(-1); +} +``` + +# kernelRet + +- `swch`や`exit`などのアセンブラで記述されたやつのInterface + +```c +typedef struct KernelRet <Type, Impl> { + __code cbc_return(Impl* kernelRet, int ret, __code next(...)); + __code exit(Impl* kernelRet, __code next(...)); + __code swtch(Impl* kernelRet, __code next(...)); + __code next(....); +} KernelRet; +``` + +```c +typedef struct KernelRetImpl <Type, Isa> impl KernelRet { + __code next(....); +} KernelRetImpl; +``` + +```c +#include "types.h" +#include "arm.h" +#include "param.h" +#include "syscall.h" +#include "proc.h" +#interface "KernelRet.h" + +// ---- +// typedef struct KernelRetImpl <Type, Isa> impl KernelRet { +// __code next(....); +// } KernelRetImpl; +// ---- + +KernelRet* createKernelRetImpl(struct Context* cbc_context) { + struct KernelRet* kernelRet = new KernelRet(); + struct KernelRetImpl* kernelRet_impl = new KernelRetImpl(); + kernelRet->kernelRet = (union Data*)kernelRet_impl; + kernelRet->cbc_return = C_cbc_returnKernelRetImpl; + kernelRet->exit = C_exitKernelRetImpl; + kernelRet->swtch = C_swtchKernelRetImpl; + return kernelRet; +} + +extern __code trapret(void); + +__code cbc_returnKernelRetImpl(struct KernelRetImpl* kernelRet, int ret, __code next(...)) { + int num = proc->cbc_arg.cbc_console_arg.num; + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + goto trapret(); +} + +extern __code exit(void); + + +__code exitKernelRetImpl(struct KernelRetImpl* kernelRet, __code next(...)) { + goto exit(); +} + +extern __code swtch(void); + +__code swtchKernelRetImpl(struct KernelRetImpl* kernelRet, __code next(...)) { + goto swtch(); +} + +``` + +# システムコールエントリ + +- `exec`だけもつInterface + - 番号の対応とかは事前にメタ計算で解決する + +``` +typedef struct SyscallEntry <Type, Impl> { + __code exec(Impl* syscall_entry, __code next(...)); + __code next(....); +} SyscallEntry; +``` + +- イメージ的にはこんな感じ? + +```c +#include "../context.h" +#interface "SyscallEntry.h" + +// ---- +// typedef struct ReadSyscallEntry <Type, Isa> impl SyscallEntry { +// __code next(....); +// } ReadSyscallEntry; +// ---- + +SyscallEntry* createReadSyscallEntry(struct Context* cbc_context) { + struct SyscallEntry* syscall_entry = new SyscallEntry(); + struct ReadSyscallEntry* read_syscall_entry = new ReadSyscallEntry(); + syscall_entry->syscall_entry = (union Data*)read_syscall_entry; + syscall_entry->exec = C_execReadSyscallEntry; + return syscall_entry; +} +__code execReadSyscallEntry(struct ReadSyscallEntry* syscall_entry, __code next(...)) { + + goto file_read(...); +} +``` + +# proc.cbc関連 + +- プロセス操作で既に`__ncode`になってる人々 + +``` +typedef struct CbCProc <Type, Impl> { + __code sched(Impl* cbc_proc, __code next(...)); + __code sleep(Impl* cbc_proc, struct spinlock* lk, __code next(...)); + __code sleep1(Impl* cbc_proc, __code next1(...)); + __code wakeup(Impl* cbc_proc, void* chan, __code next1(...)); + __code wakeup1(Impl* cbc_proc, void* chan, __code next(...)); + __code next(....); + __code next1(...); +} CbCProc; +``` + +- 実装を書いたので動かしてみる + - 大域変数なプロセステーブル(`ptable`)をとりあえずヘッダファイルにして`proc.cbc`と共有した + +```c +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "arm.h" +#include "proc.h" +#include "spinlock.h" +#include "ptable.h" + +#include "kernel.h" + +#interface "CbCProc.h" + +// ---- +// typedef struct CbCProcImpl <Type, Isa> impl CbCProc { +// __code next(....); +// } CbCProcImpl; +// ---- + +CbCProc* createCbCProcImpl(struct Context* cbc_context) { + struct CbCProc* cbc_proc = new CbCProc(); + struct CbCProcImpl* cb_c_proc_impl = new CbCProcImpl(); + cbc_proc->cbc_proc = (union Data*)cb_c_proc_impl; + cbc_proc->sched = C_schedCbCProcImpl; + cbc_proc->sleep = C_sleepCbCProcImpl; + cbc_proc->sleep1 = C_sleep1CbCProcImpl; + cbc_proc->wakeup = C_wakeupCbCProcImpl; + cbc_proc->wakeup1 = C_wakeup1CbCProcImpl; + return cbc_proc; +} + +__code schedCbCProcImpl(struct CbCProcImpl* cbc_proc, __code next(...)) { + int intena; + + if(!holding(&ptable.lock)) { + panic("sched ptable.lock"); + } + + if(cpu->ncli != 1) { + panic("sched locks"); + } + + if(proc->state == RUNNING) { + panic("sched running"); + } + + if(int_enabled ()) { + panic("sched interruptible"); + } + + intena = cpu->intena; + swtch(&proc->context, cpu->scheduler); + cpu->intena = intena; + + goto next(...); +} + +__code sleepCbCProcImpl(struct CbCProcImpl* cbc_proc, void* chan, struct spinlock* lk, __code next(...)) { + //show_callstk("sleep"); + + if(proc == 0) { + panic("sleep"); + } + + if(lk == 0) { + panic("sleep without lk"); + } + + if(lk != &ptable.lock){ //DOC: sleeplock0 + acquire(&ptable.lock); //DOC: sleeplock1 + release(lk); + } + proc->chan = chan; + proc->state = SLEEPING; + proc->lk = lk; + + goto schedCbCProcImpl(cbc_sleep1); +} + +__code sleepCbCProcImpl_stub(struct Context* cbc_context) { + CbCProcImpl* cbc_proc = (CbCProcImpl*)GearImpl(cbc_context, CbCProc, cbc_proc); + struct spinlock* lk = Gearef(cbc_context, CbCProc)->lk; + void* chan = Gearef(cbc_context, CbCProc)->chan; + enum Code next = Gearef(cbc_context, CbCProc)->next; + goto sleepCbCProcImpl(cbc_context, cbc_proc, chan, lk, next); +} + + +__code sleep1CbCProcImpl(struct CbCProcImpl* cbc_proc, __code next1(...)) { + struct spinlock *lk = proc->lk; + // Tidy up. + proc->chan = 0; + + // Reacquire original lock. + if(lk != &ptable.lock){ //DOC: sleeplock2 + release(&ptable.lock); + acquire(lk); + } + + goto next1(...); +} + +__code wakeupCbCProcImpl(struct CbCProcImpl* cbc_proc, void* chan, __code next1(...)) { + acquire(&ptable.lock); + goto wakeup1CbCProcImpl(chan); +} + +__code wakeup1CbCProcImpl(struct CbCProcImpl* cbc_proc, void* chan, __code next(...)) { + struct proc *p; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { + if(p->state == SLEEPING && p->chan == chan) { + p->state = RUNNABLE; + } + } + + release(&ptable.lock); + goto next(...); +} +``` + +# 現状 + +- スタックフレームがおかしい +- interfaceに無い構造体を引数で保つ場合はstubを手書きしないと型エラー + - `struct`が`generate_stub`で`Gearef`の左辺から落とされる + +## スタックフレームがおかしい + +### 通常のsyscall (関数呼び出し->goto meta) + +``` +(gdb) bt +#0 cbc_returnKernelRetImpl_stub (cbc_context=0x87ffd000) at /mnt/dalmore-home/one/build/cbcxv6/CMakeFiles/kernel.dir/c/impl/KernelRetImpl.c:37 +#1 0x80033d3c in trap_swi () at /mnt/dalmore-home/one/src/cbcxv6/src/trap_asm.S:30 +#2 0x00000000 in ?? () +``` + +### read + +``` +(gdb) bt +#0 cbc_ret (ret=1) at /mnt/dalmore-home/one/build/cbcxv6/CMakeFiles/kernel.dir/c/syscall.c:170 +#1 0x80023764 in cbc_read (next=0x800231b4 <cbc_ret>) at /mnt/dalmore-home/one/build/cbcxv6/CMakeFiles/kernel.dir/c/sysfile.c:88 +#2 0x80033d3c in trap_swi () at /mnt/dalmore-home/one/src/cbcxv6/src/trap_asm.S:30 +#3 0x000019dc in ?? () +Backtrace stopped: previous frame identical to this frame (corrupt stack?) +(gdb) up +``` + +readの場合は余計なスタックが乗っていて駄目 +- `goto meta`に統一させれば`tail call`になりそうなので、`read`のInterface化を目指す + +## 構造体の問題 +- この場合`spinlock`は`typedef`してないので`struct`つけないといけないけど外される + - 全部typedefすれば良いのだけど... + + +``` +__code sleepCbCProcImpl_stub(struct Context* cbc_context) { + CbCProcImpl* cbc_proc = (CbCProcImpl*)GearImpl(cbc_context, CbCProc, cbc_proc); + struct spinlock* lk = Gearef(cbc_context, CbCProc)->lk; + void* chan = Gearef(cbc_context, CbCProc)->chan; + enum Code next = Gearef(cbc_context, CbCProc)->next; + goto sleepCbCProcImpl(cbc_context, cbc_proc, chan, lk, next); +} +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/07/14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/07/14.md Wed Dec 16 15:11:16 2020 +0900 @@ -14,15 +14,47 @@ - わりと忘れている..... - xv6の書き換え作業 - シス管関連 + - テスト用ldap環境をDockerでつくっていた + - gitlabのプロキシ関連 + - NetlifyCMSが使えるように! +- ~~インターネットの人に煽られて~~ Scala(akka)とHaskellやってます # CbC勉強会 - Gearsをざっと勉強した - 入門記事をいくつか書いてるので興味があれば見てみてください - https://growi.cr.ie.u-ryukyu.ac.jp/Gears/introduction + - https://growi.cr.ie.u-ryukyu.ac.jp/Gears/introduction/parallel_execution +- `par goto`関連は勉強したい + +# Raku +- だいぶ忘れている... +- 教科書を読んだり、自分の同人誌とかにまとめてたほうを見て感覚を思い出している + - 次勉強会をするとだいぶ勘が戻りそう +- 最新バージョンは`2020.06` + - https://github.com/rakudo/rakudo/tags +- 最近はプログラマから触れるASTの開発(RubyのIseq的なもの)の開発や、コンパイル時にビルドされるマクロの開発がされてるらしい + - https://www.youtube.com/watch?v=91uaaSyrKm0 + - https://www.jnthn.net/papers/2020-cic-rakuast.pdf # xv6の書き換え - `cbc_read`でスタックが積まれていた - `bl`命令に変換されてる..... + - `bl`はサブルーチンコールと対応していて、`ret`しないといけなくなってしまう +## 対応するコード + +```c +__ncode cbc_read(__code (*next)(int ret)){ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { + goto next(-1); + } + goto cbc_fileread(f, p, n, next); +} +``` +## デバッグ結果 ``` 11 LDR r1, =edata_entry @@ -61,4 +93,286 @@ #1 0x800344f0 in trap_swi () at /mnt/dalmore-home/one/src/cbcxv6/src/trap_asm.S:30 #2 0x000019dc in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?) -``` \ No newline at end of file +``` + +- コンパイラのバグっぽい気もするけれど、追求するべきかは悩む(それよりInterface化したい) + + +## Interface化 + +- readをitnerface化中 + - とりあえずコピってくるとこは終わった + - `goto next`するときの引数を`KernelRet`interfaceに書き込む必要がある + - アセンブラの`ret`を呼び出すinterface + - `next`の値は自分自身のinterfaceに呼び出されてしまう +- `next`の引数はアノテーション的なものか記法で解決したい + +```c + goto next[KernelRet](ret,...); ....? + + @KernelRet + goto next(ret,...); +``` + +### interface化 +- 全部同じファイルにしたので絶対にこのままでは動かない + - グローバル変数はkernelのcontextに積みたい + - どこで積むかは別途考える(ヘッダファイル化する?) + +```c +#include "../context.h" +#interface "ReadSyscall.h" +#interface "KernelRet.h" + +// ---- +// typedef struct ReadSyscallImpl <Type, Isa> impl ReadSyscall { +// __code next(....); +// } ReadSyscallImpl; +// ---- + +ReadSyscall* createReadSyscallImpl(struct Context* cbc_context) { + struct ReadSyscall* read_syscall = new ReadSyscall(); + struct ReadSyscallImpl* read_syscall_impl = new ReadSyscallImpl(); + read_syscall->read_syscall = (union Data*)read_syscall_impl; + read_syscall->consoleread = C_consolereadReadSyscallImpl; + read_syscall->consoleread1 = C_consoleread1ReadSyscallImpl; + read_syscall->consoleread2 = C_consoleread2ReadSyscallImpl; + read_syscall->piperead = C_pipereadReadSyscallImpl; + read_syscall->piperead1 = C_piperead1ReadSyscallImpl; + read_syscall->piperead2 = C_piperead2ReadSyscallImpl; + read_syscall->piperead3 = C_piperead3ReadSyscallImpl; + read_syscall->fileread = C_filereadReadSyscallImpl; + read_syscall->fileread1 = C_fileread1ReadSyscallImpl; + return read_syscall; +} + +__code consolereadReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct inode* ip, char* dst, int n, __code next(int ret, ...)) { + uint target; + + iunlock(ip); + + //target = n; + acquire(&input.lock); + + if (n > 0) { + goto read_syscall->consoleread2(...); + } + + goto read_syscall->consoleread1(...); +} + +__code consoleread1ReadSyscallImpl(struct ReadSyscallImpl* read_syscall,int n, int target, char* dst, struct inode* ip, __code next(...)) { + int cont = 1; + int c = input.buf[input.r++ % INPUT_BUF]; + + if (c == C('D')) { // EOF + if (n < target) { + // Save ^D for next time, to make sure + // caller gets a 0-byte result. + input.r--; + } + cont = 0; + } + + *dst++ = c; + --n; + + if (c == '\n') { + cont = 0; + } + + if (cont == 1) { + if (n > 0) { + goto cbc_sleep(&input.r, &input.lock, read_syscall->consoleread2); + } + } + + release(&input.lock); + ilock(ip); + goto next(target - n); +} + +__code consoleread2ReadSyscallImpl(struct ReadSyscallImpl* read_syscall,struct inode* ip, __code next(...)) { + if (input.r == input.w) { + if (proc->killed) { + release(&input.lock); + ilock(ip); + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(-1); + } + goto cbc_sleep(&input.r, &input.lock, cbc_consoleread2); + } + goto read_sycall->consoleread1(); +} + +__code pipereadReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct pipe* p,char* addr, int n, __code next(int ret,...)) { + + goto next(ret,...); +} + +__code piperead1ReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct pipe* p, __code next(int ret,...)) { + if (p->nread == p->nwrite && p->writeopen){ + if(proc->killed){ + release(&p->lock); + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(-1); + } + goto cbc_sleep(&p->nread, &p->lock, cbc_piperead1); + } + goto read_syscall->piperead2(...); +} + +__code piperead2ReadSyscallImpl(struct ReadSyscallImpl* read_syscall, int i, int n, struct pipe* p, char* addr, __code next(...)) { + if (i < n && !(p->nread == p->nwrite)) { + addr[i] = p->data[p->nread++ % PIPESIZE]; + i ++; + goto read_syscall->piperead2(i,n, p, addr,next); + } + //proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_wakeup(&p->nwrite, cbc_piperead3); //DOC: piperead-wakeup +} + +__code piperead3ReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct pipe* p, int i, __code next(int ret,...)) { + release(&p->lock); + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(-1); +} + +__code filereadReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct file* f, char* addr, int n, __code next(int ret, ...)) { + if (f->readable == 0) { + ret = -1; + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(ret); + } + + if (f->type == FD_PIPE) { + goto read_syscall->piperead(f->pipe, addr, n, next); + } + + if (f->type == FD_INODE) { + ilock(f->ip); + goto read_syscall->cbc_readi(f->ip, addr, f->off, n, readsys_call->fileread1); + } + + goto cbc_panic("fileread"); +} + +__code fileread1ReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct file* f, int ret, __code next(ret, ...)) { + if (ret > 0) + f->off += ret; + iunlock(f->ip); + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(ret); +} + +``` + +## panic + +- 全部Interface化するならこのあたりも必要 + +```c +__ncode cbc_panic (char *s) +{ + cli(); + + cons.locking = 0; + + cprintf("cpu%d: panic: ", cpu->id); + + show_callstk(s); + panicked = 1; // freeze other CPU + + while (1) + ; +} +``` + + +`panicked`はファイル内のグローバル変数 +- `kernel_context`とアドレスを共有する + +### interface化 +- 先月書いてたらしい + +```c +typedef struct Err <Type, Impl> { + __code error(Impl* err, int err_code, __code next(...)); + __code panic(Impl* err, char* msg); + __code next(...); +} Err; +``` + +```c +typedef struct KernelError <Type, Isa> impl Err { + __code infinity_loop(Type* err, __code next(...)); + __code next(...); +} KernelError; +``` + +```c +#include "param.h" +#include "proc.h" +#interface "Err.h" + +// ---- +// typedef struct KernelError <Type, Isa> impl Error { +// __code infinity_loop(Type* error, next(...)); +// } KernelError; +// ---- + +Err* createKernelError(struct Context* cbc_context) { + struct Err* err = new Err(); + struct KernelError* kernel_error = new KernelError(); + err->err = (union Data*)kernel_error; + kernel_error->err = (union Data*)kernel_error; + kernel_error->infinity_loop = C_infinity_loopKernelError; + err->error = C_errorKernelError; + err->panic = C_panicKernelError; + return err; +} + +__code infinity_loopKernelError(struct KernelError* err, __code next(...)) { + goto next(...); +} + +__code errorKernelError(struct KernelError* err, int err_code, __code next(...)) { + + goto next(...); +} + +__code panicKernelError(struct KernelError* err, char* msg) { + cli(); + cons.locking = 0; + + cprintf("cpu%d: panic: ", cpu->id); + + show_callstk(msg); + panicked = 1; // freeze other CPU + + goto infinity_loopKernelError(err, err->inifinity_loop); +} +``` + +# シス管関連 + +- 詳しくは明日... + +## LDAP + +- さまざまなアプリケーションを実装する時にLDAPがネック + - 大学でLDAP本番環境に接続するという方法もあるが..... + +- akatsukiのリプレイスもあるので実装したい + - akatsukiの時に使っていたDockerfileは使えない + - 残念ながらyumからOpenLDAPが削除されている + - ubuntuでopenldapをapt getすると対話型のTUIが起動されて辛く厳しい +- https://github.com/osixia/docker-openldap + - 起動するとこまではいけたけれど、LDAPツリーが意図していたものと異なる + - その上seedでいれたldifが反映されない..... + +## gitlab +- apache -> nginx -> gitlabの地獄みたいなプロキシリレーを解消 + - https://anatofuz.hatenablog.com/entry/2020/07/14/115853 +- その結果NetlifyCMSが動かせるように!!! + - 明日のシス管来てくれ!!!
--- a/user/anatofuz/note/2020/07/21.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/07/21.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,193 @@ + +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する + + + +# 今週 +- Rustで遊んでいた +- Gearsでnextした後に呼び出し元のInterfaceからの値の取り出しを考えていた +- xv6の書き換え +- シス管関連 + + +# Rust + +- シグナルで死んだら音声を再生するCLIを作ってた + - パターンマッチ便利ですね + +```rust +use std::env; +use std::path::{Path, PathBuf}; +use structopt::StructOpt; +use std::process::Command; + + +/// Search for a pattern in a file and display the lines that contain it. +#[derive(StructOpt)] +struct Cli { + /// The path to the file to read + cmd: String +} + +#[derive(Debug)] +struct CustomError(String); + +fn main() { + let args = Cli::from_args(); + let status = Command::new(args.cmd).status().expect("failed to execute process"); + + + match status.code() { + Some(value) => return, + None => pien(), + } +} + +fn pien() { + let mut path = env::home_dir().unwrap(); + path.push(".pien.mp3"); + Command::new("afplay").arg(path).status().expect("failed to execute process"); +} +``` + +# xv6 + +## 変換スクリプト関連の微調整 +- ヘッダから`.cbc`を生成するやつとか + +## 引数をそのまま出力するケースがうまくパース出来なかったので修正 +- あんまいい書き方ではないとは思うのでやった意味があるのかは不明 + +```c +__code fileread1ReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct file* f, int ret, __code next(ret, ...)) { + if (ret > 0) + f->off += ret; + iunlock(f->ip); + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(ret); +} + +``` + +## `console.cbc`で使われているグローバル変数をkernel_contextに移動 + +```c +int panicked = 0; + +struct { + struct spinlock lock; + int locking; +} cons; +``` + +- kernel_context + +```c +#include "spinlock.h" +struct cons_arg { + struct spinlock lock; + int locking; +}; +typedef struct cons_arg cons_arg; + +typedef struct KernelContext { + struct Context context; + __code (*syscalls[10]) (void); + struct Context* proc_contexts[NPROC]; + struct proc* now_proc; + int panicked; + struct cons_arg cons_arg; +} KernelContext; +``` + +### console.cbc + +- 使うタイミングでkernelから取ってくる世界観 + +#### Before + +```c +void panic (char *s) +{ + cli(); + + cons.locking = 0; + + cprintf("cpu%d: panic: ", cpu->id); + + show_callstk(s); + panicked = 1; // freeze other CPU + + while (1) + ; +} +``` + +#### After + +```c +void panic (char *s) +{ + cli(); + + struct cons_arg* cons = &kernel_context->cons_arg; + cons->locking = 0; + + cprintf("cpu%d: panic: ", cpu->id); + + show_callstk(s); + int* panicked = &kernel_context->panicked; + *panicked = 1; // freeze other CPU + + while (1) + ; +} +``` + + +## kernel_context専用の初期化関数 + +- あとでもりもり増えると信じている + +```c +#include "context.h" + +void initKernelContext(struct KernelContext* kernel_context) { + kernel_context->panicked = 0; +} +``` + + + + +# Gears + + +## localCodeの問題 + +- 自分が開いている`.cbc`の中で定義されているかどうかの判定 + - `%localCode`に設定されていたらローカルなCodeGear + +- こういう例でうまく動かないことが発覚した + +```c +__code cg1() { + goto cg2(); +} +__code cg2() { + goto cg3(); +} +``` + +- `goto cg2()`が`meta`に変換される + - 理由はこんな感じだった + + ```perl +dalmore+one (cd /mnt/dalmore-home/one/build/cbcxv6//CMakeFiles/kernel.dir ; perl -d /mnt/dalmore-home/one/src/cbcxv6/src/gearsTools/generate_stub.pl --project xv6 /mnt/dalmore-home/one/src/cbcxv6/src/impl/ReadSyscallImpl.cbc) @@ -29,4 +219,172 @@ }; DB<5> -``` \ No newline at end of file +``` + +- `%localCode`への値の追加は`.c`を生成するタイミングで行われるので、`__code`が出てきたタイミングに左右されていた + +- とりあえず最初に全件走査して`%localCode`を生成するようにした + +```perl +for my $fn (@ARGV) { + next if ($fn !~ /\.cbc$/); + my $local_code_ref = get_local_code_at_first($fn); + &getDataGear($fn); + &generateDataGear($fn, $local_code_ref); +} + +sub get_local_code_at_first { + my ($filename) = @_; + + open my $fh, '<', $filename; + my %localCode; + while (my $line = <$fh>) { + if ($line =~ /extern\s+_\_code\s+(\w+)\((.*)\)/) { + $localCode{$1} = 1; + } elsif ($line =~ /^\s\s*_\_code\s+(\w+)\((.*)\)(.*)/) { + $localCode{$1} = 1; + } elsif ($line =~ /^\s\s*_\_code *\(\s*\*\s*(\w+)\)\((.*)\)(.*)/) { + $localCode{$1} = 1; + } + } + close $fh; + return \%localCode; +} + +``` + +- この先頭の空白ってどういう意味があったのかよく解ってない + +```perl + if ($line =~ /extern\s+_\_code\s+(\w+)\((.*)\)/) { + $localCode{$1} = 1; + } elsif ($line =~ /^\s\s*_\_code\s+(\w+)\((.*)\)(.*)/) { + $localCode{$1} = 1; + } elsif ($line =~ /^\s\s*_\_code *\(\s*\*\s*(\w+)\)\((.*)\)(.*)/) { + $localCode{$1} = 1; + } +``` + +## goto metaの抑制 + +- `goto meta`させたい時とそうじゃない場合のかき分けが難しい + - さっきの方法でやると全部`goto meta`しないバージョンになってしまう + - `goto meta`させたい場合 + - `instance->codegear()`の呼び出し方で統一? + - gotoする場合は基本的に`goto meta`に統一する? +- 直接`goto`したいときは`gotodirect`を使う...? + +```c +__code consolereadReadSyscallImpl(struct ReadSyscallImpl* read_syscall, struct inode* ip, char* dst, int n, __code next(int ret, ...)) { + uint target; + + iunlock(ip); + + //target = n; + acquire(&input.lock); + + if (n > 0) { + gotodirect consoleread2ReadSyscallImpl(...); + } + + goto read_syscall->consoleread1(...); +} +``` +- この場合は現状`(...)`に該当するものは明示的に書く必要がある + - Interfaceから値を取り出すのが面倒というとこはありそう + + + +# nextで値を書き込む/取り出す方法 + +- interfaceの実装->別のinterface(既に決定しているパターン) +- interface -> interfaceで無いCodeGear + +## いままで + +- 頑張ってstubを手で書く + +```c +__code insertCase1(struct RedBlackTree* tree, struct Node *parent, struct Node *grandparent) { + if (parent != NULL) { + tree->parent = parent; + tree->grandparent = grandparent; + goto insertCase2(tree); + } + tree->root->color = Black; + goto stackClear(); +} + +__code insertCase1_stub(struct Context* context) { + goto insertCase1(context, + &Gearef(context, Tree)->tree->Tree.tree->RedBlackTree, + &context->data[D_Stack]->Stack.data->Node, + &context->data[D_Stack]->Stack.data1->Node); +} +``` + +## interface -> interface + +- interfaceの実装にderivingをつけると呼び出し先のinterfaceのimplに対応したstubを自動生成する + - 名前はあんまよくなさそう(型instanceではない....) + - この場合`呼び出し元のCodeGear*呼び出し先のCodeGear`に対応するCodeGearを生成する + +```c +typedef struct SingleLinkedStack<Type, Isa> impl Stack { +#deriving Show RedBlackTree + struct Element* top; +} SingleLinkedStack; +``` + +```c +__code popSingleLinkedStackToShowCodeGear1() { +} +``` + +## 他の方法 + +- 出力用の構造体を用意してフラグによってmetaで切り替える + +```c +type OutputTmpArg { + int argument_sum; + union Data* arg1; + union Data* arg2; +} OutputTmpArg; + +__code meta(struct Context* context) { + if (Gearef(context, OutputTmpArg)->argument_sum > 0 ) { + goto write_arg(); + } + goto context->code[]; +} +``` + +- もはや出力は全部DataGearにして、beforeのDataGearの番号で出力があるかどうかを判定する + - Interfaceへの代入は同じ変数名というルールでやる? + - いずれにせよ対応するstubを生成したい気がする + - Cで動かしながら自動生成できれば気持ちよさそうだけれど..... + +```c +__code output1(struct cotnext* context, __code next(int ret, char* msg, __code next(...)) { +} + +type output1Output { + int ret; + char* msg; +} + + +__code meta() { + if (args[cotnext->before] > 0 ) { + ... + } +} +``` + + +# 変換スクリプトまわり +- generate_stubとgenerate_contextでパースした結果を一時ファイルにして使いたい気がする + - 全件走査が行われるのは`generate_context`だけなので、ちょっとめんどくさい事が多い + - `generate_stub`で発見されたInterfaceなどを書き出したい + - っていうか予め`MANIFEST`みたいな設定ファイルみたいなのを置いておくのが良い気がしてきた \ No newline at end of file
--- a/user/anatofuz/note/2020/07/28.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/07/28.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,32 +1,270 @@ -# DataGear +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する + + +# 今週 +- 対島を救っていました +- UTMのアップデートに伴うssh関連の問題の解決 +- 学サポ関連 + - B3にRoRを教えたり + - 留学生相手にpythonを教えたりしました + - 留学生相手たいへん..... +- xv6の書き換え + +# UTMの問題 +- 詳しくは明日のシス管で +- 次期システムの更新関係でUTMのメジャーバージョンをあげた + - 涙がでるほどありがたい(~~いらんことする~~)機能がいくつか追加された +- SSLインスペクション + - Fortigate6系(今回あげたとこ)近辺から導入された脆弱性の対応 + - 最近の通信はhttps,sshで暗号化されているので通常はUTMは中身が見れない + - やらかしている通信が来た場合遮断したいので**UTMが暗号を解読して、最暗号化する**しくみ + - この最暗号化をssh時にやろうとしていて、鍵認証できない問題 + - いろいろありsshは中身をみないようにして解決した + +# kernel goto + +Gearsで`goto hoge(arg1)`すると、変換されるmetaは`goto meta(context, arg1)`となる +- xv6の場合は`goto meta(cbc_context, arg1)` + +kernel_cotnextの情報を使ってgotoしようとする場合に現状だと制御出来なかった +- `kernel goto`構文を追加 +- `kernel goto hoge(arg1)`とすると第一引数が`kernel_cotnext`に変換される +- generate_stubで`goto`の前の文字列もキャプチャしていたのでここに手を加えた -context.hにある構造体が登録される仕組み +```perl + } elsif (/^(.*)goto (\w+)\((.*)\);/) { + # handling goto statement + # convert it to the meta call form with two arugments, that is context and enum Code + my $prev = $1; + my $next = $2; + my @args = split(/,/, $3); + my $v = 0; + my $arg_context = $context_name; + if ($prev =~ /kernel/) { + $prev = ""; + $arg_context = "kernel_context"; + } + + if (exists $filename2localCodes{$filename}->{$next}) { + print $fd $_; next; + } + for my $n ( @{$dataGearVar{$codeGearName}} ) { + # continuation arguments + $v = 1 if ( $n eq $next); + } + if ($v || defined $code{$interface}->{$next}) { + # write continuation's arguments into the interface arguments + # we may need a commit for a shared DataGear + for my $arg ( @{$outputArgs{$codeGearName}->{$next}} ) { + my $v = shift(@args); + print $fd "\t*O_$arg = $v;\n"; + } + if ($hasParGoto) { + print $fd "${prev}Gearef(${arg_context}, TaskManager)->taskList = ${arg_context}->taskList;\n"; + print $fd "${prev}Gearef(${arg_context}, TaskManager)->next1 = C_$next;\n"; + print $fd "${prev}goto meta(${arg_context}, C_$next);\n"; + } else { + print $fd "${prev}${arg_context}->before = C_$codeGearName;\n"; + print $fd "${prev}goto meta(${arg_context}, $next);\n"; + } + next; + } + if ($hasParGoto) { + print $fd "${prev}Gearef(${arg_context}, TaskManager)->taskList = ${arg_context}\->taskList;\n"; + print $fd "${prev}Gearef(${arg_context}, TaskManager)->next1 = C_$next;\n"; + print $fd "${prev}goto parGotoMeta(${arg_context}, C_$next);\n"; + next; + } elsif ($next eq "meta") { + +``` + +# localCode + +- 先週のコードが汚かったので書き直した.... + - とりあえず最初にファイルごとにlocalCodeを数え上げる方式に変更 ```perl - open my $cx,"<","context.h" or die("can't open context.h $!"); - my $inUnionData = 0; - while (<$cx>) { - if (! $inUnionData) { - if ( /^union Data/) { - $inUnionData = 1; - } - next; - } - last if (/union Data end/); - if (/struct (\w+) \{/) { - $dataGear{$1} = 'struct'; - } elsif (/^\s{4}(\w+) (\w+);/) { # primitive type - my $vtype = $1; - my $vname = $2; - if (exists $dataGear{$vname}) { - next; - } - $dataGear{$vtype} = 'primitive'; - } - $dataGear{"Context"} = "struct"; + +# +# goto nodeStack->push((union Data*)node, stackTest3); +# +# generated meta level code +# +# Gearef(context, Stack)->stack = (union Data*)nodeStack; +# Gearef(context, Stack)->data = (union Data*)node; +# Gearef(context, Stack)->next = C_stackTest3; +# goto meta(context, nodeStack->push); + +sub getDataGear { + my ($filename) = @_; + + setFilename2CodeGear($filename); + + my ($codeGearName, $name, $inTypedef,$described_data_gear); + open my $fd,"<",$filename or die("can't open $filename $!"); + while (<$fd>) { + if (! $inTypedef) { + if (/^typedef struct (\w+)\s*<(.*)>/) { + $inTypedef = 1; + + +... + +# create localCode from each cbc files +sub setFilename2CodeGear { + my ($filename) = @_; + open my $fh, '<', $filename; + while (my $line = <$fh>) { + if ($line =~ /extern\s+_\_code\s+(\w+)\((.*)\)/) { + $filename2localCodes{$filename}->{$1} = 1; + } elsif ($line =~ /^\s*_\_code\s+(\w+)\((.*)\)(.*)/) { + $filename2localCodes{$filename}->{$1} = 1; + } elsif ($line =~ /^\s*_\_code *\(\s*\*\s*(\w+)\)\((.*)\)(.*)/) { + $filename2localCodes{$filename}->{$1} = 1; + } elsif ($line =~ /^\_\_code (\w+)\((.*)\)(.*)/) { + $filename2localCodes{$filename}->{$1} = 1; } + } + close $fh; +} ``` -- デフォルトだとenumの番号で制御されている - - 今のところは型名1つだけ - - もう少し拡張性がほしい気がする \ No newline at end of file +# vm関係 +- 全部goto metaになる前提で書いてたのでうまく動かない + - そもそも1つしか動かしてなかったので思い切ってオミット + +proc.cbc + +```diff +-#interface "vm.h" + + #include "kernel.h" + +@@ -122,21 +121,6 @@ + //PAGEBREAK: 32 + // hand-craft the first user process. We link initcode.S into the kernel + // as a binary, the linker will generate __binary_initcode_start/_size +-void cbc_init_vmm_dummy(struct Context* cbc_context, struct proc* p, pde_t* pgdir, char* init, uint sz) +-{ +- // inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); +- +- struct vm* vm = createvm_impl(cbc_context); +- // goto vm->init_vmm(vm, pgdir, init, sz , vm->void_ret); +- Gearef(cbc_context, vm)->vm = (union Data*) vm; +- Gearef(cbc_context, vm)->pgdir = pgdir; +- Gearef(cbc_context, vm)->init = init; +- Gearef(cbc_context, vm)->sz = sz ; +- Gearef(cbc_context, vm)->next = C_vm_void_ret ; +- goto meta(cbc_context, vm->init_inituvm); +-} +- +- + + + void userinit(void) +@@ -154,7 +138,7 @@ + panic("userinit: out of memory?"); + } + +- cbc_init_vmm_dummy(&p->cbc_context, p, p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); ++ inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + + p->sz = PTE_SZ; + +@@ -177,15 +161,6 @@ + } +``` + + +# console.cbc + +- グローバル変数を追放 + - kernel_contextに移動 +- 呼び出すときに取ってくる方式 + +```diff +-#define INPUT_BUF 512 +-struct { +- struct spinlock lock; +- char buf[INPUT_BUF]; +- uint r; // Read index +- uint w; // Write index +- uint e; // Edit index +-} input; + + #define C(x) ((x)-'@') // Control-x + void consoleintr (int (*getc) (void)) + { + int c; ++ struct InputStruct* input_struct = getInputStruct(kernel_context); + +- acquire(&input.lock); ++ acquire(&input->lock); + + while ((c = getc()) >= 0) { + switch (c) { +@@ -201,8 +194,8 @@ + break; + + case C('U'): // Kill line. +- while ((input.e != input.w) && (input.buf[(input.e - 1) % INPUT_BUF] != '\n')) { +- input.e--; ++ while ((input->e != input->w) && (input->buf[(input->e - 1) % INPUT_BUF] != '\n')) { ++ input->e--; + consputc(BACKSPACE); + } + +``` + +InputStruct.h + +```c ++dalmore+one cat data_gear/InputStruct.h +typedef struct input_struct { + #define INPUT_BUF 512 + struct spinlock lock; + char buf[INPUT_BUF]; + uint r; // Read index + uint w; // Write index + uint e; // Edit index +} input_struct; +``` + +kernel_contextの初期化時にdataにアロケートする + +```c +#include "context.h" + +void initKernelContext(struct KernelContext* kernel_context) { + kernel_context->panicked = 0; + struct InputStruct* input_struct = ALLOC_DATA(kernel_context->conterxt, InputStruct)->InputStruct; +} + +struct InputStruct* getInputStruct(struct KernelContext* kernel_context) { + struct InputStruct* input_struct = kernel_context->context->data[D_KernelContext]->InputStruct; + return input_struct; +} +``` + +## 悩みどころ + +- これらkernel_contextに置いているDataGearを必要とするCodeGearはプロセスごとのcontextを使う前提のCodeGearになっている +- CodeGearがstubで取り出してくる先のDataGearをプロセスのcontextとkernel_contextの2種類存在してしまう + - なにかkernel_contextから値を取ってくるようなAPIがほしい気がする + - 変数名にkが先頭がつくとkernelから持ってくる + - アノテーション... +- この前interfaceのパーサーを書いたときに、`__code`の引数はすべてitnerfaceにあるという前提で書いてしまった + - 別のDataGearを持ってくる処理が現状書きづらいのでパーサー直したい + +# AbyssServer +- Rakuの`IO::Socket::INET`がunix domain socketを使えるとか主張している + - とはいえunix domain socketを使った例題が一切ネットに無いので真偽不明 + - とりあえずポート番号の代わりにパスを書けばいいのかと思い実装したがだめだった.... + - ライブラリの実装読む必要ありそう + +
--- a/user/anatofuz/note/2020/08/04.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/08/04.md Wed Dec 16 15:11:16 2020 +0900 @@ -16,4 +16,160 @@ - B1と一緒に作業したり - 障害復旧したり - 学科サイトからHTMLをgoroutineでダウンロードするくんを書いていたりした - \ No newline at end of file +- 今週はあまり対馬の民を救っていない + +# Lock +- kernel_contextの値を取る時に必要そう + - 計算に必要なタイミングでstubでkernel_cotnextから回収して、計算が終わったら書き戻す + - 書き戻す用のmetaが必要そう +- 想像図 + - lockが取れていたら実際に取り出したいstubにgoto + - ダメそうならwaitを再帰呼び出し +```c +__code consoleread2ReadSyscallImpl(struct ReadSyscallImpl* read_syscall,struct InputArg* input, struct inode* ip, __code next(...)) { + if (input->r == input->w) { + if (proc->killed) { + release(&input->lock); + ilock(ip); + KernelRet* kernel_ret = createKernelRetImpl(cbc_context); + goto kernel_ret->cbc_return(-1); + } + goto cbc_sleep(&input->r, &input->lock, cbc_consoleread2); + } + goto read_sycall->consoleread1(); +} + + +__code consoleread2ReadSyscallImpl_stub(struct Context* cbc_context) { + ReadSyscallImpl* read_syscall = (ReadSyscallImpl*)GearImpl(cbc_context, ReadSyscall, read_syscall); + inode* ip = Gearef(cbc_context, ReadSyscall)->ip; + enum Code next = Gearef(cbc_context, ReadSyscall)->next; + struct InputArg* input = GeareData(kernel_context, InputArg); + goto consoleread2ReadSyscallImpl(cbc_context, read_syscall, ip, next); +} + +__code consoleread2ReadSyscallImpl_wait_lock(struct Context* cbc_context) { + srtruct KernelContext* kcontext = &kernel_context; + goto semaphore->p(consoleread2ReadSyscallImpl); +} +``` + +- 従来のGears + - pthreadのAPIを使って実装されている + - xv6には当然そのまま移植できない + +```c +__code pOperationSemaphoreImpl(struct SemaphoreImpl* semaphore, __code next(...)) { + pthread_mutex_lock(&semaphore->mutex); + goto meta(context, C_pOperationSemaphoreImpl1); +} + +__code pOperationSemaphoreImpl1(struct SemaphoreImpl* semaphore, __code next(...)) { + if (semaphore->value == 0) { + pthread_cond_wait(&semaphore->cond, &semaphore->mutex); + goto meta(context, C_pOperationSemaphoreImpl1); + } + semaphore->value--; + pthread_mutex_unlock(&semaphore->mutex); + goto next(...); +} +``` + +- xv6で実装する場合 + - 我々にはspinlockがあるので... + - 似たようなlock機能を`kernel_context`向きに実装するのが早そう + - なのでxv6のspinlockの実装を眺めていた + +- ロックを獲得するacquire読んだけど`#if 0`でほとんど使われてなさそう + - どうも`#if 0`なのはx86向きのもとコードっぽい`xhcg`とか使ってるし..... + +```c +// Acquire the lock. +// Loops (spins) until the lock is acquired. +// Holding a lock for a long time may cause +// other CPUs to waste time spinning to acquire it. +void acquire(struct spinlock *lk) +{ + pushcli(); // disable interrupts to avoid deadlock. + lk->locked = 1; // set the lock status to make the kernel happy + +#if 0 + if(holding(lk)) + panic("acquire"); + + // The xchg is atomic. + // It also serializes, so that reads after acquire are not + // reordered before it. + while(xchg(&lk->locked, 1) != 0) + ; + + // Record info about lock acquisition for debugging. + lk->cpu = cpu; + getcallerpcs(get_fp(), lk->pcs); + +#endif +} +``` + +- 呼ばれているpush/pop cli + - みたところ`int_enabled`を読んだあとに`cli`する世界 + - `cpu->ncli`は`pushcli`のネストということらしい +- `intena`はinterrupt enableの略っぽい + +```c +// Pushcli/popcli are like cli/sti except that they are matched: +// it takes two popcli to undo two pushcli. Also, if interrupts +// are off, then pushcli, popcli leaves them off. + +void pushcli (void) +{ + int enabled; + + enabled = int_enabled(); + + cli(); + + if (cpu->ncli++ == 0) { // == cpu->nli == 0; cpu->nlic++ + cpu->intena = enabled; + } + + +} + +void popcli (void) +{ + if (int_enabled()) { + panic("popcli - interruptible"); + } + + if (--cpu->ncli < 0) { + cprintf("cpu (%d)->ncli: %d\n", cpu, cpu->ncli); + panic("popcli -- ncli < 0"); + } + + if ((cpu->ncli == 0) && cpu->intena) { + sti(); + } +} +``` + +```c +void cli (void) +{ + uint val; + + // ok, enable paging using read/modify/write + asm("MRS %[v], cpsr": [v]"=r" (val)::); + val |= DIS_INT; + asm("MSR cpsr_cxsf, %[v]": :[v]"r" (val):); +} +``` + +# 障害復旧 + +- 停電後の復電時に瞬電かなんかでL3スイッチの3つのうち1つが死ぬ + - 死んだL3に接続していた6Fのフロアスイッチ、6F研究室の多めのやつなどが死 +- 業者の方がいい感じに死んだL3スイッチに接続していたポートを残り2つに移動させていた + - ありがとうございます...... + - 明日新しいのがくるらしい + - https://anatofuz.hatenablog.com/entry/2020/08/03/212649 \ No newline at end of file
--- a/user/anatofuz/note/2020/08/11.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/08/11.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,10 +4,137 @@ - https://growi.cr.ie.u-ryukyu.ac.jp/user/anatofuz/note/2020/08/04 # 今週 +- 結膜炎です\(^o^)/ + - 視力低下を感じる - 学サポでB2,B3にJavaとPythonでデータ分析のやつを教える - 1日に4時間教えたりしてしんどい - シス管関連 - スイッチのconfigを解析するやつ等々 - そのた - [ARM勉強会](https://connpass.com/event/180812/)見てた - - [Tour of Rust](https://tourofrust.com/)に手を出す \ No newline at end of file + - [Tour of Rust](https://tourofrust.com/)に手を出す + +# gearsの例題 + +- localCode絡みの問題 + - revision 645だと動く +- 従来のGearsはこういう書き方が多い + +- main.cbc + - `goto`時の引数を省略する + - `meta`になる -> stubで値を取り出しているので今までは問題ない + +```c +__code initDataGears(struct LoopCounter* loopCounter, struct TaskManager* taskManager) { + // loopCounter->tree = createRedBlackTree(context); + loopCounter->i = 0; + taskManager->taskManager = (union Data*)createTaskManagerImpl(context, cpu_num, gpu_num, 0); + struct Timer* timer = Gearef(context, Timer); + goto code1(); +} + +__code code1(struct Timer* timer) { + printf("cpus:\t\t%d\n", cpu_num); + printf("gpus:\t\t%d\n", gpu_num); + printf("length:\t\t%d\n", length); + goto createTask1(); +} + +__code code2(struct TaskManager* taskManager) { + goto taskManager->shutdown(exit_code); +} + +__code code2_stub(struct Context* context) { + goto code2(context, &Gearef(context, TaskManager)->taskManager->TaskManager); +} +``` + + +- SynchronizedQueue + +```c +__code putSynchronizedQueue(struct SynchronizedQueue* queue, union Data* data, __code next(...)) { + Element* element = new Element(); + element->data = data; + element->next = NULL; + Element* last = queue->last; + Element* nextElement = last->next; + if (last != queue->last) { + goto putSynchronizedQueue(); + } + if (nextElement == NULL) { + struct Atomic* atomic = queue->atomic; + goto atomic->checkAndSet(&last->next, nextElement, element, next(...), putSynchronizedQueue); + } else { + struct Atomic* atomic = queue->atomic; + goto atomic->checkAndSet(&queue->last, last, nextElement, putSynchronizedQueue, putSynchronizedQueue); + } +} + +__code takeSynchronizedQueue(struct SynchronizedQueue* queue, __code next(union Data* data, ...)) { + struct Element* top = queue->top; + struct Element* last = queue->last; + struct Element* nextElement = top->next; + if (top != queue->top) { + goto takeSynchronizedQueue(); + } + if (top == last) { + if (nextElement != NULL) { + struct Atomic* atomic = queue->atomic; + goto atomic->checkAndSet(&queue->last, last, nextElement, takeSynchronizedQueue, takeSynchronizedQueue); + } + } else { + struct Atomic* atomic = queue->atomic; + goto atomic->checkAndSet(&queue->top, top, nextElement, takeSynchronizedQueue1, takeSynchronizedQueue); + } + goto takeSynchronizedQueue(); +} +``` + +## 一応治せるが... + +- コンパイル時にwarningが出まくる + - 型があってないと主張される...(コンパイラのバグ?) + - boundedbufferは引数を埋めた所、errorは出なくなったがセグフォ + +```sh +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c: In function 'initDataGears': +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c:21:10: warning: implicit declaration of function 'code1' [-Wimplicit-function-declaration] + 21 | goto code1(context, timer); + | ^~~~~ +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c: At top level: +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c:30:8: warning: conflicting types for 'code1' + 30 | __code code1(struct Context *context,struct Timer* timer) { + | ^~~~~ +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c:21:10: note: previous implicit declaration of 'code1' was here + 21 | goto code1(context, timer); + | ^~~~~ +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c: In function 'code1': +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c:34:10: warning: implicit declaration of function 'createTask1'; did you mean 'createTask1_stub'? [-Wimplicit-function-declaration] + 34 | goto createTask1(context, &GearImpl(context, TaskManager, taskManager)); + | ^~~~~~~~~~~ + | createTask1_stub +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c: At top level: +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c:53:8: warning: conflicting types for 'createTask1' + 53 | __code createTask1(struct Context *context,struct TaskManager* taskManager) { + | ^~~~~~~~~~~ +/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/c/examples/boundedBuffer/main.c:34:10: note: previous implicit declaration of 'createTask1' was here + 34 | goto createTask1(context, &GearImpl(context, TaskManager, taskManager)); + | ^~~~~~~~~~~ +``` + + +## 解決策 + +- `mata goto nextcodeGearName(...)`みたいにすると`goto meta`強制になる + - それ以外は`localCode`の挙動に準拠する +- このあたりはどうせPerlで変換するので変換ルールフォーマットファイルを定義するのもいいかもしれない +- metaに渡す情報は構造体で定義したい希ガスる + - どうやるかはなやみどころ(あんま最近やってない... + +```c +goto meta(context, arg[type => C_exampleXtake2_single_linked_stack, + InputData => struct exampleXtak2_sinle_linked_stack { }, + ]); + +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/08/18.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/08/18.md Wed Dec 16 15:11:16 2020 +0900 @@ -29,6 +29,42 @@ - generate_stub側の修正を頑張る - とりあえずparallelを優先にして、xv6はあとで +## クリティカルな問題 + +```c +__code pop2Test_StackTestImpl(struct StackTestImpl* stackTest, struct Stack* stack, __code next(...)) { + goto stack->pop2(pop2Test1_StackTestImpl); +} + +__code pop2Test3_StackTestImpl(struct StackTestImpl* stackTest, struct Stack* stack, __code next(...)) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + goto pop2Test1_StackTestImpl(stackTest, (union Data*)str, (union Data*)str1); +} + + +__code pop2Test1_StackTestImpl(struct StackTestImpl* stackTest, union Data* data, union Data* data1, struct Stack* stack, __code next(...)) { + String* str = (String*)data; + String* str2 = (String*)data1; + + printf("%d\n", str->size); + printf("%d\n", str2->size); + goto next(...); +} + +__code pop2Test1_StackTestImpl_stub(struct Context* context) { + struct StackTestImpl* stackTest = GearImpl(context, StackTest, stackTest); + Data* data = Gearef(context, Stack)->data; + Data* data1 = Gearef(context, Stack)->data1; + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2Test1_StackTestImpl(context, stackTest, data, data1, stack, next); +} +``` + + ## generate_stub.pl - 各.cbcごとに.cを生成するくん - スタブを生成する @@ -191,3 +227,109 @@ next; ``` +### implのname space + +- `#impl`で指定したInterfaceと同名の`__code`が対象 + - generate_stubのタイミングで名前が変わる + +``` +#include "../context.h" +#interface "Stack.h" +#include <stdio.h> + +#impl "Stack.h" +//include "Node.h" +// typedef struct SingleLinkedStack { +// struct Element* top; +// } SingleLinkedStack; + + +__code clear(struct SingleLinkedStack* stack,__code next(...)) { + stack->top = NULL; + goto next(...); +} + +__code push(struct SingleLinkedStack* stack, union Data* data, __code next(...)) { + Element* element = new Element(); + element->next = stack->top; + element->data = data; + stack->top = element; + goto next(...); +} + +__code pop(struct SingleLinkedStack* stack, __code next(union Data* data, ...)) { + if (stack->top) { + data = stack->top->data; + stack->top = stack->top->next; + } else { + data = NULL; + } + goto next(data, ...); +} + +__code pop2(struct SingleLinkedStack* stack, __code next(union Data* data, union Data* data1, ...)) { + if (stack->top) { + data = stack->top->data; + stack->top = stack->top->next; + } else { + data = NULL; + } + if (stack->top) { + data1 = stack->top->data; + +``` + +これが生成される +- コンストラクタは書けば優先される(基本は自動生成) + + +``` +#include <stdio.h> + +//include "Node.h" +// typedef struct SingleLinkedStack { +// struct Element* top; +// } SingleLinkedStack; + +Stack* createSingleLinkedStack(struct Context* context) { + struct Stack* stack = &ALLOCATE(context, Stack)->Stack; + struct SingleLinkedStack* singleLinkedStack = &ALLOCATE(context, SingleLinkedStack)->SingleLinkedStack; + stack->stack = (union Data*)singleLinkedStack; + singleLinkedStack->top = NULL; + stack->push = C_pushSingleLinkedStack; + stack->pop = C_popSingleLinkedStack; + stack->pop2 = C_pop2SingleLinkedStack; + stack->get = C_getSingleLinkedStack; + stack->get2 = C_get2SingleLinkedStack; + stack->isEmpty = C_isEmptySingleLinkedStack; + stack->clear = C_clearSingleLinkedStack; + return stack; +} + +void printStack1(union Data* data) { + struct Node* node = &data->Element.data->Node; + if (node == NULL) { + printf("NULL"); + } else { + printf("key = %d ,", node->key); + printStack1((union Data*)data->Element.next); + } +} + +void printStack(union Data* data) { + printStack1(data); + printf("\n"); +} + +__code clearSingleLinkedStack(struct Context *context,struct SingleLinkedStack* stack,enum Code next) { + stack->top = NULL; + context->before = C_clearSingleLinkedStack; + goto meta(context, next); +} + +__code clearSingleLinkedStack_stub(struct Context* context) { + SingleLinkedStack* stack = (SingleLinkedStack*)GearImpl(context, Stack, stack); + enum Code next = Gearef(context, Stack)->next; + goto clearSingleLinkedStack(context, stack, next); +} +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/08/20.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/08/20.md Wed Dec 16 15:11:16 2020 +0900 @@ -75,4 +75,65 @@ file_name "/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/tools/../Stack.h", name "Stack" } +``` + +``` +[ 5%] Generating c/AtomicReference.c +[ 5%] Generating c/examples/boundedBuffer/main.c +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: code2, method: shutdown +[ 11%] Generating c/examples/boundedBuffer/initBuffer.c +[ 17%] Generating c/examples/boundedBuffer/SemaphoreImpl.c +[INFO] found instance lock, typeName Lock, cuurentCodeGear: pOperationSemaphoreImpl, method: doLock +[INFO] found instance queue, typeName Queue, cuurentCodeGear: pOperationSemaphoreImpl1, method: put +[INFO] found instance lock, typeName Lock, cuurentCodeGear: pOperationSemaphoreImpl1, method: doUnlock +[INFO] found instance lock, typeName Lock, cuurentCodeGear: pOperationSemaphoreImpl2, method: doUnlock +[INFO] found instance worker, typeName Worker, cuurentCodeGear: pOperationSemaphoreImpl3, method: taskReceive +[INFO] found instance lock, typeName Lock, cuurentCodeGear: vOperationSemaphoreImpl, method: doLock +[INFO] found instance queue, typeName Queue, cuurentCodeGear: vOperationSemaphoreImpl1, method: isEmpty +[INFO] found instance queue, typeName Queue, cuurentCodeGear: vOperationSemaphoreImpl2, method: take +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: vOperationSemaphoreImpl3, method: spawn +[INFO] found instance lock, typeName Lock, cuurentCodeGear: vOperationSemaphoreImpl4, method: doUnlock +[ 17%] Generating c/examples/boundedBuffer/BoundedBuffer.c +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: putBoundedBuffer, method: p +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: putBoundedBuffer1, method: p +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: putBoundedBuffer2, method: v +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: putBoundedBuffer3, method: v +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: takeBoundedBuffer, method: p +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: takeBoundedBuffer1, method: p +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: takeBoundedBuffer2, method: v +[INFO] found instance semaphore, typeName Semaphore, cuurentCodeGear: takeBoundedBuffer3, method: v +[ 23%] Generating c/examples/boundedBuffer/consumer.c +[INFO] found instance buffer, typeName Buffer, cuurentCodeGear: consumer, method: take +[ 23%] Generating c/examples/boundedBuffer/producer.c +[INFO] found instance buffer, typeName Buffer, cuurentCodeGear: producer, method: put +[ 29%] Generating c/SpinLock.c +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: doLockSpinLock, method: checkAndSet +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: doUnlockSpinLock, method: checkAndSet +[ 35%] Generating c/CPUWorker.c +[INFO] found instance tasks, typeName Queue, cuurentCodeGear: taskReceiveCPUWorker, method: take +[INFO] found instance worker, typeName Worker, cuurentCodeGear: getTaskCPUWorker, method: shutdown +[INFO] found instance iterator, typeName Iterator, cuurentCodeGear: odgCommitCPUWorker, method: barrier +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: odgCommitCPUWorker1, method: decrementTaskCount +[INFO] found instance queue, typeName Queue, cuurentCodeGear: odgCommitCPUWorker2, method: isEmpty +[INFO] found instance queue, typeName Queue, cuurentCodeGear: odgCommitCPUWorker3, method: take +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: odgCommitCPUWorker4, method: spawn +[INFO] found instance taskWorker, typeName Worker, cuurentCodeGear: odgCommitCPUWorker6, method: taskReceive +[ 35%] Generating c/TaskManagerImpl.c +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: spawnTasksTaskManagerImpl1, method: setWaitTask +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: spawnTasksTaskManagerImpl3, method: spawn +[INFO] found instance queue, typeName Queue, cuurentCodeGear: setWaitTaskTaskManagerImpl, method: put +[INFO] found instance iterator, typeName Iterator, cuurentCodeGear: spawnTaskManagerImpl, method: exec +[INFO] found instance queue, typeName Queue, cuurentCodeGear: taskSend1, method: put +[INFO] found instance queue, typeName Queue, cuurentCodeGear: taskSend2, method: put +[INFO] found instance tasks, typeName Queue, cuurentCodeGear: shutdownTaskManagerImpl, method: put +[ 41%] Generating c/SingleLinkedQueue.c +[ 41%] Generating c/SynchronizedQueue.c +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: clearSynchronizedQueue, method: checkAndSet +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: putSynchronizedQueue, method: checkAndSet +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: putSynchronizedQueue, method: checkAndSet +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: takeSynchronizedQueue, method: checkAndSet +[INFO] found instance atomic, typeName Atomic, cuurentCodeGear: takeSynchronizedQueue, method: checkAndSet +[ 47%] Generating c/MultiDimIterator.c +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: execMultiDimIterator, method: spawn +[INFO] found instance taskManager, typeName TaskManager, cuurentCodeGear: execMultiDimIterator1, method: spawn ``` \ No newline at end of file
--- a/user/anatofuz/note/2020/08/25.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/08/25.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,21 @@ +# 2020/08/25 + +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する + + +# 今週 +- ひたすらPerlを書いていた +- generate_*.plに`use warnings`を対応した +- Gearefのインデントをきれいにした +- Perlのテストを書き始めた +- Outputがある場合のstubの自動生成ができた + + # generate_*.plのwarnings対応 - perlの場合`use warnings`すると未定義値を使ったケースなどでwarningが出るようになる @@ -180,4 +198,344 @@ generateTypedefData(); generateDataGearInit(); } -``` \ No newline at end of file +``` + +# perlライブラリの整備とテスト + +- `Gears::Util`に押し込んでいたInterfaceのパーサーを`Geas::Interface`に移動 + - 他細々したリファクタリング等 +- いくつかの処理のテストを`perlTests`下に描き始めている + - Interfaceのパース + - generate_stubの挙動 +- generate_stub.plのテストは変換先の`.c`を予め用意しておき、生成した中身が一致しているかどうかの簡易なテスト + - 関数単位でのテストをする場合は気合いれてリファクタリングする必要がある... + +# generate_stub.pl + +- `.cbc`(Gearsで書かれたソース)を`.c`純粋なCbCに変換するスクリプト +- 大きく呼ばれるサブルーチンの数は2つ + - getDataGear($fn); + - `.cbc`または`.h`を読み込んで出てきたCodeGearとDataGearを数える + - `typedef`の有無でヘッダファイルか`.cbc`かを判定している + - 最初はコマンドライン引数として与えられた.cbcをパースする + - でてきた.hや.cbcを再帰的にパースしにいく + - ここで一度`.cbc`が読み込まれる + - generateDataGear($fn); + - `.cbc`を読みながら同時に`.c`を生成する + - 現状`.cbc`を読み進めたら戻せないので(配列にいれるとかすればできる)、`.c`を書き込む前に必要なデータ回収は`getDataGear`でする必要がある +- この2つのサブルーチンを使う関係で、比較的グローバル変数が多い + - ループで書かないといけないので、どうしてもそうなるところがある... + +## includeしているファイルのパスを解決 +- Gearsで自分で書いたヘッダファイルをincludeしようとする場合、ビルドする場所の関係でパスの指定が難しい + - `#include "hoge.h"`していた場合、`hoge.h`がプロジェクトルート下にいた場合フルパスに置き換える + +``` + } elsif (/^#include "(.*).h"$/) { + my $headerName = $1; + if ($headerName =~ m|/?context$|) { + print $fd $_; + next; + } + + # This process assumes that there are no header files of the same name + my $path = $headerNameToInfo->{$headerName}->{path}; + unless ($path) { + print $fd $_; + next; + } + + print $fd '#include "' .$path . '"'; + print $fd "\n"; + next; +``` + +## 出力があるInterfaceから値を取り出したい + +```c +__code pop2Test_StackTestImpl(struct StackTestImpl* stackTest, struct Stack* stack, __code next(...)) { + goto stack->pop2(pop2Test1_StackTestImpl); +} + +__code pop2Test3_StackTestImpl(struct StackTestImpl* stackTest, struct Stack* stack, __code next(...)) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + goto pop2Test1_StackTestImpl(stackTest, (union Data*)str, (union Data*)str1); +} + + +__code pop2Test1_StackTestImpl(struct StackTestImpl* stackTest, union Data* data, union Data* data1, struct Stack* stack, __code next(...)) { + String* str = (String*)data; + String* str2 = (String*)data1; + + printf("%d\n", str->size); + printf("%d\n", str2->size); + goto next(...); +} + +__code pop2Test1_StackTestImpl_stub(struct Context* context) { + struct StackTestImpl* stackTest = GearImpl(context, StackTest, stackTest); + Data* data = Gearef(context, Stack)->data; + Data* data1 = Gearef(context, Stack)->data1; + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2Test1_StackTestImpl(context, stackTest, data, data1, stack, next); +} +``` + +- 考え方としてはこの感じ + +- 各`__code`ごとに引数と型名の組を保存 +- `goto stack->pop(nextCodeGear)`が見つかれば、どのInterfaceが呼ばれているのかをみる +- interfaceが特定できれば、メソッドの定義を確認 + - 出力があるメソッドの場合は、出力として呼び出し元(Stack)のInterfaceに書き込まれる変数と型の組を取得 + - フラグを立てておいて`.c`を生成するタイミングで`C_`を変更しし、対応したstubを生成 + +## ローカル変数の取得 + +- とりあえず`__code`の引数と途中で生成しているローカル変数の変数名と型名の組を各`__Code`ごとに保存しておく + - 引数でもらってるケース, createしているケースがあるため + - stubを切り替える際に切り替える対象のCodeGearの名前が必要なので、`__code`ごとに保存しておく必要がある + +```perl + } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) { + my $codeGearName = $1; + if ($codeGearName =~ /_stub$/) { + $stub{$codeGearName}->{static} = 1; + $stub{$codeGearName}->{wrote} = 1; + $currentCodeGear = undef; + next; + } + my $args = $2; + my $cbc_source_path = $searchCbCFromCodeGearNameWCurrentFrileName->($codeGearName, $filename); + if ($cbc_source_path) { + &getCodeGear($cbc_source_path); + } + my $vname2type = Gears::Util->parseCodeGearDeclarationArg($args); + for my $vname (keys %$vname2type) { + $codeGearInfo->{$codeGearName}->{arg}->{$vname} = $vname2type->{$vname}; + } + $currentCodeGear = $codeGearName; + } elsif ((/^\s*(union|struct|const|enum)?\s*(\w+)(\*)\s+(\w+)\s+=/) && $currentCodeGear) { # collect local variables + my $structType = $1; + my $interfaceName = $2; + my $instance = $4; + $codeGearInfo->{$currentCodeGear}->{localVar}->{$instance} = $interfaceName; +``` + +## gotoしているタイミングでのハンドリング +- 引数->ローカル変数の順で`goto hoge->foo(nextCode)`のhogeの型を確認する + - この時点で`#inteface`しているかどうかを確認 + - 忘れていそうだったらwarningだしながら自動include +- 出力する変数名とInterfaceを保存しつつ、stubの名前を決める +- 今の所は`goto hoge->foo(nextCode)`と1引数の場合のみ想定 + - `goto hoge->foo(bar,baz,nextCode)`の場合はまだ対応していない + - Gearsの方はこのケースはないので.... xv6ならあるかも + + +```perl + } elsif (/^(.*)goto (\w+)\-\>(\w+)\((.*)\);/) { + # handling goto statement + # determine the interface you are using, and in the case of a goto CodeGear with output, create a special stub flag + my $prev = $1; + my $instance = $2; + my $method = $3; + my $tmpArgs = $4; + my $typeName = $codeGearInfo->{$currentCodeGear}->{arg}->{$instance}; + unless ($typeName) { + #this case is not __code arguments. + for my $localVar (keys %{$codeGearInfo->{$currentCodeGear}->{localVar}}) { + if ($localVar eq $instance) { + $typeName = $codeGearInfo->{$currentCodeGear}->{localVar}->{$localVar}; + last; + } + } + unless ($typeName){ + die "[ERROR] not found $instance type $.: $_\n"; + } + } + unless (exists $call_interfaces{$filename}->{$typeName}) { + warn "[AUTOINCLUDE] Forget #interface '$typeName' declaration in $filename"; + includeInterface(\%call_interfaces, $filename, $typeName, $headerNameToInfo); + } + + my $nextOutPutArgs = findExistsOutputDataGear($typeName, $method); + my $outputStubElem = { modifyEnumCode => $currentCodeGear, createStubName => $tmpArgs }; + + if ($nextOutPutArgs) { + my $tmpArgHash = {}; + map { $tmpArgHash->{$_} = $typeName } @$nextOutPutArgs; + + $outputStubElem->{args} = $tmpArgHash; + + #We're assuming that $tmpArgs only contains the name of the next CodeGear. + #Eventually we need to parse the contents of the argument. (eg. @parsedArgs) + my @parsedArgs = split /,/ , $tmpArgs; # + if (scalar(@parsedArgs) != 1) { + warn '[WARN] TBD'; + } + + $generateHaveOutputStub->{counter}->{$tmpArgs}++; + $outputStubElem->{counter} = $generateHaveOutputStub->{counter}->{$tmpArgs}; + $generateHaveOutputStub->{list}->{$currentCodeGear} = $outputStubElem; + } +``` + + +## `C_`の生成関連 + +- `next`を引数の最後に置くと`C_next`になってしまうバグ + - 同様に`stack->pop`などを引数の最後においた場合も`C_stack->pop`になってしまう + +- `C_`が生成される箇所で変数名をみてよしなにする + - 別のinterfaceから値を取ってくるケースで、stubを切り替えるのもここで行う + +```perl + $p =~ s/^(.*)\s(\w+)//; + $pType = $1; + $pName = $2; + $arg =~ s/^(\s)*(\w+)/$2/; + if ($pType =~ s/\_\_code$//) { + if ($arg =~ /(\w+)\(.*\)/) { + print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = $1;\n"; + } else { + my $hasGotoArgOrLocalVar = undef; + my $outputStubElem = $generateHaveOutputStub->{list}->{$codeGearName}; + + if ($outputStubElem && !$stub{$outputStubElem->{createStubName}."_stub"}->{static}) { + my $pick_next = "$outputStubElem->{createStubName}_$outputStubElem->{counter}"; + print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = C_$pick_next;\n"; + $i++; + next; + } + + # find __code of argument or local variable + for my $localVarType (qw/arg localVar/) { + my $foundVarType = $currentCodeGearInfo->{$localVarType}->{$arg}; + if ($foundVarType && $foundVarType eq '__code') { + $hasGotoArgOrLocalVar = 1; + } + } + + # inteface case + + if ($arg =~ /->/) { + print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = $arg;\n"; #Gearef->()->next = bar->baz; + $i++; + next; + } + + if ($hasGotoArgOrLocalVar) { + print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = $arg;\n"; #Gearef->()->next = next; + $i++; + next; + } + + print $fd "${indent}Gearef(${context_name}, $ntype)->$pName = C_$arg;\n"; + $i++; + next; + } +``` + +## stubの生成 + +- generateStubの最後に行う +- 既に`__stub`の中に何を書けばいいのかは確定している + - 置き換える予定のフィールドを取得して、置換して解決 +- 名前は出てきた順に `hoge_1_stub`と`_\d`がつく +- 今の所静的にstubがあれば生成しない + +```perl + #Create a stub when the output is a different interface + for my $modifyEnumCodeCodeGear (keys %{$generateHaveOutputStub->{list}}) { + my $outputStubElem = $generateHaveOutputStub->{list}->{$modifyEnumCodeCodeGear}; + my $targetStubName = $outputStubElem->{createStubName}; + my $createStubName = "$outputStubElem->{createStubName}_$outputStubElem->{counter}"; + my $replaceArgs = $outputStubElem->{args}; + my $replaceStubContents = $dataGearName{$targetStubName}; + + #If the stub was handwritten, skip + if ($stub{"${targetStubName}_stub"}->{static}) { + next; + } + + for my $arg (keys %$replaceArgs) { + my $interface = $replaceArgs->{$arg}; + $replaceStubContents =~ s/,(.*)\)->$arg/,$interface)->$arg/; + } + + generateStub($fd,$createStubName,$replaceStubContents); + } +``` + +# まだやってない実装 + +- 他のファイルで定義しているCodeGearに継続するケース + - 継続先の引数を読みに行って生成すれば問題ないのでできそう + - 既にCodeGearの名前から`.cbc`を特定する処理は実装済み + - 名前は工夫する必要がある +- Intefaceの実装に継続するケース + - `goto hoge->(stack->pop)` + - Stackを実装しているImplの全部のpopに対してstubを生成 + - なんとかして切り替える + + +# ほか + +- Gearefのインデントが揃うようになりました + - tabで頑張ってた所を`goto hoge();`のgotoまでのインデントに揃えるようにした + +```c +__code odgCommitCPUWorker(struct Context *context,struct CPUWorker* worker, struct Context* task) { + if (task->iterate) { + struct Iterator* iterator = task->iterator; + Gearef(context, Iterator)->iterator = (union Data*) iterator; + Gearef(context, Iterator)->task = task; + Gearef(context, Iterator)->next = C_odgCommitCPUWorker1; + Gearef(context, Iterator)->whenWait = C_odgCommitCPUWorker6; + context->before = C_odgCommitCPUWorker; + goto meta(context, iterator->barrier); + } else { + context->before = C_odgCommitCPUWorker; + goto meta(context, C_odgCommitCPUWorker1); + } +} +``` + + + +# 問題点 + +## 直接gotoで指定すると引数が落とされる + +- こうかくと + +```c +__code pop2Test3_StackTestImpl(struct StackTestImpl* stackTest, struct Stack* stack, __code next(...)) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + goto pop2Test1_StackTestImpl(stackTest, (union Data*)str, (union Data*)str1); +} +``` + +- こうなってしまう + - `(union Data*)str`とかが落とされる... + +```c +__code pop2Test3_StackTestImpl(struct Context *context,struct StackTestImpl* stackTest, struct Stack* stack, enum Code next) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + goto meta(context, C_pop2Test1_StackTestImpl); +} +``` + +# 今週 + +- Gearsに名前空間の実装 +- シス管 \ No newline at end of file
--- a/user/anatofuz/note/2020/09/08.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/09/08.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,10 +1,19 @@ # 2020/09/08 +# 研究目的 +- OSの信頼性を保証する必要がある +- 信頼性の保証にはモデル検査や定理証明を使用したい + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- 既存のunixであるxv6をCbCで書き換えて、検証を行いやすくしたい + - kernel/user両方をCbCで実装する + # 最近 - シス管関連 - LDAPの構築 + - とりあえず元気にubuntu上で動いているのでしばらく安泰 - radius - その他ansible + - ansibleの書き方だいぶわかってきた気がする - Gears - Interfaceの実装を満たしていないとエラーを出す - コンストラクタの自動生成 @@ -14,6 +23,7 @@ - 満たしていないmethodが生えているとコンパイルタイムでエラーを出す - Interfaceの実装のファイルの場合、実装したメソッドを数え上げている + - ルール的には第一引数に`Impl`が来ている (満たすべきCodeGear)だけ回収 ``` $ make pop_and_push @@ -29,8 +39,8 @@ - 実装するべきCodeGearをパターンマッチする愚直な実装 ```perl - if ($implInterfaceInfo->{isImpl}) { - for my $shouldImplCode (map { $_->{name} } @{$implInterfaceInfo->{parsedInterfaceInfo}->{codes}}) { + if ($implInterfaceInfo->{isImpl} && $filename =~ /\.cbc\z/) { + for my $shouldImplCode (map { $_->{name} } grep { $_->{args} =~ /Impl/ } @{$implInterfaceInfo->{parsedInterfaceInfo}->{codes}}) { my $isDefine = $shouldImplCode; for my $implCode (keys %{$codeGearInfo}) { if ($implCode =~ /$shouldImplCode/) { @@ -44,6 +54,7 @@ } } } + ``` # 名前空間の実装 @@ -56,9 +67,250 @@ - 新しい記法`#impl`を導入した +## 基本ルール + +- `#impl "Stack.h"` + - `Stack.h`を実装している場合に記述する + - この場合は自分の`.cbc`のファイル名と実装の型名が一致している前提 + - `SingleLinkedStack.cbc`の場合 -> `SingleLinkedStack.h`が存在しないとだめ + +- `#impl "StackTest.h" for "StackTestImpl3.h"` + - Inteerface for 型名の順で書く + - この場合は実装する`.cbc`とヘッダファイルの名前が異なっても大丈夫 + +## 実際に書く + +### ヘッダ + +```c +typedef struct StackTest <Type, Impl> { + __code insertTest1(Impl* stackTest, struct Stack* stack, __code next(...)); + __code insertTest2(Impl* stackTest, struct Stack* stack, __code next(...)); + __code insertTest3(Impl* stackTest, struct Stack* stack, __code next(union Data* data, union Data* data1, ...)); + __code insertTest4(Impl* stackTest, struct Stack* stack, __code next(...)); + __code pop2Test(Impl* stackTest, struct Stack* stack, __code next(...)); + __code pop2Test1(Impl* stackTest, union Data* data, union Data* data1, struct Stack* stack, __code next(...)); + __code next(...); +} StackTest; +``` + +### 実装 + +- 継続で渡す`insertTest1`などは変換される + +```c +#include "../../../context.h" +#interface "StackTest.h" +#interface "StackTest2.h" +#interface "Stack.h" +#include <stdio.h> + +#include "String.h" + +#impl "StackTest.h" for "StackTestImpl3.h" + + +__code insertTest1(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) { + String* str = NEW(String); + str->size = 99; + goto stack->push((union Data*)str, insertTest2); +} + +__code insertTest2(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) { + String* str = NEW(String); + str->size = 100; + goto stack->push((union Data*)str, pop2Test); +} + + +__code pop2Test(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) { + goto stack->pop2(pop2Test1); +} + +__code pop2Test3(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(union Data* data, union Data* data1, ...)) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + data = (union Data*)str; + data1 = (union Data*)str1; + + goto pop2Test1(stackTest, data, data1); +} + + +__code pop2Test1(struct StackTestImpl3* stackTest, union Data* data, union Data* data1, struct Stack* stack, __code next(...)) { + String* str = (String*)data; + String* str2 = (String*)data1; + + printf("%d\n", str->size); + printf("%d\n", str2->size); + goto next(...); +} +``` + +## 変換後 + +```c +#include "../../../context.h" +#include <stdio.h> + +#include "/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/examples/pop_and_push/String.h" + +StackTest* createStackTestImpl3(struct Context* context) { + struct StackTest* stackTest = &ALLOCATE(context, StackTest)->StackTest; + struct StackTestImpl3* StackTestImpl3 = &ALLOCATE(context, StackTestImpl3)->StackTestImpl3; + stackTest->stackTest = (union Data*)StackTestImpl3; + stackTest->stack = NULL; + stackTest->data = NULL; + stackTest->data1 = NULL; + stackTest->insertTest1 = C_insertTest1StackTestImpl3; + stackTest->insertTest2 = C_insertTest2StackTestImpl3; + stackTest->insertTest3 = C_insertTest3StackTestImpl3; + stackTest->insertTest4 = C_insertTest4StackTestImpl3; + stackTest->pop2Test = C_pop2TestStackTestImpl3; + stackTest->pop2Test1 = C_pop2Test1StackTestImpl3; + return stackTest; +} + + +__code insertTest1StackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next) { + String* str = NEW(String); + str->size = 99; + Gearef(context, Stack)->stack = (union Data*) stack; + Gearef(context, Stack)->data = (union Data*)str; + Gearef(context, Stack)->next = C_insertTest2StackTestImpl3; + goto meta(context, stack->push); +} + +__code insertTest1StackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto insertTest1StackTestImpl3(context, stackTest, stack, next); +} + +__code insertTest2StackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next) { + String* str = NEW(String); + str->size = 100; + Gearef(context, Stack)->stack = (union Data*) stack; + Gearef(context, Stack)->data = (union Data*)str; + Gearef(context, Stack)->next = C_pop2TestStackTestImpl3; + goto meta(context, stack->push); +} + + +__code insertTest2StackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto insertTest2StackTestImpl3(context, stackTest, stack, next); +} + +__code pop2TestStackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next) { + Gearef(context, Stack)->stack = (union Data*) stack; + Gearef(context, Stack)->next = C_pop2Test1StackTestImpl3_1; + goto meta(context, stack->pop2); +} + +__code pop2TestStackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2TestStackTestImpl3(context, stackTest, stack, next); +} + +__code pop2Test3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next,union Data **O_data,union Data **O_data1) { + Data* data __attribute__((unused)) = *O_data; + Data* data1 __attribute__((unused)) = *O_data1; + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + data = (union Data*)str; + data1 = (union Data*)str1; + + goto meta(context, C_pop2Test1StackTestImpl3); +} + + +__code pop2Test3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + Data** O_data = &Gearef(context, StackTest)->data; + Data** O_data1 = &Gearef(context, StackTest)->data1; + goto pop2Test3(context, stackTest, stack, next, O_data, O_data1); +} + +__code pop2Test1StackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, union Data* data, union Data* data1, struct Stack* stack, enum Code next) { + String* str = (String*)data; + String* str2 = (String*)data1; + + printf("%d\n", str->size); + printf("%d\n", str2->size); + goto meta(context, next); +} + + +__code pop2Test1StackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Data* data = Gearef(context, StackTest)->data; + Data* data1 = Gearef(context, StackTest)->data1; + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2Test1StackTestImpl3(context, stackTest, data, data1, stack, next); +} + +__code insertTest3StackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next) { + StackTest2* stackTest2 = createStackTest2Impl(context); + String* str = NEW(String); + str->size = 100; + Gearef(context, StackTest2)->stackTest2 = (union Data*) stackTest2; + Gearef(context, StackTest2)->stack = stack; + Gearef(context, StackTest2)->data1 = (union Data*) (union Data*)str; + Gearef(context, StackTest2)->next = C_pop2TestStackTestImpl3; + goto meta(context, stackTest2->insertTest1); +} + +__code insertTest3StackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto insertTest3StackTestImpl3(context, stackTest, stack, next); +} + +__code insertTest4StackTestImpl3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next) { + StackTest2* stackTest2 = createStackTest2Impl(context); + String* str = NEW(String); + str->size = 100; + Gearef(context, StackTest2)->stackTest2 = (union Data*) stackTest2; + Gearef(context, StackTest2)->stack = stack; + Gearef(context, StackTest2)->data1 = (union Data*) (union Data*)str; + Gearef(context, StackTest2)->next = C_pop2TestStackTestImpl3; + goto meta(context, stackTest2->insertTest1); +} +__code insertTest4StackTestImpl3_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto insertTest4StackTestImpl3(context, stackTest, stack, next); +} + +__code pop2Test1StackTestImpl3_1_stub(struct Context* context) { + StackTestImpl3* stackTest = (StackTestImpl3*)GearImpl(context, StackTest, stackTest); + Data* data = Gearef(context, Stack)->data; + Data* data1 = Gearef(context, Stack)->data1; + Stack* stack = Gearef(context, StackTest)->stack; + enum Code next = Gearef(context, StackTest)->next; + goto pop2Test1StackTestImpl3(context, stackTest, data, data1, stack, next); +} +``` + # Gears コンストラクタの自動生成 -- `#impl`キーワードを定義 +- `#impl`キーワードとすり替えられる + - 基本的には`trans_impl.pl`で実装していたルーチンの移植 ```perl } elsif(/^#impl "(.*)"/) { @@ -79,4 +331,107 @@ } print $fd Gears::Stub->generate_constructor($constructInterface, $constructImpl); next; -``` \ No newline at end of file +``` + +``` +#include "../../../context.h" +#include <stdio.h> + +#include "/Users/anatofuz/src/firefly/hg/Gears/Gears/src/parallel_execution/examples/pop_and_push/String.h" + +StackTest* createStackTestImpl3(struct Context* context) { + struct StackTest* stackTest = &ALLOCATE(context, StackTest)->StackTest; + struct StackTestImpl3* StackTestImpl3 = &ALLOCATE(context, StackTestImpl3)->StackTestImpl3; + stackTest->stackTest = (union Data*)StackTestImpl3; + stackTest->stack = NULL; + stackTest->data = NULL; + stackTest->data1 = NULL; + stackTest->insertTest1 = C_insertTest1StackTestImpl3; + stackTest->insertTest2 = C_insertTest2StackTestImpl3; + stackTest->insertTest3 = C_insertTest3StackTestImpl3; + stackTest->insertTest4 = C_insertTest4StackTestImpl3; + stackTest->pop2Test = C_pop2TestStackTestImpl3; + stackTest->pop2Test1 = C_pop2Test1StackTestImpl3; + return stackTest; +} +``` + + +# 悩みどころ + +## 直接gotoしたいのに引数が落とされる + +- こうすると + +```c +__code pop2Test3(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + union Data* data = (union Data*)str; + union Data* data1 = (union Data*)str1; + + goto pop2Test1(stackTest, data, data1); +} +``` + +- こうなるもの + + +```c +__code pop2Test3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + union Data* data = (union Data*)str; + union Data* data1 = (union Data*)str1; + + goto meta(context, C_pop2Test1StackTestImpl3); +} +``` + + +- 出力があってないという話らしい + +```c +__code pop2Test3(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(union Data* data, union Data* data1, ...)) { + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + data = (union Data*)str; + data1 = (union Data*)str1; + + goto pop2Test1(stackTest, data, data1); +} +``` + + +```c +__code pop2Test3(struct Context *context,struct StackTestImpl3* stackTest, struct Stack* stack, enum Code next,union Data **O_data,union Data **O_data1) { + Data* data __attribute__((unused)) = *O_data; + Data* data1 __attribute__((unused)) = *O_data1; + String* str = NEW(String); + str->size = 200; + String* str1 = NEW(String); + str1->size = 300; + data = (union Data*)str; + data1 = (union Data*)str1; + + goto meta(context, C_pop2Test1StackTestImpl3); +} + +``` + +- これは書き方の問題っぽい....... + + +## Copy on Writeの実装 + +- InterfaceのDataGearに書き込みに行くタイミングでコピーしたい気がする + - 誰が書き込んでいるCodeGearなのかの特定がしたい + - CodeGear内でのInterfaceへの再代入を禁止する + - 再代入したい場合は新しいGearを作って差し替えたい + - ここは別のメタ計算を埋め込みたい \ No newline at end of file
--- a/user/anatofuz/note/2020/10/20.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/10/20.md Wed Dec 16 15:11:16 2020 +0900 @@ -12,4 +12,17 @@ - プログラムの信頼性の保証を動作しつつ行うには、メタレベルの計算を活用したい - そのためにはメタレベルの計算を柔軟に扱うAPIや実装方法が必要 - 本研究ではノーマル/メタレベルでの実装に適した、継続を基本とする言語Continuation Based Cを用いて、OSの実装を行い、メタ計算APIについて考察する。 - \ No newline at end of file + + +# 今週 +- シス管周りいろいろ + - news-ieにCMSを仕込んだ + - あとで通知を作成 +- 余裕が出てきたのでいろいろ再開 + - `ie-virsh`を構築したいけど、C + Python2なのでどうせならRustで書き直すかみたいな気分 + - Rust忘れてたのでRustlingsやってた + - https://github.com/rust-lang/rustlings + +# Gears系 +- par gotoの高速化ちょっとやろうかなみたいな気持ち + - その前にcontextへの書き戻しを検知 or 構文で書き戻しを禁止したい気がする \ No newline at end of file
--- a/user/anatofuz/note/2020/11/03.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/11/03.md Wed Dec 16 15:11:16 2020 +0900 @@ -21,8 +21,15 @@ - ie-virshの実装 - 大体Rustで実装終わった - あと`define-gdb`のport問題だけ解決すればなんとかなる + - 50000番台を学籍番号から割り振ろかなとか考えている + - 細かい落ち葉拾い系 + - mkdirしたdirectoryのpermissionとか + - undefineしたときのxmlの削除とか + - c + python2 から rust単体へ... + - 特にRustでやった深い意味はない(やってみたかっただけ) - http://www.cr.ie.u-ryukyu.ac.jp/hg/Members/anatofuz/ie-virsh/ - https://gitlab.ie.u-ryukyu.ac.jp/k198584/ie-virsh - - c + python2 から rust単体へ... - - 特にRustでやった深い意味はない(やってみたかっただけ) -- そろそろGearsの研究を再開するので、直前までなにやってたかを思い出しつつ色々 \ No newline at end of file +- そろそろGearsの研究を再開したいので、直前までなにやってたかを思い出しつつ色々 + +# Gears +- 起動時にcontextをいくつか作るのをやってみる予定 \ No newline at end of file
--- a/user/anatofuz/note/2020/11/10.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/11/10.md Wed Dec 16 15:11:16 2020 +0900 @@ -18,8 +18,58 @@ - 奨学金の免除申請の書類が来たので作文をすることに - 業績系いろいろ書かないと... - 指導教員の推薦の作文がありますがどうしましょう... - +- 知り合いのエンジニアが沖縄に来てたので飲みに行っていた - アシャリフ先生のpukiwiki置換 - ひたすらperlを書いてeuc-jpにキレる世界観 +- RustのFileWriteを書いた + - https://gitlab.ie.u-ryukyu.ac.jp/os/2020/k198584/filewrite +- Rakuのenv系のビルドツールにプルリクを送ったけれど無視されて辛い -- https://gitlab.ie.u-ryukyu.ac.jp/os/2020/k198584/filewrite \ No newline at end of file +# CbC関連 + +- B3の松岡くんと作業した +- ArmなCbC GCCのdependendsで指定していた`arm-none-eabi-gcc`が古いらしい + +```diff +diff --git a/cbcgcc-arm.rb b/cbcgcc-arm.rb +index 5bd5e81..8823374 100644 +--- a/cbcgcc-arm.rb ++++ b/cbcgcc-arm.rb +@@ -14,7 +14,7 @@ class CbcgccArm < Formula + depends_on "mpfr" + depends_on "libmpc" + depends_on "zstd" +- depends_on "arm-none-eabi-gcc" ++ depends_on "ArmMbed/homebrew-formulae/arm-none-eabi-gcc" + + bottle do + rebuild 1 +@@ -43,7 +43,8 @@ class CbcgccArm < Formula + "--disable-werror", + "--disable-libssp", "--disable-libstdcxx-pch", "--disable-libmudflap", + "--with-newlib", +- "--with-headers=#{arm}/gcc/arm-none-eabi/include,#{inc}" ++ "--with-headers=#{arm}/gcc/arm-none-eabi/include,#{inc}", ++ "--with-gas" + system "sh config.status" + system "make","-j","4" + system "make", "install" +``` + +# Raku関係 + +Rakudo-Star(rakuの季節ごとにでる詰め合わせパック)のビルドツールが`Configure.pl`から`rstar`に変更になっていた。 + +- MoarVM, NQP, Rakuのそれぞれでは`Configure.pl`が使われているらしい +- `rstar`はbash script + +気づいたら`v2020.10`に... + +- https://twitter.com/koto_san_kana/status/1320121190724341760 + +```shell +$raku --version +Welcome to 𝐑𝐚𝐤𝐮𝐝𝐨™ v2020.10. +Implementing the 𝐑𝐚𝐤𝐮™ programming language v6.d. +Built on MoarVM version 2020.10. +``` \ No newline at end of file
--- a/user/anatofuz/note/2020/11/17.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/11/17.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,95 @@ + +# 研究目的 +- アプリケーションの信頼性を保証するには土台となるOSの信頼性を高く保証する必要がある + - しかしOSの機能をテストですべて検証するのは不可能である。 +- 定理証明やモデル検査を利用して、テストに頼らずに保証したい + - 証明しやすい形、かつ実際に動くソースコードが必要 + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- プログラムは二つの計算に分離される + - プログラムは入力と出力の関係を決める計算(ノーマルレベル) + - その計算に必要なメタな計算(メタレベル) +- プログラムの信頼性の保証を動作しつつ行うには、メタレベルの計算を活用したい +- そのためにはメタレベルの計算を柔軟に扱うAPIや実装方法が必要 +- 本研究ではノーマル/メタレベルでの実装に適した、継続を基本とする言語Continuation Based Cを用いて、OSの実装を行い、メタ計算APIについて考察する。 + + +# 最近 +- 奨学金の免除申請の書類が来たので作文をすることに + - 業績系いろいろ書かないと... + - 指導教員の推薦の作文がありますがどうしましょう... +- RustのFileWriteを書いた + - https://gitlab.ie.u-ryukyu.ac.jp/os/2020/k198584/filewrite +- BigSurにあげた + - brewはまだBigSurを完全サポートしてない +- シス管関係 +- Rakuのenv系のビルドツールにプルリクを送ったけれど無視されて悲しい + +# BigSur + +- アイコンがiOSっぽくてダサい + - SEも変わってて違和感がすごい +- brewは完全サポートしてないらしい + - CommandLineTools関係でも色々大変そう +``` +Warning: You are using macOS 11.0. +We do not provide support for this released but not yet supported version. +You will encounter build failures with some formulae. +Please create pull requests instead of asking for help on Homebrew's GitHub, +Twitter or any other official channels. You are responsible for resolving +any issues you experience while you are running this +released but not yet supported version. +``` + +# CbC関連 + +- B3の松岡くんと作業した +- ArmなCbC GCCのdependendsで指定していた`arm-none-eabi-gcc`が古いらしい + +```diff +diff --git a/cbcgcc-arm.rb b/cbcgcc-arm.rb +index 5bd5e81..8823374 100644 +--- a/cbcgcc-arm.rb ++++ b/cbcgcc-arm.rb +@@ -14,7 +14,7 @@ class CbcgccArm < Formula + depends_on "mpfr" + depends_on "libmpc" + depends_on "zstd" +- depends_on "arm-none-eabi-gcc" ++ depends_on "ArmMbed/homebrew-formulae/arm-none-eabi-gcc" + + bottle do + rebuild 1 +@@ -43,7 +43,8 @@ class CbcgccArm < Formula + "--disable-werror", + "--disable-libssp", "--disable-libstdcxx-pch", "--disable-libmudflap", + "--with-newlib", +- "--with-headers=#{arm}/gcc/arm-none-eabi/include,#{inc}" ++ "--with-headers=#{arm}/gcc/arm-none-eabi/include,#{inc}", ++ "--with-gas" + system "sh config.status" + system "make","-j","4" + system "make", "install" +``` + +# Raku関係 + +Rakudo-Star(rakuの季節ごとにでる詰め合わせパック)のビルドツールが`Configure.pl`から`rstar`に変更になっていた。 + +- MoarVM, NQP, Rakuのそれぞれでは`Configure.pl`が使われているらしい +- `rstar`はbash script + +気づいたら`v2020.10`に... + +- https://twitter.com/koto_san_kana/status/1320121190724341760 + +```shell +$raku --version +Welcome to 𝐑𝐚𝐤𝐮𝐝𝐨™ v2020.10. +Implementing the 𝐑𝐚𝐤𝐮™ programming language v6.d. +Built on MoarVM version 2020.10. +``` + + 試しに`arm-none-gcc`を使ってみる ```c @@ -43,6 +135,10 @@ なんかlinkerで死んでる + +1つ1つ手でやってみる +- `arm-none-eabi-gcc -S hello.c` + アセンブラはなんかできてるっぽい ```asm @@ -110,4 +206,56 @@ .word .LC1 .size main, .-main .ident "GCC: (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)" +``` + +- asでコンパイル + +```shell ++firefly+one arm-none-eabi-as hello.s ++firefly+one ls +Cerium/ a.out a.out.dSYM/ foo.c foo.s hello.c hello.s memo puri/ test test.c ++firefly+one file a.out +a.out: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped +``` + +出来ている? + + +# Gears +- そろそろがんばります... +- とりあえず引数で無いけれど、特定のヘッダファイル`context.h`に登録したい場合の構文を作った + +```c +#include "../context.h" +#include <stdio.h> +#interface "Queue.h" +#data "Node.h" +#data "Element.h" + +Queue* createSingleLinkedQueue(struct Context* context) { + struct Queue* queue = new Queue(); + struct SingleLinkedQueue* singleLinkedQueue = new SingleLinkedQueue(); + queue->queue = (union Data*)singleLinkedQueue; + singleLinkedQueue->top = new Element(); + singleLinkedQueue->last = singleLinkedQueue->top; + queue->take = C_takeSingleLinkedQueue; + queue->put = C_putSingleLinkedQueue; + queue->isEmpty = C_isEmptySingleLinkedQueue; + queue->clear = C_clearSingleLinkedQueue; + return queue; +} +``` + + +- generate_stubでコメントに変換される + +```c +#include "../context.h" +#include <stdio.h> +#interface "Queue.h" +// include "Node.h" +// include "Element.h" + +Queue* createSingleLinkedQueue(struct Context* context) { + struct Queue* queue = new Queue(); ``` \ No newline at end of file
--- a/user/anatofuz/note/2020/11/24.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/11/24.md Wed Dec 16 15:11:16 2020 +0900 @@ -13,12 +13,15 @@ # 最近 +- シス管の発表資料書いてました - 楽しくなってie-virshの実装を進めていた - Gearsはコンストラクタ生成周りいじってました - SingleLinkedStackのコンストラクタを自動生成するように - あとは松岡くんとかとPerl書いてました - +- 今週は内定者と懇親します + # Gears +- SingleLinkedStackのコンストラクタが消え去った 変換前 @@ -103,4 +106,29 @@ ``` - 変換時には`next`と`whenEmpty`の様な継続のCodeGearは`C_`を生成しないように仕込まれている - - 一意な実装が存在するわけではないので \ No newline at end of file + - 一意な実装が存在するわけではないので + - 微妙に此処がバグっていたので直した + +# Option + +Rustに影響されているのでMaybeみたいなやつがほしい気がする + +```c +typedef struct Option <Type, Impl> { + __code some(Impl* option, union Data* data, __code next(...)); + __code none(Impl* option, __code next(...)); + __code is_ok(Impl* option, __code ok(union Data* data, ...), __code none(...)); +} Option; +``` + +- 意外とかけそうなので例題書いてみるか... + - 1 Interfaceが複数のImplを持つ例題を書くかみたいな気持ち + - 今のInterfaceにImplをもたせる方針をやめるか、中でシンボルテーブルみたいなのを持ちたい気がする + - いやそれがcontextではあるのだけれど... + +# NEXT + +- メタ計算APIとして自分自身の型情報の取得とかしたい気がする + - もしくはGenericsに該当するAPI +- par gotoの改良したい + - プロセスを作らずにスレッドを作るみたいな戦略もありそう..? \ No newline at end of file
--- a/user/anatofuz/note/2020/12/04.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/12/04.md Wed Dec 16 15:11:16 2020 +0900 @@ -2,3 +2,7 @@ - a - b - c + +```shell +$perl --version +```
--- a/user/anatofuz/note/2020/12/08.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/12/08.md Wed Dec 16 15:11:16 2020 +0900 @@ -15,79 +15,261 @@ # 最近 - growiをCLIで編集できるツール書いていました - シス管関係 +- Gearsのコンストラクタの生成ルーチンがバグってたので直した - Interfaceの実装を考えている - 修論のmindmapを書き始めました + aaa +# growiのCLI +- growiのバックアップもかねてgolangで書いていたものを流用 + - backupはweb APIでは完全には厳しいので、mongodbをdumpしたjsonをパースする方針 +- webAPIを叩いてMarkdownを更新するコマンド +- ローカルファイルに変更がない場合はAPIを叩かない +- `growsync edit`で自分のメモページが日付ごと生成される + + + + +# Perlスクリプトのバグ + +- コンストラクタ自動生成関連で微妙なバグが発生していた +- 型ほしい!!!!!!!! + +```diff +diff -r b3d446fb5b93 -r a7f52fd3d546 src/parallel_execution/generate_stub.pl +--- a/src/parallel_execution/generate_stub.pl Thu Nov 26 14:55:17 2020 +0900 ++++ b/src/parallel_execution/generate_stub.pl Tue Dec 08 16:42:07 2020 +0900 +@@ -594,13 +594,13 @@ + next unless ($implInterfaceInfo->{genConstructor}); + + my $constructInterface = { +- name => $implInterfaceInfo->{interface}, +- path => $headerNameToInfo->{$implInterfaceInfo->{interface}}->{path} ++ name => $implInterfaceInfo->{interface}, ++ file_name => $headerNameToInfo->{$implInterfaceInfo->{interface}}->{path} + }; + + my $constructImpl = { +- name => $implInterfaceInfo->{implementation}, +- path => $headerNameToInfo->{$implInterfaceInfo->{implementation}}->{path} ++ name => $implInterfaceInfo->{implementation}, ++ file_name => $headerNameToInfo->{$implInterfaceInfo->{implementation}}->{path} + }; + + unless ($constructImpl->{path}) { +``` + + # Interfaceの複数実装 -- Haskellの例題見ながら雰囲気を考えている - - どのIntefaceが使われているかは型ごとにenumを作成したい +- `#impl`で宣言した下のブロックで実装を書く + - rust的に `impl { }`にするのが良いかもしれない ```c -/* -data Point = Pt Double +#impl "Stack.h" for "SingleLinkedStack.h" + +__code clearSingleLinkedStack(struct SingleLinkedStack* stack,__code next(...)) { + stack->top = NULL; + goto next(...); +} -instance Eq Point where - (Pt x) == (Pt x') = x == x' +__code pushSingleLinkedStack(struct SingleLinkedStack* stack, union Data* data, __code next(...)) { + Element* element = new Element(); + element->next = stack->top; + element->data = data; + stack->top = element; + goto next(...); +} -instance Ord Point where - compare (Pt x) (Pt x') - | x == x' = EQ - | x < x' = LT - | otherwise = GT +__code popSingleLinkedStack(struct SingleLinkedStack* stack, __code next(union Data* data, ...)) { + if (stack->top) { + data = stack->top->data; + stack->top = stack->top->next; + } else { + data = NULL; + } + goto next(data, ...); +} -main = do print $ (Pt 1) == (Pt 2) -- 出力: False - print $ (Pt 1) >= (Pt 2) -- 出力: False - print $ (Pt 1) <= (Pt 2) -- 出力: True -*/ - -typedef struct Rectangle { - int l; - int w; +__code pop2SingleLinkedStack(struct SingleLinkedStack* stack, __code next(union Data* data, union Data* data1, ...)) { + if (stack->top) { + data = stack->top->data; + stack->top = stack->top->next; + } else { + data = NULL; + } + if (stack->top) { + data1 = stack->top->data; + stack->top = stack->top->next; + } else { + data1 = NULL; + } + goto next(data, data1, ...); } -typedef struct Ord { - __code equal(Impl* eq, Impl* other, __code ok(...), __code none(...)); - __code lt(Impl* eq, Impl* other, __code ok(...), __code none(...)); - __code pt(Impl* eq, Impl* other, __code ok(...), __code none(...)); +__code getSingleLinkedStack(struct SingleLinkedStack* stack, __code next(union Data* data, ...)) { + if (stack->top) { + data = stack->top->data; + } else { + data = NULL; + } + goto next(data, ...); +} + +__code get2SingleLinkedStack(struct SingleLinkedStack* stack, __code next(union Data* data, union Data* data1, ...)) { + if (stack->top) { + data = stack->top->data; + if (stack->top->next) { + data1 = stack->top->next->data; + } else { + data1 = NULL; + } + } else { + data = NULL; + data1 = NULL; + } + goto next(data, data1, ...); +} + +__code isEmptySingleLinkedStack(struct SingleLinkedStack* stack, __code next(...), __code whenEmpty(...)) { + if (stack->top) { + goto next(...); + } else { + goto whenEmpty(...); + } } -impl Ord typedef struct Rectangle { - - __code rectangleual(Impl* rectangle, Impl* other, __code ok(...), __code none(...)) { - goto rectangle->eq(other, ok, none, ...); - } +#impl "Eq.h" for "SingleLinkedStack.h" - __code lt(Impl* rectangle, Impl* other, __code ok(...), __code none(...)) { - if (rectangle.x > other.x) { - goto ok(...); - } - goto none(...); - } - +__code eq(SingleLinkedStack* self, SingleLinkedStack* other, __code next(), __code ne()) { + goto sub_eq(self, other, self->pop(), other->pop()); } -typedef enum PointTypeManager { - Point-Ord, - Point-Equal +__code sub_eq(SingleLinkedStack* self, SingleLinkedStack* other, Element* self_element, Element* other_element, __code equal(...), __code ne(...), __code next(...)) { + if (self_element == other_element) { + if (self_element == NULL ) { + goto equal(next); + } + goto sub_eq(self, other, self->pop(), other->pop(), next); + } + got ne(next); +} +``` + +# これをもとにコンストラクタが生成される + + +```c +Stack* createSingleLinkedStack(struct Context* context) { + struct Stack* stack = &ALLOCATE(context, Stack)->Stack; + struct SingleLinkedStack* single_linked_stack = &ALLOCATE(context, SingleLinkedStack)->SingleLinkedStack; + stack->stack = (union Data*)single_linked_stack; + stack->data = NULL; + stack->data1 = NULL; + single_linked_stack->top = NULL; + stack->clear = C_clearSingleLinkedStack; + stack->push = C_pushSingleLinkedStack; + stack->pop = C_popSingleLinkedStack; + stack->pop2 = C_pop2SingleLinkedStack; + stack->isEmpty = C_isEmptySingleLinkedStack; + stack->get = C_getSingleLinkedStack; + stack->get2 = C_get2SingleLinkedStack; + return stack; } ``` -# Option +- Implは誰が持ってるべき? + - Interfaceごとにlistを作るのが良い気がしてきた -Rustに影響されているのでMaybeみたいなやつがほしい気がする +```c + struct Stack { + union Data* stack; + union Data* data; + union Data* data1; + enum Code clear; + enum Code push; + enum Code pop; + enum Code pop2; + enum Code isEmpty; + enum Code get; + enum Code get2; + enum Code next; + enum Code whenEmpty; + int interfaceID; + } Stack; + +``` + +- 現状のContext + - `union Data** data`にすべてのDataGearが入っている + - indexはDataGearのenumが使用されている + - 複数のInterfaceのImplは現状`data`にそのまま置けない(添字を自分で作る必要がありそう) +- `ALLOCATE`すればヒープに作成される + - 作成したヒープのアドレスは誰かが持っている必要がある + - contextのheapは`ALLOCATE`の際に自動で拡張される + - 複数のInterfaceのImplを持つものはheapに置いて別途管理すれば良い気がする...? +- InterfaceのImplごとにIDを降ってIDを管理したい + - object? ```c -typedef struct Option <Type, Impl> { - __code some(Impl* option, union Data* data, __code next(...)); - __code none(Impl* option, __code next(...)); - __code is_ok(Impl* option, __code ok(union Data* data, ...), __code none(...)); -} Option; +struct Context { + enum Code next; + struct Worker* worker; + struct TaskManager* taskManager; + int codeNum; + __code (**code) (struct Context*); + union Data **data; + void* heapStart; + void* heap; + long heapLimit; + int dataNum; + + // task parameter + int idgCount; //number of waiting dataGear + int idg; + int maxIdg; + int odg; + int maxOdg; + int gpu; // GPU task + struct Context* task; + struct Element* taskList; +#ifdef USE_CUDAWorker + int num_exec; + CUmodule module; + CUfunction function; +#endif + /* multi dimension parameter */ + int iterate; + struct Iterator* iterator; +}; ``` -- 意外とかけそうなので例題書いてみるか... - - 1 Interfaceが複数のImplを持つ例題を書くかみたいな気持ち - - 今のInterfaceにImplをもたせる方針をやめるか、中でシンボルテーブルみたいなのを持ちたい気がする - - いやそれがcontextではあるのだけれど... -- .....と思いきやgotoすればいいという感じだったので却下 +``` +Stack* createSingleLinkedStackWEQ(struct Context* context) { + struct Stack* stack = &ALLOCATE(context, Stack)->Stack; + struct SingleLinkedStack* single_linked_stack = &ALLOCATE(context, SingleLinkedStack)->SingleLinkedStack; + stack->stack = (union Data*)single_linked_stack; + stack->data = NULL; + stack->data1 = NULL; + single_linked_stack->top = NULL; + stack->clear = C_clearSingleLinkedStack; + stack->push = C_pushSingleLinkedStack; + stack->pop = C_popSingleLinkedStack; + stack->pop2 = C_pop2SingleLinkedStack; + stack->isEmpty = C_isEmptySingleLinkedStack; + stack->get = C_getSingleLinkedStack; + stack->get2 = C_get2SingleLinkedStack; + eq->eq = C_eqSingleLinkedSatack; + return stack; +} +``` +# シス管関係 + +- そろそろ本業に移行したいところ.... +- お手伝いしてくれる人々募集しています + +# Rust + +- Static Linkできるらしい? + - https://stackoverflow.com/questions/31770604/how-to-generate-statically-linked-executables
--- a/user/anatofuz/note/2020/12/10.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/12/10.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,3 @@ # 2020/12/10 + +##
--- a/user/anatofuz/note/2020/12/14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/12/14.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,8 @@ -# hello \ No newline at end of file +# 2020年 12月14日 月曜日 22時50分33秒 JST + +例題 +- chat +- dpp +- twice +- copy on write +- a
--- a/user/anatofuz/note/2020/12/15.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/anatofuz/note/2020/12/15.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,337 @@ -# aaa \ No newline at end of file +# 研究目的 +- アプリケーションの信頼性を保証するには土台となるOSの信頼性を高く保証する必要がある + - しかしOSの機能をテストですべて検証するのは不可能である。 +- 定理証明やモデル検査を利用して、テストに頼らずに保証したい + - 証明しやすい形、かつ実際に動くソースコードが必要 + - 継続ベースの状態遷移系で再実装することで表現しやすくしたい +- プログラムは二つの計算に分離される + - プログラムは入力と出力の関係を決める計算(ノーマルレベル) + - その計算に必要なメタな計算(メタレベル) +- プログラムの信頼性の保証を動作しつつ行うには、メタレベルの計算を活用したい +- そのためにはメタレベルの計算を柔軟に扱うAPIや実装方法が必要 +- 本研究ではノーマル/メタレベルでの実装に適した、継続を基本とする言語Continuation Based Cを用いて、OSの実装を行い、メタ計算APIについて考察する。 + + +# 最近 +- 何となくこんな感じで実装したいデザインが決まってきた + - ジェネリクスもいれる必要がありそう +- DataGearのメタ情報を保存するリストを導入した +- perlで変換スクリプトを書き始めた +- growiをupdateしたらAPI経由でのpageのcreateができなくなった + - issue報告しておいた(プルリクはjsがなにもわからんかった....... + - エンドポイントが変わったらしい(ドキュメントも変えてほしい) +- 温めていたPerlインタプリタのブログを書いた + +# Gearsジェネリクス + +- なんとなくこうなりそうな雰囲気で書いてみた + - `rectangle`だけをElementとして許可するSingleLinkedStack + - Elementにもジェネリクスが必要そう +- ジェネリクスも実装する必要性が出来てきた気がする + - MetaCodeGearで型情報の検査を行いたい + - 型検査をするCodeGearはPerlでコンパイル時に生成できそう + - enumさえ解ればディスパッチができそう + +```c + +// #data Element<Rectangle>; +// #data Element + +#impl SingleLinkedStack<Rectangle> for Stack.h + +__code clearSingleLinkedStack(struct SingleLinkedStack* stack,__code next(...)) { + stack->top = NULL; + goto next(...); +} + +__code pushSingleLinkedStack(struct SingleLinkedStack* stack, struct Rectangle* rectangle, __code next(...)) { + Element* element = new Element<Rectangle>(); + element->next = stack->top; + element->data = rectangle; + stack->top = element; + goto next(...); // nextのstubの前にElementの型検査したい +} + +__code popSingleLinkedStack(struct SingleLinkedStack* stack, __code next(struct Rectangle* rectangle, ...)) { + if (stack->top) { + rectangle = stack->top->data; + stack->top = stack->top->next; + } else { + rectangle = NULL; + } + goto next(rectangle, ...); +} + +__code pop2SingleLinkedStack(struct SingleLinkedStack* stack, __code next(struct Rectangle* rectangle, struct Rectangle* rectangle1, ...)) { + if (stack->top) { + rectangle = stack->top->data; + stack->top = stack->top->next; + } else { + rectangle = NULL; + } + if (stack->top) { + rectangle1 = stack->top->data; + stack->top = stack->top->next; + } else { + rectangle1 = NULL; + } + goto next(rectangle, rectangle1, ...); +} + + +__code getSingleLinkedStack(struct SingleLinkedStack* stack, __code next(struct Rectangle* rectangle, ...)) { + if (stack->top) { + rectangle = stack->top->data; + } else { + rectangle = NULL; + } + goto next(rectangle, ...); +} + +__code get2SingleLinkedStack(struct SingleLinkedStack* stack, __code next(struct Rectangle* rectangle, struct Rectangle* rectangle1, ...)) { + if (stack->top) { + rectangle = stack->top->data; + if (stack->top->next) { + rectangle1 = stack->top->next->data; + } else { + rectangle1 = NULL; + } + } else { + rectangle = NULL; + rectangle1 = NULL; + } + goto next(rectangle, rectangle1, ...); +} + +__code isEmptySingleLinkedStack(struct SingleLinkedStack* stack, __code next(...), __code whenEmpty(...)) { + if (stack->top) { + goto next(...); + } else { + goto whenEmpty(...); + } +} +``` + + +# dataの関係性 + +- DataGearの`...`を考えると、MetaDataGearの情報を使うことで色々表現が出来るのではないかと考える + - DataGearの直積とかが作れるのではないのか的な +- DataGearを取り出す(キャストする)CodeGearがほしい気がする + - 明示的に指定 or 継続先のCodeGearが要求している型に合わせてDataをキャストする +- Cなのでダイナミックなキャストが出来ない +- 型情報を保存する変数が必要そう + - 型タイプのenumとデータそのものへのポインタを持つ + - metaでのみ扱う事ができる +- ....と思っていたら、既にMetaDataGearとして書き込まれていることを発見 + - とはいえほぼ使われていない + +``` +#define ALLOC_DATA(context, dseg) ({\ + Meta* meta = (Meta*)context->heap;\ + meta->type = D_##dseg;\ + meta->size = sizeof(dseg);\ + meta->len = 1;\ + context->heap += sizeof(Meta);\ + context->data[D_##dseg] = context->heap; context->heap += sizeof(dseg); (dseg *)context->data[D_##dseg]; }) + +#define ALLOC_DATA_TYPE(context, dseg, t) ({\ + Meta* meta = (Meta*)context->heap;\ + meta->type = D_##t;\ + meta->size = sizeof(t);\ + meta->len = 1;\ + context->heap += sizeof(Meta);\ + context->data[D_##dseg] = context->heap; context->heap += sizeof(t); (t *)context->data[D_##dseg]; }) + +#define ALLOCATE(context, t) ({ \ + Meta* meta = (Meta*)context->heap;\ + context->heap += sizeof(Meta);\ + union Data* data = context->heap; \ + context->heap += sizeof(t); \ + meta->type = D_##t; \ + meta->size = sizeof(t); \ + meta->len = 1;\ + data; }) + +#define ALLOCATE_ARRAY(context, t, length) ({ \ + Meta* meta = (Meta*)context->heap;\ + context->heap += sizeof(Meta);\ + union Data* data = context->heap; \ + context->heap += sizeof(t)*length; \ + meta->type = D_##t; \ + meta->size = sizeof(t)*length; \ + meta->len = length; \ + data; }) +``` + +- 現状の`Meta`を取り出すAPI + +- `GET_META(dseg) ((Meta*)(((void*)dseg) - sizeof(Meta)))` + - 現在の構造体のポインタからMetaを取り出す +- `GET_TYPE(dseg) (GET_META(dseg)->type)` + - 型のenumを取り出す +- `GET_SIZE(dseg) (GET_META(dseg)->size)` + - 型のサイズを取り出す +- `GET_LEN(dseg) (GET_META(dseg)->len)` + - 配列 +- `GET_WAIT_LIST(dseg) (GET_META(dseg)->wait)` + - Queueで使う + + +取り出してきたオブジェクトからメタ情報は計算可能 +- 現状はヒープの先端から辿らないとオブジェクトの位置がわからない +- ヒープのデータ構造が次のパターンのどれか + - metaのみ + - meta + data +- 現在の`heap`から逆向き計算できない +- 1つ前のMetaや、型から現在存在しているMeta情報を取り出したい + - ぐりぐり回せば取れるが、データ構造を用意するのが良さそう + - meta情報とポインタだけ持つデータ構造 + + +## meta構造体 + +- 従来実装 + +```c +typedef struct Meta <Type, Impl> { + enum DataType type; + long size; + long len; + struct Queue* wait; // tasks waiting this dataGear; +} Meta; +``` + +- 変更後 + - `union Data* data`をいれた + +```c +typedef struct Meta <Type, Impl> { + enum DataType type; + long size; + long len; + union Data* data; + struct Queue* wait; // tasks waiting this dataGear; +} Meta; +``` + + +- `ALLOC`関係のマクロの中でmetaDataに書き込みに行くように変更 + - オブジェクト自体のポインタを代入など +- `pop_and_push`の例題の場合はリニアに探してもそこまで時間はかからなさそう + +``` +#define ALLOC_DATA_TYPE(context, dseg, t) ({\ + Meta* meta = (Meta*)context->heap;\ + meta->type = D_##t;\ + meta->size = sizeof(t);\ + meta->len = 1;\ + context->heap += sizeof(Meta);\ + meta->data = context->heap; \ + *context->metaData = meta; \ + context->metaData++; \ + context->data[D_##dseg] = context->heap; context->heap += sizeof(t); (t *)context->data[D_##dseg]; }) + +#define ALLOCATE(context, t) ({ \ + Meta* meta = (Meta*)context->heap;\ + context->heap += sizeof(Meta);\ + union Data* data = context->heap; \ + context->heap += sizeof(t); \ + meta->type = D_##t; \ + meta->size = sizeof(t); \ + meta->len = 1;\ + meta->data = data; \ + *context->metaData = meta; \ + context->metaData++; \ + data; }) +``` + +- pop_and_poshでテストしてみた + +```c +__code insertTest1(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) { + String* str = &ALLOCATE(context, String)->String; + str->size = 99; + Meta* secondeMeta = (Meta*)(context->heapStart + (sizeof(Meta)*2)); + printf("seconde: %d\n", secondeMeta->type); + Meta* prevMeta = GET_PREV_META(str); + printf("prev: %d\n", prevMeta->type); + printf("str: %d\n", GET_TYPE(str)); + goto stack->push((union Data*)str, insertTest2); +} +``` + +- 確認したところちゃんと記録されていた + - enumの値がわかればキャストするCodeGearに飛ばして、OutputDataGearとして書き出すことができそう + +``` +(lldb) p *(struct Stack*)((Meta*)*(context->metaData-5))->data +(struct Stack) $31 = { + stack = 0x000000011412eb70 + data = 0x0000000000000000 + data1 = 0x0000000000000000 + clear = C_clearSingleLinkedStack + push = C_pushSingleLinkedStack + pop = C_popSingleLinkedStack + pop2 = C_pop2SingleLinkedStack + isEmpty = C_isEmptySingleLinkedStack + get = C_getSingleLinkedStack + get2 = C_get2SingleLinkedStack + next = C_checkAndSetAtomicReference + whenEmpty = C_checkAndSetAtomicReference +} +``` + +- そういえばNEWとALLOCATEの使い分けがわからない + - contextに積むかつまないかの違いっぽい + - Metaを使いたい場合はcontextに積む必要がある + +```c +#define NEW(type) (type*)(calloc(1, sizeof(type))) +#define NEWN(n, type) (type*)(calloc(n, sizeof(type))) + +#define ALLOC_DATA(context, dseg) ({\ + Meta* meta = (Meta*)context->heap;\ + meta->type = D_##dseg;\ + meta->size = sizeof(dseg);\ + meta->len = 1;\ + context->heap += sizeof(Meta);\ + meta->data = context->heap; \ + *context->metaData = meta; \ + context->metaData++; \ + context->data[D_##dseg] = context->heap; context->heap += sizeof(dseg); (dseg *)context->data[D_##dseg]; }) + +#define ALLOC_DATA_TYPE(context, dseg, t) ({\ + Meta* meta = (Meta*)context->heap;\ + meta->type = D_##t;\ + meta->size = sizeof(t);\ + meta->len = 1;\ + context->heap += sizeof(Meta);\ + meta->data = context->heap; \ + *context->metaData = meta; \ + context->metaData++; \ + context->data[D_##dseg] = context->heap; context->heap += sizeof(t); (t *)context->data[D_##dseg]; }) + +#define ALLOCATE(context, t) ({ \ + Meta* meta = (Meta*)context->heap;\ + context->heap += sizeof(Meta);\ + union Data* data = context->heap; \ + context->heap += sizeof(t); \ + meta->type = D_##t; \ + meta->size = sizeof(t); \ + meta->len = 1;\ + meta->data = data; \ + *context->metaData = meta; \ + context->metaData++; \ + data; }) +``` + + +# 例題 + +- API生やすにも例題が必要な気がする +- chat +- DDP +- file copy +- Bitonic sort +
--- a/user/ikkun/memo/2020/04/27.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/04/27.md Wed Dec 16 15:11:16 2020 +0900 @@ -3,13 +3,6 @@ # 要約 * GeasOSはCbCで記述されており処理単位であるcodeGearの間に自由にメタ計算をはさむことができる。ここにdataGearの状態を記録することにより、ユーザプロセスあるいはカーネルそのもののモデル検査が可能になる。一般的なモデル検査では状態数の爆発は避けられない。記録する状態を抽象化あるいは限定する手法について考察する。 -# 先行研究との違い -* - -# やること -* スケジューラーの作成(iteratorを使用した物) -* depth firstの探索用のスタックに変わるものを作る - # つかうもの excution DPP(make -o とインクルードをつける) @@ -18,14 +11,15 @@ GearsOSにDPPを組み込む デッドロックすることを確認できればおk goto スケジューラーをGearsOSにかえる -par goto もつかう +par goto をつかう 第二フィロソファー使って書く + +# 実装について fork ptrが第二フィロソファー -誰がforkを持ってるかを - +誰がforkを持ってるかを持ってるのがある。 enum action next はいらない 最初にやるのはGearsで第二フィロソファーを動かす -そしたらデッドロックする、滅多にしないだろうけど +そしたらデッドロックする、すぐはしない それをモデル検査で捕まえる。 state.db.cが datagearをバイナリツリー @@ -42,10 +36,9 @@ GearsOSの スケジューラーのqueueがイテレーターの塊、なのでマルチスレッドで動かす。 -シングルスレッドでチェッキングしているものを、複数スレッど動かす。 +シングルスレッドでチェッキングしているものを、複数スレッド動かす。 四段階のお仕事。 -今回の論文はこう言う構築でやりますと言う論文 examplesのしたに 書く。 @@ -54,12 +47,12 @@ twice のところに作っていく。 -Gearsの制御は割り込みされないから、書き込んだ際にレーすコンディションで落ちる可能性がある +Gearsの制御は割り込みされないから、書き込んだ際にレースコンディションで落ちる可能性がある 書き込んで飛ぶけど、書き込みに負けるかもしれない。 これはばいとにっくそバイトにそーとでも -第二フィロソファーを動かすまではやりたい。 +# 第二フィロソファーで取り合え使える規模について 第二フォロソファーは5プロセッサー xv6は1プロセッサー @@ -69,7 +62,9 @@ ページテーブルの状態は馬鹿でかいけど、全てを検証ではなくて、取り合う場合、 メモリが少ない場合にページテーブルを取り合う。 -論文の目次も作る + +# 研究会に向けてやること +論文の目次を作る 最初の手順は第二フィロソファー GearsOSの例題を動かす。 forkの排他制御はシンクロナイズドキューでいけると思うけど、シングルスレッドの検証と相性のいい方法でないといけない。 @@ -77,3 +72,15 @@ +# anatofuzからのmemo (ty) +phils の中の right とleft, Action nextはいらない(nextはmetaにある) + +contextの中には必要がないデータ入っている + +forkとかが握っているアドレスは、有限であってほしい + +forkから見ると状態数は2**5くらい + +do_actionとかはなくなりそう + +
--- a/user/ikkun/memo/2020/04/28.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/04/28.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,4 @@ +# memo pick upをアトミックにやってほしい、ぱルス先輩のがある なくても擬似並列では動く @@ -5,6 +6,11 @@ しかしその場合は失敗する可能性がある 並列にforkなどの並列のやり方について考える余地がある。 +同期系はユーザー側にもあるし、プロセス側にもある +ユーザーとプロセス、システムの切り替えがあるのが普通だが、それのトラップをなくす +システムモードもメタだと考えると、いらないかも +ただその代わり、安全性は事前に保証される必要がある。 + ステイトDBについて 普通のCで書いたある。 ぜんぶCbCにするべきではある、難易度は高い @@ -17,3 +23,7 @@ brew で入れられるようにしてほしい + + +# +luatex
--- a/user/ikkun/memo/2020/05/01.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/05/01.md Wed Dec 16 15:11:16 2020 +0900 @@ -15,8 +15,11 @@ 並列システムのモデルの1つ 大まかに並列なプロセスを忠実にモデルにする化する方法とインターリビングモデルがある インターリビングは + • 並列実行されるイベントは任意の順序で現れる + • 並列なプロセスを線形順序の実行系列として表現する。 + さらにこのインターリビングモデルの中で、同一の並列プロセスを表している実行系列を簡約するこ事を Partial order Reduciton(半順序簡約)という ## 線形時相論理(LtL)とは そもそも時相論理とは時間と真偽の組み合わせのこと。
--- a/user/ikkun/memo/2020/05/19.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/05/19.md Wed Dec 16 15:11:16 2020 +0900 @@ -7,8 +7,10 @@ # CbC_gccのコンパイルが終わっていない。 * なぜか32bitでコンパイルされるてしまう問題、 * 呼び出すリンカーも間違ってはないはずだけど、、、 -* アナグラくんのやつを参考に \ - https://growi.cr.ie.u-ryukyu.ac.jp/user/anatofuz/note/2020/04/28 +* 参考にしたサイトと、アナグラくんの丁寧なまとめ\ +https://solarianprogrammer.com/2019/10/12/compiling-gcc-macos \ +https://growi.cr.ie.u-ryukyu.ac.jp/user/anatofuz/note/2020/04/28 +* # memo * web スライドだと端っこ少し見えるみたいなことが起きる
--- a/user/ikkun/memo/2020/05/21.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/05/21.md Wed Dec 16 15:11:16 2020 +0900 @@ -3,16 +3,19 @@ * 先日話していたようにCbC_gccのコンパイルでエラーが出てる問題を先生とやってきた # 先生とやったこと -* 32bitで出ているので、どこかで32ビットが生成されているからそれを探す、 +* 32bitで出ているので、どこかで32ビットが生成されているからそれを探す\ +$ find . -name '*.o'|wc\ +$ find . -name '*.o'|xargs file |grep 32 * lbgcc # memo * エラーが出ていたshellスクリプトをコピって -ld をはずして tmp.shとした * gcc -v でコンパイルの内容を見ながら 使われてるオプションから --- +``` ./gcc/cc1 hello.c -とすることで中間言語のhello.sが生成される -これならまだライブラリは関係ないので、通る -gcc hello.s とすることで実行ファイルが作成される。 --- \ No newline at end of file +gcc hello.s +``` +中間言語のhello.sが生成してそれを普通のgccでコンパイルする方法、 +これならhello.sが生成されるときはライブラリは関係ないので通る。 +
--- a/user/ikkun/memo/2020/06/23.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/06/23.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,48 @@ -# /user/ikkun/memo/2020/06/23 \ No newline at end of file +# 研究目的 +* 本研究室で開発しているGearsOSではアプリケーションやサービスの信頼性をOSの機能として保証することを目指しており、モデル検査による信頼性の保証方法を確立することで、テストによる保証よりも幅広い保証を行う。 +* ユーザーレベルとシステムレベルと分けることによって、GearsOS自身をGearsOS上で保証する事ができるようになる +* モデル検査の例題としてDPPをOS上で検査する。 + +# 近況報告 +* 先週はすみません。 +* DPPの実装をすすめるにあたって先輩たちのコードを覗いてます。 +* 就活は、、、、 + + +# philosohers実装 +* DPPでの philosohers を並列に呼び出す必要があるので、twice の例題を参考に書き直す +* dpp3.cbc がphilosoherのアクションになる。 +* 現状のscheduler.cbc だと 次のアクションへcase文でgoto する部分があるのでこれをそれぞれのスレッドごとに実行するようにする。 + +* DPPコンパイル出来ない、、 +--- +$ /usr/local/Cellar/cbcgcc/10.0.1/bin/gcc -v scheduler.cbc +Undefined symbols for architecture x86_64: + "_create_queue", referenced from: + _task_entry1 in cc05rju1.o + _init_final in cc05rju1.o + "_eating", referenced from: + _do_action in cc05rju1.o + "_enqueue", referenced from: + _task_entry2 in cc05rju1.o + "_hungry1", referenced from: + _do_action in cc05rju1.o + "_hungry2", referenced from: + _do_action in cc05rju1.o + "_pickup_lfork", referenced from: + _do_action in cc05rju1.o + "_pickup_rfork", referenced from: + _do_action in cc05rju1.o + "_putdown_lfork", referenced from: + _do_action in cc05rju1.o + "_putdown_rfork", referenced from: + _do_action in cc05rju1.o + "_thinking", referenced from: + _do_action in cc05rju1.o +ld: symbol(s) not found for architecture x86_64 +collect2: error: ld returned 1 exit status + +--- + + +
--- a/user/ikkun/memo/2020/06/30.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/06/30.md Wed Dec 16 15:11:16 2020 +0900 @@ -8,10 +8,10 @@ # DPP * dining phirosoper ploblem の略でデッドロック検証モデル。 * 現在のタスクはマルチスレッド実装。 - - - - +* contex.h 自動生成するプログラムがみつけられない、、、 +* アナグラくんがちょうどmakeのやり方のページ書いてた oh... https://growi.cr.ie.u-ryukyu.ac.jp/Gears/introduction/parallel_execution +* +* とりあえず パルス先輩の書いてたタスクマネージャーを参考に書く。
--- a/user/ikkun/memo/2020/10/20.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/10/20.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,17 @@ -# /user/ikkun/memo/2020/10/20 \ No newline at end of file +# GearsOSにおけるモデル検査 + +# 研究目的 +* 一般的にアプリケーションはテストと言われる方法を用いてバグを発見し修正することで信頼性を高める、しかしバグの再現性が低い場合には発見は困難になる。この際にはデバックを行うプログラマーの経験による予測が必要であり、予想した原因に基づいて1つ1つチェックをしていく必要がある。 +* モデル検査とは、検証したいアプリケーションの状態遷移記述を用いて行われ、特定の状態から遷移する全ての組み合わせに対して検査を行うことで、信頼性を保証する。 +* 当研究室で開発しているGearsOSはアプリケーションやサービスの信頼性をOSの機能として保証することを目指しており、モデル検査による検証や、定理証明を用いる事での信頼性へのアプローチを行っています。 +* 本研究ではGearsOSにおけるDPPのモデル検査を行うことでGearsOSにおけるモデル検査手法の確立と、さらにGearsOS上での自身のモデル検査について研究する。 + +# 実装の全体像 +* モデル検査を行うための例題としてのDPPを扱う。DPPは並列で動きつつ、スレッド間でデータのやり取りを行う。このためデッドロックが起こる。今回の研究ではこのデッドロックをモデル検査で検出する。 +* スレッド間でのデータのやり取りはCASを用いているSynchronizedQueueでデータの保証を行う。 +* モデル検査を行うために、DPPを動かしつつstatmantDBとmemoryTreeによってログを保存する。 + +# 現在 +* TaskManagerImplを通して、cbcの復習終わりました。(ようやく) +* いまからTaskManagerのinterfaceを書く。 +* \ No newline at end of file
--- a/user/ikkun/memo/2020/12/01.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/12/01.md Wed Dec 16 15:11:16 2020 +0900 @@ -11,8 +11,38 @@ * スレッド間でのデータのやり取りはCASを用いているSynchronizedQueueでデータの保証を行う。 * モデル検査を行うために、DPPを動かしつつstatmantDBとmemoryTreeによってログを保存する。 -# 現在 -* 先週配信しながら作業するって話でしたが、結局していないので時間決めてやりたいと思います(13~17時)午前中は研究以外をする予定。 +# コメント +interface を通してぐるぐる回るようにしないといけない + +dpp_common.h でアクション_next はいらない + +phils はリソース? + +goto meta を読んでる部分で、順々によんでやるやつにすればいい + +cpu worker を持ってる、それぞれcontextのリストを持っているので、その分だけスレッドを投げてやる +cpuworkerは本来複数いて、 +実行可能な複数のqueueのうちどれかを動かしてやる。 -* TaskmanagerImplの作業していて、mutexってなんぞしました。 -* taskManagerImplからDPP呼び出す。 \ No newline at end of file +スレッドはcpuの数をこえるので、こえた分どうにかしないといけない。 +スレッドプールに投げるけど、そのあとgotometaで切り替えてやらないといけない。 +taskは赤黒きにぶっこんでたような +par goto もCPUの数以上に投げると、終了を待ってしまうので、それだといけない +セリウムだと、もっとベクトライズされていたのでタスクが小さい想定だった。 +Gearsの場合は自分でタスクを小さくする想定、しかしphiloは終わらないので、自分でgotometaでタスクマネージャーに戻るかを選択しないといけない。これはメタ側に書かれるもの。 + +C++?? +cpuwokerのモデルチェッキングと、それようのgoto metaの作成 + + +synchonizedqueue はシングルワーカーだと動かない。 +モデルチェッキングワーカーが持ってる複数スレッドの中でエミュレートしないといけない。 +chack and set + +Atomic で chack and setq は書かれている。 +こいつはcpuwokerからは特別扱いされないと行けない。こいつが来たときに優先できるように。 + +今はコンストラクタをファンクションコールにしているけど。それを~するとTaskManagerの方も簡単になりそう + +第2フィロソファーをそのまま動かしたい。 +第二フィロソファーは清水君のやってる新しい感じで書く必要がある。 \ No newline at end of file
--- a/user/ikkun/memo/2020/12/08.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/12/08.md Wed Dec 16 15:11:16 2020 +0900 @@ -8,18 +8,23 @@ # 実装の全体像 * モデル検査を行うための例題としてのDPPを扱う。DPPは並列で動きつつ、スレッド間でデータのやり取りを行う。このためデッドロックが起こる。今回の研究ではこのデッドロックをモデル検査で検出する。 -* スレッド間でのデータのやり取りはCASを用いているSynchronizedQueueでデータの保証を行う。 +* スレッド間でのデータのやり取りはCaSを用いているSynchronizedQueueでデータの保証を行う。 * モデル検査を行うために、DPPを動かしつつstatmantDBとmemoryTreeによってログを保存する。 # 目次構成 -* 序論(研究目的、背景) -* モデル検査によるアプローチ(他のモデル検査ツール、CbCと検証、) -* GearsOSによるモデル検査手法(DPP、タブロー展開、) -* GearsOS上での実装(pargoto、synchronizedqueue、cpuworker、statmantDB、memoryTree -- pargoto でのphilsの起動 -- cpuworkerをSynchronizedqueueのCaS優先に -- 状態を保存するstatmantDB、memoryTree -- -* 評価 -* 結論 +* 1_序論(研究目的、背景) +* 2_モデル検査によるアプローチ(他のモデル検査ツール、CbCによる検証、goto) +* 3_GearsOSによるモデル検査手法(DPP、タブロー展開、) +* 4_GearsOS上での実装(pargoto、synchronizedqueue、cpuworker、statmantDB、memoryTree + pargoto でのphilsの起動 + cpuworkerをSynchronizedqueueのCaS優先に + 状態を保存するstatmantDB、memoryTree +* 5_評価 +* 6_結論 + +# 引っ越しました +* 寮の改装のためにあと数ヶ月しかいないのに追い出されました。 +* 改装後の北辰に移動しました。光回線が使えるそうですが、2年契約なので数カ月後には違約金で1万近く取られる可能性が +* 今のところは午前中が70Mbps、ゴールデンタイムが1.9Mbpsぐらいでてるので大丈夫そう。 +* 引っ越して一番良かったのはお風呂が同じ階にあるk
--- a/user/ikkun/memo/2020/12/15.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/memo/2020/12/15.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,28 @@ -# /user/ikkun/memo/2020/12/15 \ No newline at end of file +# GearsOSにおけるモデル検査 + +# 研究目的 +* 一般的にアプリケーションはテストと言われる方法を用いてバグを発見し修正することで信頼性を高める、しかしバグの再現性が低い場合には発見は困難になる。この際にはデバックを行うプログラマーの経験による予測が必要であり、予想した原因に基づいて1つ1つチェックをしていく必要がある。 +* モデル検査とは、検証したいアプリケーションの状態遷移記述を用いて行われ、特定の状態から遷移する全ての組み合わせに対して検査を行うことで、信頼性を保証する。 +* 当研究室で開発しているGearsOSはアプリケーションやサービスの信頼性をOSの機能として保証することを目指しており、モデル検査による検証や、定理証明を用いる事での信頼性へのアプローチを行っています。 +* 本研究ではGearsOSにおけるDPPのモデル検査を行うことでGearsOSにおけるモデル検査手法の確立と、さらにGearsOS上での自身のモデル検査について研究する。 + +# 実装の全体像 +* モデル検査を行うための例題としてのDPPを扱う。DPPは並列で動きつつ、スレッド間でデータのやり取りを行う。このためデッドロックが起こる。今回の研究ではこのデッドロックをモデル検査で検出する。 +* スレッド間でのデータのやり取りはCaSを用いているSynchronizedQueueでデータの保証を行う。 +* モデル検査を行うために、DPPを動かしつつstatmantDBとmemoryTreeによってログを保存する。 + +# 目次構成 + +* 1_序論(研究目的、背景) +* 2_モデル検査によるアプローチ(他のモデル検査ツール、CbCによる検証、goto) +* 3_GearsOSによるモデル検査手法(DPP、タブロー展開、) +* 4_GearsOS上での実装(pargoto、synchronizedqueue、cpuworker、statmantDB、memoryTree + pargoto でのphilsの起動 + cpuworkerをSynchronizedqueueのCaS優先に + 状態を保存するstatmantDB、memoryTree +* 5_評価 +* 6_結論 + +# mindmap + +![GearsOS model chacking.jpg](/attachment/5fd88f5e0b8e3d0049117561)] \ No newline at end of file
--- a/user/ikkun/slide/2020.4.14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/slide/2020.4.14.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,15 @@ -# Gears OSにおける multi threadにおけるプログラム検証 +# Gears OSのモデル検査を用いた設計 + +# 研究目的 +プログラムの信頼性を保証するには、プログラムの証明、またはモデル検査がある。 +モデル検査を行う場合はプログラムの持ち得る全ての状態を調べる事になり、SPINかjava path finderが一般的には用いられるが、SPINで行う場合にはPROMELAに書き換える必要がありjava path finder はjavaのバイトコードを検証するためのものであるが、大きなプログラムの検証や複数プロセスが扱えないなどの問題点がある。 +本研究ではGeasOS上でDPPのモデルチェッキングを行ことで、書き換えを必要とせず、複数プロセスのプログラムの検証を行う + + + # 要約 * CbC は処理の移行を goto 用いて行い、データ構造はdate gearにより保持する事でプログラムの処理をcode gear毎の独立したものにする。 * Geas OS はCbCで記述されおり、処理を変更する事なく処理の間に自由にメタ処理を挟む事ができる、これにスケジューラーを挟む事でマルチスレッド処理などが可能となる。 -* メタ計算部分にモデルチェッキングを入れる事でプログラムを実行しながらにして証明することが可能となる。 \ No newline at end of file +* メタ計算部分にモデルチェッキングを入れる事でプログラムを実行しながらにして証明することが可能となる。 +* モデルチェッキングはdepth firstで行われる、しかしGeasOSはstackがないため、ポインタを使って戻ることができない、そこで \ No newline at end of file
--- a/user/ikkun/slide/sigos.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ikkun/slide/sigos.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,61 +1,239 @@ +--- +marp: true +title: Gears OSでモデル検査を実現する手法について +paginate: true +--- + +# <!--fit--> Gears OSでモデル検査を実現する手法について +- 東恩納 琢偉 + - 琉球大学理工学研究科 情報工学専攻 +--- + # 研究目的 -- OS上ではさまざまなアプリケーションやサービスが提供されるが、予期しないエラーが起こり得る -- 本研究室で開発している GearsOS ではアプリケーションやサービスの信頼性をOSの機能として保証することを目指しており、モデル検査による保証について考察する -- GearsOS そのものをGearsOS上でモデル検査することに関しても考察する。 + +- OS上ではさまざまなアプリケーションやサービスが提供されるが、予期しないエラーが起こり得る。 +- 本研究室で開発している GearsOS ではアプリケーションやサービスの信頼性をOSの機能として保証することを目指しており、今回はモデル検査による信頼性の保証について考察する。 +- またGearsOS そのものをGearsOS上でモデル検査する手法について考察する。 +--- # Gears OS -- アプリケーションやサービスの信頼性をOSの機能として保証することを目指している。 -- 信頼性を保証する手法としてモデル検査を上げている。 -- GearsOS は軽量継続を基本とする言語 CbC を用いたOSの実装である。 + +- 軽量継続を基本とする言語 Contnution based C を用いて記述されている。 +- アプリケーションやサービスの信頼性をOSの機能として保証することを目指しています。 +- 信頼性を保証する方法としてモデル検査による検証や、定理証明を用いる事で、信頼性へのアプローチを行っています。 + +--- # Continution based C -- CbC とは C言語をベースとして、開発された言語でC言語との違いはプログラムにおける goto 文を用いて CodeGear という単位で遷移する。 + +- CbC とは C言語をベースとして、開発された言語でC言語との違いはプログラムにおける goto 文を用いて CodeGear という単位で遷移する。 - goto 文による遷移は関数呼び出しとは異なり、stackや環境を隠して持つことがない。 -<div style="text-align: center;"> - <img src="../paper/pic/meta_gear.pdf" alt="normalCodeGear" width="600"> -</div> +- 以下は CbC によって記述された codeGear です。 +``` +code pickup_lfork(PhilsPtr self, TaskPtr current_task) +{ + if (self->left_fork->owner == NULL) { + self->left_fork->owner = self; + self->next = pickup_rfork; + goto scheduler(self, current_task); + } else { + self->next = hungry1; + goto scheduler(self, current_task); +} +``` + +--- + +# goto + +- goto 文はCbC における状態遷移に使われ、 goto の直後に遷移先を記述することで接続される。 +- goto による遷移は軽量継続と言い、関数呼び出しのような環境変数を持たず、遷移元の処理に囚われず、遷移先を自由に変更する事が可能である。これにより処理の間にメタレベルの計算を挿入する事が可能である。 +- CbC における遷移記述はそのまま状態遷移記述にすることができる。 + + +<center><img src="./pic/input-outputDataSegment.svg" alt="" width="100%" height="100%" ></center> + +--- + # dataGear と meta dataGear + - CbC における入力は dataGear と呼ばれる構造体になっており、ノーマルレベル とメタレベルがある。 - メタレベルには計算を行うCPUやメモリ、計算に関するノーマルレベルのdataGearを格納するcontext などがある。context は一般的なOSのプロセスに相当する。 -# goto +--- + +# stub CodeGear -# 既存のモデル検査手法 -- 一般的に利用されるモデル検査ツールとしてSPINと java path finder(JPF)がある --- SPIN では以下の性質を検査することができる -* アサーション -* デッドロック -* 到達性 -* 進行性 -* 線形時相論理で記述された仕様 +- メタレベルから見ると、code Gearの入力はcontext ただ1つである。 +- ノーマルレベルからMeta dataGear であるcontext を直接参照してしまう事は、ユーザーがメタレベルに対して自由に記述できてしまう事になる。 +- この問題を防ぐため context から必要なノーマルレベルのdata Gearを取り出して、ノーマルレベルのcodeGearを呼び出し渡す処理を行う仲介役として、メタレベルの stub CodeGearがある。 + +``` +__code clearSingleLinkedStack(struct Context *context,struct SingleLinkedStack* stack,enum Code next) { + stack->top = NULL; + goto meta(context, next); +} -- JPF では以下の性質を検査することができる -* スレッドの可能な実行すべてを調べる -* デッドロックの検出 -* アサーション -* Partial Order Reduction +__code clearSingleLinkedStack_stub(struct Context* context) { + SingleLinkedStack* stack = (SingleLinkedStack*)GearImpl(context, Stack, stack); + enum Code next = Gearef(context, Stack)->next; + goto clearSingleLinkedStack(context, stack, next); +} +``` + +--- + +# contextと状態数 -# タブロー展開と状態数の抽象化 -- GearsOS におけるモデル検査はタブロー展開を用いることでデッドロックを調べる。 -- タブロー法は生成可能な状態のすべてを生成する手法である。 -- 生成された状態の組み合わせを深さ優先探索で調べ、木構造で保存する。この時、同じ状態の組み合わせがあれば抽象化し共有することで、状態数が増えすぎる事を抑える。 -# -- GearsOS による検証用プログラムとして Dining Philosohers Ploblem を用いる。 +- プログラムの非決定的な実行は、入力あるいは並列実行の非決定性から生じる。 +- 並列実行の非決定性は、同時に実行される codeGear の順列並び替えになるので、それらの並び替えを生成し、その際に生じるcontextの状態を数え上げる事で、モデル検査を実装できる。 +- しかし、このcontextの状態はとても巨大になる事がある、そのためそれらを抽象化する必要性がある。 + +--- + +# GearsOSの実装 + +- codeGear は処理の基本単位であり、並列処理などにより割り込まれることなく記述された通りに実行される必要がある。 +- しかし一般的には、他のcodeGearが共有されたdataGearに競合的に書き込んだり、割り込みにより処理が中断したりする。 +- しかし、GearsOSにおいては正しく実行される事を保証されるように実装されているとする。 +--- + +# モデル検査 + +- モデルとは検証したいアプリケーションやサービスの振る舞いや性質を抽象化して表現したものであり、抽象化の手法には以下のようなものがある。 + + 状態遷移モデル + 論理モデル + 組み合わせモデル + フローモデル ..etc +- このモデルが仕様を満たしているかどうかを検査するのがモデル検査である。 +- 検査の要点によってモデルを使い分ける必要性がある。 + +--- + +# 状態遷移モデル + +- 今回行うモデル検査は状態遷移からプログラムの振る舞いを検証する。 +- 状態遷移モデルとは、処理前と処理後の状態をつなぎ合わせる手法である。 + +| 構成要素 | | +| ---------- | --------------------------------- | +| 状態 | プログラムの状態 | +| 初期状態 |何らかの処理、計算が行われる前の状態| +| 終了状態 |処理、または計算が行われた状態 | +| 処理(計算) |状態を変化させる | +| 遷移条件 |状態が分岐する際の条件 | + +--- + +# 既存のモデル検査手法(SPIN) +- 一般的に扱われるモデル検査ツールとしてSPINがある。 +- SPIN はPromela (Process Meta Language)で記述される。 +- C言語と似た文法を持ち、元は通信プロトコルの検証として開発された言語であり、検証機を生成し、コンパイルと実行を行うことで検証される。 +- チャネルを使って通信や並列動作を記述する。 +- 有限オートマトンに変換してモデル検査を行う。 +- Promelaへの書き換えが必要 +- SPIN での検査可能な性質 + アサーション + デッドロック + 到達性 + 進行性 + 線形時相論理で記述された仕様 + +--- + +# 既存のモデル検査手法(Java path Finder) + +- Java Path Finder はjavaプログラムの検査ツール +- java バーチャルマシン(JVM) を直接シュミレーション実行している、これによりjavaのバイトコードを直接実行可能である。 +- バイトコードを状態遷移モデルとして扱い、実行時に遷移し得る状態を網羅的に検査している。 +- 実行パターンを網羅的に調べるため、複数のプロセスの取り扱いができず、また状態空間が巨大な場合は、一部を抜き出して検査する必要がある。 +- JPF で検査可能な性質 + スレッドの可能な実行すべてを調べる + デッドロックの検出 + アサーション + Partial Order Reduction + +--- + +# モデル検査手法について +- GearsOS におけるモデル検査はcode gear 単位の順列組み合わせによって行われる。 +- codegear 実行後の状態を、データベースに格納する。 +- 新しい状態が生成されなくなった時モデル検査が終了する。 +- 哲学者5人が次の状態に進めなくなった時をデッドロックとして検出する。 +- 必要な状態はフォークの状態だけになるので、それ以外の状態は無視することができる。 +- これにより状態数を下げることができる。 +- つまり、問題に合わせたメタ計算により、モデル検査の状態数を下げることができる。 +- GearsOS による検証用プログラムとして Dining Philosohers Ploblem (DPP)を用いる。 + +--- + +# DPP(dining philosohers ploblem) + +- 5人の哲学者が円卓についており、各々スパゲティーの皿が目の前に用意され、スパゲティーは絡まっている為2つのフォーク使わなければ食べれない。 +- フォークは皿の間に1本ずつの計5本しかないため、すべての哲学者が同時に食事することはできず、また全員がフォークを1本ずつ持ってしまった場合、誰も食事することは出来ない。この状態をデッドロックとする。 +<center><img src="./pic/dpp_image.svg" alt="" width="48%" height="48%" ></center> + +--- + # DPP -- 5人の哲学者が円卓についており、各々スパゲティーの皿が目の前に用意され、スパゲティーは絡まっている為2つのフォーク使わなければ食べれない。フォークは席の間に1本ずつある。哲学者は、思考とフォークを持つ、食事する。 -- 状態は以下のようになる -* Pickup Right fork -* Pickup Left fork -* eating -* Put Right fork -* Put Left fork -* Thinking + +- 状態の構成要素は次の6つからなる。 +`Pickup Right fork` ` Pickup Left fork` `eating` ` Put Right fork` `Put Left fork` ` Thinking ` + +<right><img src="./pic/dpp_image.svg" alt="" width="55%" height="55%" ></right> + +--- + + +# GeasOS におけるDPP実装(1/3) + +- 5つのスレッドで並列処理を行う事で、哲学者の行動を再現する。 +- gearsOSには並列機構の par goto があり、これを使用するスケジューラーによって並列にスレッドを起動する。 +- par goto は引数として dataGear と実行後に継続する _exit をわたす。 +- par goto は複数スレッドでの実行であるので、各スレッドで実行後に__exitに継続する事で終了する。 + +--- + +# GearsOS におけるDPP実装(2/3) + +- マルチスレッドでのデータの一貫性を保証する手法としてCheck and Set (CAS) がある。 +- CAS を用いて値の比較、更新をアトミックに行う。 +- CAS は書き込みの際に、書き込む MetaCodeGear に更新前と更新後の値を渡し、更新前の値が保存されているメモリ番地の値と比較し同じデータがであれば書き込みを行う。異なる場合はほかからの書き込みがあったとみなし、値の更新に失敗し、もう一度CASを行う。 +- DPPの例題ではフォークがスレッドで共有されるデータにあたるので、CAS を用いることによってスレッド間での同期を行う。 + +--- -# GeasOS におけるDPP実装 -- 5つのスレッドで並列処理を行う事で、哲学者の行動を再現する。 -- gearsOSには並列機構の par goto があり、これを使用するスケジューラーによって並列にスレッドを起動する。 -- フォークの管理をsynchronixed Queue を用いることによってスレッド間での同期を行う。 -- スレッドの状態遷移に metaCodeGear を 挟みメタレベルで各スレッドの状態の保存を行う。 \ No newline at end of file +# GearsOS におけるDPP実装(3/3) +- 5つのスレッドで行われる処理の状態は6つあり、それぞれを状態変数で表す。 +- この状態遷移は goto next によって遷移し、metaCodeGear を 挟みメタレベルで各スレッドの状態を 各スレッドごとに用意した Memory Tree に保存する。 +- Memory Tree はstateDBによってまとめられ、同じ状態は共有される。 +- またDPPにおける状態遷移は無限ループであるため、stateDBを用いて同じ状態を検索することで、終了判定を行う。 + +--- + +# GearsOS でのモデル検査を実現する方法について + +- DPP をGearsOS 上のアプリケーションとして実装する。 +- DPP を codeGear のシャッフルの1つとして実行する。 +- 可能な実行を生成する iterator を作成する +- 状態を記録する memory Tree と stateDB を作成する。 + +--- + +# GearsOS の GearsOS によるモデル検査 + +- GerasOS そのものも codeGear で記述されている。 +- CPU毎の C.context、共有するkernel のK.context、ユーザープログラムのU.context と考えることができ、これらはmeta dataGear であるK.context に含まれている。 +- U.context がDPPのような単純なものならば、OS全体のcontext も複雑にはならないため、これらをGearsOSで実行することが可能である。 +- GearsOS を含む codeGear のシャッフル実行を行う事ができれば、DPPと同じようにモデル検査を行う事ができる。 +- 検査する codeGear と検査される codeGear は同じものであるが、実行する meta codeGear を異なっている。 +- 異なるmeta codeGear を指定してコンパイルすることで実現できる。 + + + + +
--- a/user/jogo/note.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/jogo/note.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,1 @@ -ゼミの記事 \ No newline at end of file +$lsx(tree=leaf,hierarchy=off) \ No newline at end of file
--- a/user/jogo/note/2020/12/15.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/jogo/note/2020/12/15.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,28 @@ -# \ No newline at end of file +# 研究目的 + +多段 ssh 接続を管理する sshr の改良 + +## 研究内容 + +目的のサーバにアクセスするために外部からサーバへのアクセスへは踏み台サーバからのアクセスが必要である.踏み台サーバでは外部から第三者に乗っ取られることや不特定多数の攻撃の中継地点を防止するためのものである.しかし,利用している踏み台サーバが停止すると学内での復旧作業が必要になってしまうそこで,新規踏み台サーバとしてsshrを提案する.sshrは鶴田博文氏が作成したものである.sshrはシステム管理者が組み込み可能なフック関数を用いてシステム変化に追従できるsshプロキシサーバである.本稿ではsshrを改良し弊学へ利用できるように実装をした. + +# sshrのリポジトリをfetchした +- 以前PR送ったやつを取り込んだ + + +# 修論のためのマインドマップを書き始めた +- mindmaisterというサービスを用いて書いていた +- freemindはすぐ落ちていたが宮平くんから1.0.0のfreemindをいただいたので試したら落ちなかった +- freemindで書いていきます + +# シス管 +- 和田先生の新しい部屋のネットワークが繋がらないということでフロアスイッチを見てきた +- アナグラくんが言った通物理的に繋がっていなかった +- 方法としてはあきポートが一つだけあったので確認してそこに接続するかvlanを複数割り当てるかのどちら + + +# アドベントカレンダーの記事を書いた +- 就活とサクナヒメの感想のブログ +- 就活のはわりと見られていてみんなきになってることなのかと感じた + +
--- a/user/jogo/メモ/2020/04/21/zemi/20200421.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/jogo/メモ/2020/04/21/zemi/20200421.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,16 +5,20 @@ - dockerの嫌なところ ## シス管 +回線弱々でこまりました -mattermostのバージョンアップとメモリ,CPU,容量マシマシにできた +mattermostのバージョンアップとメモリ,CPU,容量マシマシにできた(mkくんありがとうございます) + +mattemostのデータベースレプリケーション用再構築 ## 長田研の方の研究 +研究目的 sshの踏み台サーバの提案 踏み台サーバの提案としてsshrの導入 vmに立てていて実装はgolang -DBにuser,pub-key,host先を置いておいてsshできる +DBにuser,pub-key,hostのテーブル置いておく, 新規性的にはldapとの連携がとれる
--- a/user/jogo/メモ/2020/04/28/zemi.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/jogo/メモ/2020/04/28/zemi.md Wed Dec 16 15:11:16 2020 +0900 @@ -14,9 +14,15 @@ 公開鍵をsshr自体に渡すことでsshr自体での一元管理ができる. +コードを読んでてsshrの中で使っている関数で使用するものを使いつつ洗い出している最中です + +sshのユーザー名を参照する関数とかを使いながらとりあえず自分だけのみでお試し中です + +今の所コードを読んで # 研究室周り 実験3の内容が決まった. b4生が長田研のサーバに入れるようにするために行なった + # 雑談 wimaxを契約した
--- a/user/jogo/メモ/2020/06/16/zemi/20200616.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/jogo/メモ/2020/06/16/zemi/20200616.md Wed Dec 16 15:11:16 2020 +0900 @@ -13,14 +13,22 @@ 信頼性をあげてるけど、どうやるか、バグいくつ見つけたとかそういうところ - +# 比較項目 1. 既存のsshとsshrの速度についての比較(yomitan経由との比較) 2. セキュリティ周りについて. 3. 従来の踏み台サーバとの比較 4. 新規踏み台サーバを追加することでの利点 - -1. sshとsshrでの速度を計測 +# 比較項目の内容 +1. sshとsshrでの速度を計測, 2. 秘密鍵,公開鍵の登録,または実際に外部公開したさいの対策 3. yomitanサーバとの比較 -4. sshrサーバを追加することでの管理者側の利点,理療者側の利点. \ No newline at end of file +4. sshrサーバを追加することでの管理者側,利用者側の利点,欠点 + +# タイトル + +sshrを用いた新規踏み台サーバの構築 検証 + +## subject + +弊学の踏み台サーバは学科のリソースへのアクセスなどを行うために用意されている.2020年度はシステムを移行することになっているためシステム構成が変わる可能性がある.そこで今回提案する踏み台サーバとしてsshrを提案する.sshrはシステム管理側がクライアント側に意識をしてもらうことなくシステム構成の変更を可能にするためのである.本稿では新システム移行に対して柔軟に対応できる,新規踏み台サーバとしてsshrサーバの構築を行う.
--- a/user/jogo/メモ/2020/06/30.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/jogo/メモ/2020/06/30.md Wed Dec 16 15:11:16 2020 +0900 @@ -51,8 +51,9 @@ システム移行と被ってる.... -sshrのsshr/cryptの実装への理解が足りていなかったので読みつつやっている -前回アナグラ君と読んで割とわかったので追いつけなかった分を読んで実装していく +- sshrのsshr/cryptの実装への理解が足りていなかったので読みつつやっている +- 前回アナグラ君と読んで割とわかったので追いつけなかった分を読んで実装していく +- 久しぶりにsshrのりポジトリをプルしたらバグっていたので初めてossにPRを送ってmergeされました!
--- a/user/matac42/note/2020/12/01/test.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/matac42/note/2020/12/01/test.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,30 @@ -初めてのgrowi \ No newline at end of file +# 初めてのgrowi +bar +## steins +* gate +* el + * p + * c +### A +foo +#### B +higa +##### C +huga +###### D +hoge +###### E +hello + +`command` + +``` +command +lines +``` + + what is this. + next line + +`$cat` +`%less`
--- a/user/matac42/note/2020/12/15.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/matac42/note/2020/12/15.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,9 +1,30 @@ # 今日やったこと * toeic対策 * part別攻略が一旦終わった. +* キッチンカーでお昼を買った. + * 琉大にキッチンカーが来ていたので行ってみた. + * くによしのステーキ丼を食べた. + * ¥700 + * いい感じの量で美味しかった.(ふたを切らしてしまったらしく¥100まけてもらった.) * enpit * 頂いた写真を追加した. - + * デモ + * 成果発表資料作成 + * デモ練習 +* ゼミ + * カレーの具が毎回変わって嬉しい. + * masatoがsingularityのsifの作り方を学んだ. + * localeは言語・地域設定 + * mindmapの使い方 + * 書けるだけたくさん書いて広げるのが良さそう. # 明日は * toeic対策 - * 模試をやりたい. \ No newline at end of file + * 模試をやりたい. +* 今日gcdsの設定できなかったのでやりたい. +# ゼミのメモ +* hugoかmarkdownでゼミ用の資料を作りたい. +* osの課題用のsingularity sifを作って欲しい. + * amaneとdaruで使えるように. +* 研究室のものが動かせるsingularityのコンテナを立てられるようにしたい. +* 岡崎先生に頼むとwindowsのライセンスもらえるからmacbook airでdualbootできるようにしたい. +* mindmap書いてみようかな. \ No newline at end of file
--- a/user/menikon/thesis.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/menikon/thesis.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,8 +1,7 @@ # CbC による xv6 の FileSystem の書き換え -author: Takahiro Sakamoto, Shinji Kono +- 並列信頼研 -profile: 琉球大学工学部情報工学科並列信頼研 - +- 坂本昂弘 ## 研究目的 - OSに対し高い信頼性を実現させたい @@ -10,152 +9,257 @@ - 前段階としてシンプルであるが基本的な機能を揃えたOSであるxv6をCbCで書き換える -- CbCは処理の基本単位をCodeGearとし、stackに値を積む事なくCodeGear間を遷移する +- xv6のFilleSystemをCbCで記述し、なるべく処理を細分化実装してやる + +--- + +# Continuation based C +- 状態遷移ベースで記述できる言語(以下CbC) +- C の関数呼び出しとは異なり、stack に値を積まない +- Code Gear + - 基本的な処理の単位 + - goto 文で遷移する +- Data Gear + - Code Gear からアクセスできるデータの単位 + - 引数など + + +--- +# Code Gear による継続 +- Code Gear の処理の間を goto によって遷移していく +- __code CodeGear名 で定義 +![](https://i.imgur.com/etfQund.png) + + +--- + +# Data Gear の受け渡し +- Code Gear からアクセスできるデータ +- Code Gear の計算の入力と、計算の出力が存在する + +![](https://i.imgur.com/3E0DGWA.png) + + +--- + +# Data Gear の一種であるContext -- CodeGear間は状態遷移であるためOS内部を明確化することができる +- Contextには実行するプログラムの全てのData Gear と Code Gear が登録されている +- ユーザープロセスに対応して1つのcontextが存在する +- CodeGearの入出力は、一度Contextに書き込まれる +- Contextは実行している処理の状態を保持している + - そのためContextを見れば、実行中の処理がわかる + ![](http://ie.u-ryukyu.ac.jp/~e165723/context.pdf) + +--- + +# Xv6 +- MIT の講義用教材として作られたOS +- xv6 は Unix の基本的な構造を持っている。 + - プロセス + - 仮想メモリ + - ファイルシステム +- Xv6 をCbCで書き換える -- 本研究ではOS内部の明確化を実現し信頼性を向上させるためにCbCを用いFileSystemを書き換える +--- + +# Xv6のFileSystem +- FileSystem は コンピュータの資源を操作するための OS が持つ機能である +- xv6 の FileSystem は、デバイスやプロセス、カーネル内の処理をする際の情報などをファイルとして扱う +- inodeを用いファイルの管理や操作を行う +- inodeはディスク上にブロックを持つ木構造のデータ構造 +--- + +# Xv6の書き換え方針 +- 段階的に書き換えていきたい +- FileSystem を書き換える理由 + - FileSystem は状態が複雑に変化するため、信頼性を保証する必要がある +- インターフェースを定義、実装する +- 状態遷移ベースにしてやる + +--- -## 研究概要 -- -## Continuation based C -* Continuation based C (CbC) はこの Code Gear 処理の単位としてプログラミング言語として開発している。 -* Code Gear は 関数呼び出し時の環境を使わずに次の Code Gear へと goto 文によって遷移する -* この goto 文による遷移を軽量継続と呼ぶ -* 継続を用いることによって状態遷移ベースでのプログラミングが可能である -* CbC は C と互換性のある言語なので、C の関数も呼び出すことができる -## CbC のコード例 -* CbC では Code Gear は \_\_code Code Gear 名 (引数) の形で記述される -* Code Gear は戻り値を持たないので、関数とは異なり return 文は存在しない -* goto の後に Code Gear 名と引数を並べて、次の Code Gear の遷移を記述する +# インターフェースの導入 +- CbC のモジュール化の方法 +- Javaのインターフェースと同様 +- インターフェースによるメリット + - 複雑な状態の解消 + - 入力の切り替えによる実装の入れ替え +- 実装は別で定義し、呼び出す + - 後ほど説明 + +--- + +# インターフェースの定義 +- Xv6 の FileSystem の インターフェース +- typedef struct の直後にインターフェース名(fs)を書く +- fs で使う Code Gear を登録する +- Code Gear は __code CodeGear名(引数); で記述する + - 引数が Data Gear に相当する +- 第1引数の Impl* fs がインターフェースの実装の型になる +- privateな実装側のヘッダーファイルも インターフェース と同じように用意する +``` c +typedef struct fs<Type,Impl> { + __code readsb(Impl* fs, uint dev, struct superblock* sb, __code next(...)); + __code iinit(Impl* fs, __code next(...)); + __code ialloc(Impl* fs, uint dev, short type, __code next(...)); + __code iupdate(Impl* fs, struct inode* ip, __code next(...)); + __code idup(Impl* fs, struct inode* ip, __code next(...)); +.... +} fs; +``` +--- + + +# インターフェース実装内の CbC +- for文やif文がある場合はさらに実装を分ける + - Basic Block をもとに状態遷移ベースで記述することを目標とする +- インターフェースは外から呼び出されるAPI +- それに対してインターフェースの実装の Code Gearから明示的に呼び出される Code Gearは、Java の private メソッドのように扱われる。 +- 実際に書き換えた一部の例として fs.c の ialloc の実装を分けた記述を説明する -## CbC のコード例 -* この goto の行き先を継続と呼び、このときの a+b が次の Code Gear への出力となる +![](https://ie.u-ryukyu.ac.jp/~e165723/seni.pdf) +```clike +__code iallocfs_impl(struct fs_impl* fs, uint dev, short type, __code next(...)) { + goto allocinode(fs, dev, sb, next(...)); +} +``` +- 関数が呼び出されるとprivate実装に遷移する + +--- + +# ialloc の CbCによる書き換え +- FileSystemの代表的なAPIであるiallocをCbCで書き直した +- ialloc + - inodeにi-numberという番号を割り当てている -``` -__code cg0(int a, int b){ - goto cg1(a+b); -} +## 元ソースコード +- ialloc のソースコードの一部 +- for文の中でif文の処理が行われ、複雑である +- for文とif文を切り分けてやる +```clike + for (inum = 1; inum < sb.ninodes; inum++) { + bp = bread(dev, IBLOCK(inum)); + dip = (struct dinode*) bp->data + inum % IPB; -__code cg1(int c){ - goto cg2(c); + if (dip->type == 0) { + memset(dip, 0, sizeof(*dip)); + dip->type = type; + log_write(bp); + brelse(bp); + return iget(dev, inum); + } + .... + } + panic("ialloc: no inodes"); + +``` + +## iallocの処理の流れ +![](https://ie.u-ryukyu.ac.jp/~e165723/iallocloop.pdf) + +## CbCで書き換えたiallc +### 書き換え前 +- まずfor文のループするかどうか、条件を確認する +```clike +for (inum = 1; inum < sb.ninodes; inum++) { + .... } ``` -## CbC の継続 - -## Gears におけるメタ計算 -* Gears OS ではメタ計算を Meta Code Gear、Meta Data Gear で表現する -* Meta Code Gear はノーマルレベルの Code Gear の直後に遷移され、メタ計算を実行する -* Meta Code Gear で OS の機能であるメモリ管理やスレッド管理を行う - -## Meta Gear -* Gears OS では、Meta Code Gear は通常の Code Gear の直前、直後に挿入され、メタ計算を実行する -* 通常の計算からはメタ計算は見ることができない - - -## Context -* Gears OS では Context と呼ばれる、使用されるすべての Code Gear、Data Gear を持つ Meta Data Gear を持っている -* Gears OS は必要な Code Gear、Data Gear を参照したい場合、この Context を通す必要がある -* Context は Meta Data Gear であるため、Meta Code Gear を介してアクセスする +### 書き換え後 +- ループの条件に合うかどうかを確認するためのCodeGearに遷移する +```clike +__code allocinode(struct fs_impl* fs_impl, uint dev, struct superblock* sb, __code next(...)){ //:skip +.... + goto allocinode_loopcheck(fs_impl, inum, dev, sb, bp, dip, next(...)); +} +``` +- allocinode_loopcheckに遷移しループの条件の確認を行う +```clike +__code allocinode_loopcheck(struct fs_impl* fs_impl, uint inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + if( inum < sb->ninodes){ + goto allocinode_loop(fs_impl, inum, dev, type, sb, bp, dip, next(...)); + } + .... +} +``` +- ループ文の条件に当てはまらなかった場合panicへ遷移し処理が終わる +```clike +__code allocinode_loopcheck(struct fs_impl* fs_impl, uint inum, uint dev, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + .... + char* msg = "failed allocinode..."; + struct Err* err = createKernelError(&proc->cbc_context); + Gearef(cbc_context, Err)->msg = msg; + goto meta(cbc_context, err->panic); +} +``` +### 書き換え前 +- for文の中で処理が行われているif文 +- ループを抜けるか確認 +```clike +if (dip->type == 0) { + .... +} +``` +### 書き換え後 +- ループから抜けるかどうかを確認する +- 抜ける場合はallocinode_noloopへ遷移する +```clike +__code allocinode_loop(struct fs_impl* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip + .... + if(dip->type = 0){ + goto allocinode_noloop(fs_impl, inum, dev, sb, bp, dip, next(...)); + } + .... +} +``` +- ループから抜けなかった場合 +- inumの値をインクリメント +- 再びallocinode_loopcheckへと遷移する +```clike +__code allocinode_loop(struct fs_impl* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(...)){ //:skip +.... +inum++; +goto allocinode_loopcheck(fs_impl, inum, dev, type, sb, bp, dip, next(...)); +} +``` +### 書き換え前 +- 処理が抜けた場合 +- 変更された値などを更新 +- logに書き込んでやり保持していた値解放 +- returnでigetを返し終了 +```clike + memset(dip, 0, sizeof(*dip)); + dip->type = type; + log_write(bp); + brelse(bp); + return iget(dev, inum); +``` +### 書き換え後 +- 処理を抜けた場合allocinode_noloopへ遷移 +- 処理を行い値を返し終了 +```clike +__code allocinode_noloop(struct fs_impl* fs_impl, uint inum, uint dev, short type, struct superblock* sb, struct buf* bp, struct dinode* dip, __code next(int ret, ...)){ //:skip + memset(dip, 0, sizeof(*dip)); + dip->type = type; + log_write(bp); + brelse(bp); + ret = iget(dev, inum); + goto next(ret, ...); +} -## Context -* Context は全ての Code Gear のリストを持っており、enum で番号とアドレスを対応付けている -``` -enum Code { - C_popSingleLinkedStack, - C_pushSingleLinkedStack, - C_stackTest3, - C_assert3, - ... -}; -``` -``` -context->code[C_popSingleLinkedStack] = popSingleLinkedStack_stub; -context->code[C_pushSingleLinkedStack] = pushSingleLinkedStack_stub; -context->code[C_stackTest3] = stackTest3_stub; -context->code[C_assert3] = assert3_stub; ``` -## Context -* Data Gear も Code Gear と同様に Context が全ての Data Gear のリストを持っている -* Data Gear のリストも enum で管理されている -* これは引数格納用の Data Gear の番号である -``` -enum DataType { - D_Code, - D_SingleLinkedStack, - D_Stack, - D_TaskManager, - D_Worker, - ... - }; -``` - -## Interface -* Code Gear と Data Gear は Interface と呼ばれるまとまりとして記述される -* Interface は GearsOS でのモジュール化の仕組み -* Interface は使用される Data Gear の定義と、それに対する Code Gear の集合である -* Interface の操作に対応する Code Gear の引数は Interface に定義されている Data Gear を通して行われる - -## Interface の定義 -* Stack の Interface の例である -* typedef struct Interface 名で記述する -* Impl は実際に実装した際のデータ構造の型になる - -``` -typedef struct Stack<Impl> { - union Data* stack; - union Data* data; - __code next(...); - __code whenEmpty(...); - - __code clear(Impl* stack, __code next(...)); - __code push(Impl* stack, union Data* data, __code next(...)); - __code pop(Impl* stack, __code next(union Data* ...)); - __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...)); +--- +# 書き換えの評価 +- 今回はfor文やif文がある場合切り出してやり、Basic Block 単位に書き換えることができた +- Basic Block 単位に書き換えたことによって、組み合わせを変え処理の改善などに利用可能 -} -``` -## Interface の定義 -* Data Gear は 操作する Data Gear と -操作に必要な全ての Data Gear Gear が記述されている -* \_\_code で記述されているものが操作の Code Gear である - -``` -typedef struct Stack<Impl> { - union Data* stack; - union Data* data; - __code next(...); - __code whenEmpty(...); - - __code clear(Impl* stack, __code next(...)); - __code push(Impl* stack, union Data* data, __code next(...)); - __code pop(Impl* stack, __code next(union Data* ...)); - __code isEmpty(Impl* stack, __code next(...), __code whenEmpty(...)); - -} -``` -## Interface の実装の記述 -* ソースコードは Interface の実装の初期化のコードである -* 操作の Code Gear には実装した Code Gear の番号が代入されるが、ここを入れ替えることで、複数の実装を持つことができる -``` -Stack* createSingleLinkedStack(struct Context* context) { - struct Stack* stack = new Stack(); - struct SingleLinkedStack* singleLinkedStack = new SingleLinkedStack(); - stack->stack = (union Data*)singleLinkedStack; - singleLinkedStack->top = NULL; - stack->push = C_pushSingleLinkedStack; - stack->pop = C_popSingleLinkedStack; - stack->isEmpty = C_isEmptySingleLinkedStack; - stack->clear = C_clearSingleLinkedStack; - return stack; -} -``` -## xv6 の書き換えの方針 -* xv6 を CbC で書き換え、Gears OS の機能と置き換えることで Gears OS に OS の基本構造を持たせたい -* このためには xv6 をモジュール化することで、xv6 の機能を明らかにする必要がある -* xv6 の Interface を定義し、Gears OS の機能をこれに合わせることによって実現したい - -## CbC による FileSystem の書き換え ## まとめと今後の方針 +- OS 内部で CbC インターフェースを扱えるようになった +- CbC の書き換えが完了すれば、継続の入力と出力を検査することで OS の信頼性を保証したり、インターフェースの実装の入れ替えが可能になり拡張性が実現可能 +- デバックをまだ行っていないため正常に動くかどうか確認することが求められる + + +
--- a/user/riono210/lecture/sofsys/0423.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/lecture/sofsys/0423.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,24 @@ -#てsと \ No newline at end of file +# TightVNC + + +## what is it? +Virtual Network Computing software + + +## Where is the source dode? +https://www.tightvnc.com/download.php + + +## We should read this source code because ... +TreeVNCがTightVNCを基にしており、TreeVNCはより複雑なため、その元となったTightVNCを読見たいと思った。 + + +## Buid Status + + +## How to debug or trace +Intellij + + + +
--- a/user/riono210/seminar/202004.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202004.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,1 @@ -### テスト \ No newline at end of file +### 4月! \ No newline at end of file
--- a/user/riono210/seminar/202004/0414.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202004/0414.md Wed Dec 16 15:11:16 2020 +0900 @@ -4,5 +4,23 @@ ```画面配信システムTreeVNCのWifi Multicast実装``` +### 概要 +``` +講義やゼミではPCで用意した資料をプロジェクタに映しながら進行することが多い。 +この場合、発表者が交代するたびにケーブルを差し替える必要があり、PCによっては接続するアダプターの種類や解像度の設定により、正常にPC画面を表示できない場合がある。 +また、参加者もプロジェクタに集中を割く必要があり、同時に手元のPCで作業を行う場合、集中の妨げとなってしまう。 +当研究室で開発している画面配信システムTreeVNCは、発表者のPC画面を参加者のPC画面に表示するソフトウェアである。 +サーバに接続したクライアントをバイナリツリー状に接続し、配信コストを分散させる仕組みを取ることで、多人数が接続しても処理性能が下がらないような設計になっている。 +また、発表者を自由に切り替える仕組みが存在し、発表者の交代もスムーズに行うことができる。 +現在、TreeVNCの画面共有は送信するデータ量が多いために有線LANでの使用に限られている。 +そこで本研究では、Multicastでのデータ通信の考察やデータの分割・圧縮方法の実装、評価を行うことにより、無線LANでの配信環境の向上を目指し、 +TreeVNCの有用性を評価することで講義やゼミを円滑に行えることを目標とする。 +``` -## 進捗 \ No newline at end of file +## 進捗 +- ChristieをC#に書き換えをしようと考えてます +- Unityで動画作っていてその素材作成してました + + + +
--- a/user/riono210/seminar/202004/0421.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202004/0421.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,24 @@ -#てsつお \ No newline at end of file +# 0421ゼミ +## Multicast Wifi VNCの実装と評価 + +## 研究目的 + ``` +講義やゼミではPC画面で用意した資料を見ながら進行することが多い。PCごとにアダプターや解像度が異なっており、正常にPC画面を表示できない場合がある。 +当研究室で開発しているTreeVNCは、発表者のPC画面を参加者のPCに表示する画面配信システムである。 + +TreeVNCの画像共有は、送信するデータ量が多いために有線LANでの接続に限られている。 +本稿では無線LANでもTreeVNCを利用可能にするため、Wifi上にシステム制御用の従来の木構造と、画像データ送信用のMulticastの両方を構築を行う。 +Multicastでは、サーバから送信された画像データUpdateRectangleを小さいパケットに分割し送信を行うよう実装した。 + ``` + +## 進捗 +* sigosの申し込みをしました + * 論文の環境構築中、マインドマップはまだです... + * 締め切りは5/7 +* とりあえずChristieをC#に書き換えをしようかなと考えてます +* 研究計画書はオンライン提出になったみたいです + + + + + \ No newline at end of file
--- a/user/riono210/seminar/202006/0616.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202006/0616.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,3 +1,43 @@ -## +## 0616ゼミ + + +## 研究目的 +・ソフトウェアの通信にはクライアントサーバ方式とp2p方式がある +・Unityで使用されている通信フレームワーク + + + + +## 今週の進捗 +* とりあえずUnityで使われている通信フレームワークについていくつか調べてみた +* Christieの書き換えはあまり進んでいない.... +* my new gear...(mac book pro 16inch) + -## 研究目的 \ No newline at end of file +## Unityで使用されている通信フレームワーク(ライブラリ) +* Photon Unity Network2 + * クライアントサーバ方式 + * ホストがroomを作成してそこに合流する形式が主流 + * 20人まで接続無料 +* MagicOnion + * .NET Core/Unity用のリアルタイム通信フレームワーク + * クライアントサーバ方式 + * サーバ側の実装(関数など)をクライアント側で簡単に呼び出せる +* LiteNetLib + * クライアントサーバ方式 + * UDPらしい + * +* multiplayer(Unity公式 α版) +* Unet... + * 廃止予定... + + +## Christieの書き換え進捗 +今はDataGear部分の書き換えを行なっています + +あまりやる気が出ず(と言うか昼夜逆転していて)、ほとんど進んでません + + + + +
--- a/user/riono210/seminar/202006/0623.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202006/0623.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,7 +1,84 @@ -## 0623 +## 0623ゼミ ## 研究目的 +* ゲームの通信方式にはクライアントサーバ方式とp2p方式がある +* データの安全性やチート対策などでクライアントサーバ方式が主流 +* サーバに接続してマルチプレイなどのデータ同期を実現させているため、低速 +* 高速かつ安全に通信を行たい + * 並列分散フレームワークChristieがある + * Christieを利用してp2pで通信を行う +* ゲーム開発で主に使用されているUnityに対応するためにChristieをC#へ書き換えを行う + + + +## 先週・今週の進捗 +* とりあえずUnityで使われている通信フレームワークについていくつか調べてみた +* Christieの書き換えはまあまあ順調 +* my new gear...(mac book pro 16inch) + + +## Unityで使用されている通信フレームワーク(ライブラリ) +* Photon Unity Network2 + * クライアントサーバ方式 + * ホストがroomを作成してそこに合流する形式が主流 + * 20人まで接続無料 +* MagicOnion + * .NET Core/Unity用のリアルタイム通信フレームワーク + * クライアントサーバ方式 + * サーバ側の実装(関数など)をクライアント側で簡単に呼び出せる +* LiteNetLib + * クライアントサーバ方式 + * UDPらしい +* Unet + * 古のUnity公式通信フレームワーク + * 公式のサポート(例題、リファレンスなど)がほとんどなし + * あまりのクソさに廃止... +* multiplayer + * Unetの次代のUnity公式通信フレームワーク + * まだα版 + -## 今週の進捗 \ No newline at end of file +## Christieの書き換え進捗 +今はDataGear・CodeGear部分の書き換えを行なっています +時間はかかりそうだけど今のところ順調 + +javaのatomicintagerがなかったり、int型の読み書きくらいはスレッドセーフらしい(本当か...?)が、とりあえず一通り書いて動かしてみてから動作確認をしようと思ってます。 + +--- + +java +```public static <T> Class<T> [関数名] () { }``` +→ Class<T> は返り値の型 +→その前の<T>はジェネリスクメソッドの型を表す + +C# +```public static Type [関数名]<T> () { }``` +→Typeは返り値の型 +→関数名の直後の<T>はジェネックメソッドの型を表す + +--- + + +``` +java +T data = null; +Class<T> clazz = null; +byte[] messsagePack = null; +MessagePack packer = new MessagePack(); +// write read +messagePack = packer.write(data); +packer.read(messagePack, clazz); + + +C# +T data; +Type clazz = null; +byte[] messagePack = null; +// write read +messagePack = MessagePackSerialize(data); +MessagePackSerializer.Deserialize<T>(messagePack); +``` + +
--- a/user/riono210/seminar/202008/0811.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202008/0811.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,125 @@ -## 0811 +## 0811ゼミ ## 研究目的 +* ゲームの通信方式にはクライアントサーバ方式とp2p方式がある +* データの安全性やチート対策などでクライアントサーバ方式が主流 +* サーバに接続してマルチプレイなどのデータ同期を実現させているため、低速 +* 高速かつ安全に通信を行たい + * 並列分散フレームワークChristieがある + * Christieを利用してp2pで通信を行う +* ゲーム開発で主に使用されているUnityに対応するためにChristieをC#へ書き換えを行う + + +## 今週の進捗 +* 講義でチャットアプリをUnityで作ってました + * postするのにcookieにkeyを書き込む必要があり、しんどかった + * iosの仕様でバックグラウンド動作に苦しめられた +* Unity初心者勉強会を開催します +* GameJam+というイベントの運営と英語ミーティングがすることが確定 + +## C#でWebRequestでpost時にcookieにkeyを書き込む + +```C# +private IEnumerator WebRequest(){ + + //1.UnityWebRequestを生成 + UnityWebRequest request = UnityWebRequest.Post("http://", "post data"); + + //HTTPヘッダーの設定 + request.SetRequestHeader("key", "KEY"); + + //2.SendWebRequestを実行し、送受信開始 + yield return request.SendWebRequest(); + + //3.isNetworkErrorとisHttpErrorでエラー判定 + if(request.isHttpError || request.isNetworkError) { + //4.エラー確認 + Debug.Log(request.error); + } + else{ + //4.結果確認 + Debug.Log(request.downloadHandler.text); + } +} +``` +* postの例ではpython3で実装... + * post関数の引数にcookieを仕込める実装 +* Headerにkeyを書き込んでもpostできない + * そもそもUnityWebRequestにcookieを書き込む処理が実装されていない + +* C#でWebRequest自力実装することに + + +C#にはCookieContainerというcookieを書き込めるクラスがあったのでそれを利用 +```C# + // cookie書き込み + CookieContainer cc = new CookieContainer (); + cc.Add (new Uri (url), new Cookie ("key", key)); +``` + -## 今週の進捗 \ No newline at end of file +```C# +private void PostMessage () { + // 投げるjsonデータ + string postData = "{\"to\":\"someone\",\"content\":\"aaaaaaaaaaaallllllililili\"}"; + byte[] byteArray = Encoding.UTF8.GetBytes (postData); + + // cookie書き込み + CookieContainer cc = new CookieContainer (); + cc.Add (new Uri (url), new Cookie ("key", key)); + + // リクエストの作成 + HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url); + req.Method = "POST"; + req.ContentType = "application/json"; + req.ContentLength = byteArray.Length; + req.CookieContainer = cc; + + // ストリームに送信するデータを書き込む + Stream dataStream = req.GetRequestStream (); + dataStream.Write (byteArray, 0, byteArray.Length); + dataStream.Close (); + + // 送信 + HttpWebResponse res = (HttpWebResponse) req.GetResponse (); + + for (int i = 0; i < res.Headers.Count; i++) { + Debug.Log (res.Headers[i]); + } +} +``` + +## iosのバックグラウンドの動作時間 +チャットアプリだが、サーバー側は先生が用意しているのでそれを利用 + +push通知を飛ばしたいので、バックグラウンド動作時にサーバーからgetしてきたい + + +* Unityのコルーチン(非同期処理)を使うとその後の処理が返ってこない + * yield return null 1フレーム待つ →返ってこない +* await/async (C#の便利非同期処理)も 返ってこない +* Invoke("function", 1) という数秒待って関数を実行する関数も動作しない + +* なんならwhile(true)でループさせてても一定時間で処理が止まる + +` iOS 13におけるバックグラウンド時間` +`iOS 13で利用可能なバックグラウンド時間は、以前のバージョンのiOSと比較して大幅に短縮されました。iOS 13上で私たちのiOSアプリを使用して、接続したままの状態で他のアプリに切り替えた場合、その接続を維持したまま再び戻るためのバックグラウンド時間は約30秒に設定されているようです。これはOSによって制御されるもので、私たちがこれを制御する術がありません。私たちはこの問題の解決策を常に調査しており、将来的にはより良い方法を提供できると期待しています。` + + +## Unity初心者勉強会 +* 琉大の警戒レベルが3(課外活動全面禁止)になってしまったので、完全オンラインで開催 +https://igda-ryukyus.doorkeeper.jp/events/109970 + + +## GameJam+開催? +https://gamejamplus.com/#/ + +* ブラジル発 (日本の開催会場は0っぽい) +* GGJみたいな感じだが、各都市で優勝チームを決めてセミファイナル、ファイナルと進んでいく模様 +* 審査員やセミファイナルまでの間に優勝チームに付くプロをこちらが探さないといけない?? +* 15日に英語でオンライン会議する予定...(相手はポルトガル語話者) + + + +
--- a/user/riono210/seminar/202011/1124.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/202011/1124.md Wed Dec 16 15:11:16 2020 +0900 @@ -10,4 +10,240 @@ * ゲーム開発で主に使用されているUnityに対応するためにChristieをC#へ書き換えを行う ## 今週の進捗 -* 急に +* 急にやる気が出て、毎日最低1commitするようにした + * socket(Connection) + * MessagePackのバージョンとC#に入れたMessagePack + * enum(CommandType) + + + +## (B3向け)Christieとは +* GearsOS(kono研で開発しているOS)に導入予定の分散フレームワーク +* CodeGearとDataGearという概念を持っており、これらを利用して分散的に通信を行う + * CodeGear → スレッドに値するもの プログラミング的処理(関数など)とDataGearを持っている + * DataGear → データ classのフィールド変数的な + * CodeGearManager, DataGearManager... + + +詳しいことは一木が説明してくれるはず + + +## 書き換え方針 +* Annotation(C#だとAttribute)は完了 +* CodeGear → DataGear, DataGearsが書き終わり → Command周りを書き終えた + +残りのDataGear関連(DGM, RemoteDGM, WaitListなど)を書き終えたら、CodeGear関連を書き換える +年内くらいにはHelloWorldが動かせるといいなぁ + +## ジェネリクスの型情報について +```java= +public synchronized void put(String key, DataGear dg){ + if (dataGears.containsKey(key)) { + dataGears.get(key).add(dg); + } else { + LinkedBlockingQueue<DataGear> queue = new LinkedBlockingQueue<DataGear>(); + queue.add(dg); + dataGears.put(key, queue); + } +} +``` + + +```cs= +public void Put(string key, DataGear<object> dg) { + if (dataGears.ContainsKey(key)) { + dataGears[key].Enqueue(dg); + } else { + var queue = new ConcurrentQueue<DataGear<object>>(); + queue.Enqueue(dg); + dataGears.Add(key, queue); + } +} +``` + +## Socketについて +プログラミングでほぼ初めてSocket通信のプログラムを書きました... +~~接続先もAcceptしてないとIPとか取れないとか初めて知った~~ + +なんも分からん状態だったので、ChristieのSocketの部分を見つつJavaの例題をやってなんとなく理解してから +C#でも同じように例題動かしてみて書き換えしました + + +javaだとSocketクラスが割となんでもしてくれる感じ +C#だと役割が分散してる +```java= +Socket s = new Socket("localhost",3333); +DataOutputStream dout=new DataOutputStream(s.getOutputStream()); + +dout.writeUTF("Hello World"); +dout.flush(); +``` + +```cs= +IPHostEntry host = Dns.GetHostEntry ("localhost"); +IPAddress ipAddress = host.AddressList[0]; +IPEndPoint remoteEP = new IPEndPoint (ipAddress, 11000); + +Socket sender = new Socket (ipAddress.AddressFamily, + SocketType.Stream, ProtocolType.Tcp); +sender.Connect (remoteEP); + +byte[] msg = Encoding.ASCII.GetBytes ("Hello World"); +int bytesSent = sender.Send (msg); +``` + +## MessagePackのバージョン云々 +Christieに入っているMessagePackのバージョンは0.6.x +シリアライズするクラスには@Messageをつける必要がある + +バージョンが分からずにググっているとバージョンの壁に突き当たるかも +```java +import org.msgpack.MessagePack; +import org.msgpack.annotation.Message; + +public class Main1 { + @Message // Annotation + public static class MyMessage { + // public fields are serialized. + public String name; + public double version; + } + + public static void main(String[] args) throws Exception { + MyMessage src = new MyMessage(); + src.name = "msgpack"; + src.version = 0.6; + + MessagePack msgpack = new MessagePack(); + // Serialize + byte[] bytes = msgpack.write(src); + // Deserialize + MyMessage dst = msgpack.read(bytes, MyMessage.class); + } +} +``` + +```java +// Serialize with MessagePacker. +// MessageBufferPacker is an optimized version of +// MessagePacker for packing data into a byte array +MessageBufferPacker packer = MessagePack.newDefaultBufferPacker(); + packer + .packInt(1) + .packString("leo") + .packArrayHeader(2) + .packString("xxx-xxxx") + .packString("yyy-yyyy"); + +byte[] msgpack = packer.toByteArray() + +// Deserialize with MessageUnpacker +MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(msgpack); +int id = unpacker.unpackInt(); // 1 +String name = unpacker.unpackString(); // "leo" +int numPhones = unpacker.unpackArrayHeader(); // 2 +String[] phones = new String[numPhones]; +for (int i = 0; i < numPhones; ++i) { + phones[i] = unpacker.unpackString(); // phones = {"xxx-xxxx", "yyy-yyyy"} +} +unpacker.close(); +``` +--- + ## C#のMessagePackについて +* C#向けのMessagePackはmsgpackが作っているものとCSharpが作っているものの2つがある + * CSharp版は日本人が作成している + * Unityなどでも使用できるらしい + * cliよりも爆速であるらしい + +![](https://cloud.githubusercontent.com/assets/46207/23835716/89c8ab08-07af-11e7-9183-9e9415bdc87f.png) + +2種類あるというのも書き換えで勘違いしそうになった要因 + +シリアライズするクラスにはAttributeをつける必要があるため、こちらを採用した +```cs +[MessagePackObject] +public class RemoteMessage { + [Key("type")] + public int type; // コマンドタイプ + [Key("fromDmgName")] + public string fromDmgName; // 送り元のDgmName REPLYの時に使用 + [Key("key")] + public string key; + [Key("clazz")] + public string clazz; +} +``` + +## javaとC#のenumの違いについて +```java +public enum CommandType { + PUT, + TAKE, + PEEK, + REMOTETAKE, + REMOTEPEEK, + REPLY, + CLOSE, + FINISH; + + public int id;//コマンドのid + public static HashMap<Integer, CommandType> hash = new HashMap<Integer, CommandType>();//コマンド対応表 + private static int lastId = 0;//コマンドの総数 + + private CommandType() { + this.id = incrementLastId(); + }//for init + + private int incrementLastId() { + return ++lastId; + } + + public static CommandType getCommandTypeFromId(int id) { + return hash.get(id); + } + + // 各コマンドが初期化された最後に呼ばれる + static { + for (CommandType type : CommandType.values()) { + hash.put(type.id, type); + } + } +} +``` +* C#ではenumにフィールド変数やメソッドをはやすことができない + * ヘルパークラスを作って対応 + * かなりややこしい感じに 想定していた動作になってない + * 独自でenumっぽいクラスを作成して対応 + +HashMap(Dectionary)をstaticで返さないといけないのがヘルパクラスだと面倒 +javaは最初にenumが呼び出された時に1回だけ初期化動作がされる + →ヘルパクラスを使って最初の一回だけ判断して初期化処理を作るのは面倒 +```cs +public class CommandType { + private static int lastId = 0; // コマンドの総数 + public readonly int id = ++lastId; // コマンドのid コンストラクタが呼ばれるたびにlastIdが++される + public static readonly Dictionary<int, CommandType> hash = new Dictionary<int, CommandType>(); + + private CommandType() { + hash.Add(this.id, this); + } + + /// <summary> + /// idよりCommandTypeを返す + /// </summary> + /// <param name="id"></param> + /// <returns></returns> + public static CommandType GetCommandTypeFromId(int id) { + return hash[id]; + } + + public static readonly CommandType PUT = new CommandType(); + public static readonly CommandType TAKE = new CommandType(); + public static readonly CommandType PEEK = new CommandType(); + public static readonly CommandType REMOTETAKE = new CommandType(); + public static readonly CommandType REMOTEPEEK = new CommandType(); + public static readonly CommandType REPLY = new CommandType(); + public static readonly CommandType CLOSE = new CommandType(); + public static readonly CommandType FINISH = new CommandType(); +} +```
--- a/user/riono210/seminar/__template.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/seminar/__template.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,6 +1,12 @@ ## mmdd ## 研究目的 - +* ゲームの通信方式にはクライアントサーバ方式とp2p方式がある +* データの安全性やチート対策などでクライアントサーバ方式が主流 +* サーバに接続してマルチプレイなどのデータ同期を実現させているため、低速 +* 高速かつ安全に通信を行たい + * 並列分散フレームワークChristieがある + * Christieを利用してp2pで通信を行う +* ゲーム開発で主に使用されているUnityに対応するためにChristieをC#へ書き換えを行う ## 今週の進捗 \ No newline at end of file
--- a/user/riono210/sigos2020.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/sigos2020.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,24 +1,35 @@ -# 画面配信システム TreeVNC のマルチキャストの導入 +# Multicast Wifi VNCの実装と評価 author: Ryo Yasuda, Shinji Kono profile: 並列信頼研 ## 画面配信システムの活用 -- 講義やゼミではプロジェクタを使用して、先生が用意した資料を見ることが多い。その際接続不良など、物理的アクシデントが起きる恐れがある +<!-- - 講義やゼミではプロジェクタを使用して、先生が用意した資料を見ることが多い。その際接続不良など、物理的アクシデントが起きる恐れがある - 画面配信システムで代用する場合がある。画面配信システムのとしてはAppleTVやUstreamなどが挙げられる - AppleTVは画面共有先がTVに限定されている - Ustreamは画面の切り替えを行うことができない - <center><img src="https://i.imgur.com/5lT1RZ9.png" alt="message" width="200" height="200"> <img src="https://i.imgur.com/qpeYXUl.png" alt="message" width="200" height="150"></center> - +--> +- コロナ禍によりリモートワークが推進され、ビデオ通話ソフトウェアの重要性が高まっている +- リモートワークではPCの画面共有を行って、情報を共有することも多い +- ビデオ通話ソフトウェアとしてはZoomやMicrosoft Teamsなどが挙げられる - +(zoomとteamsの画像) ## 画面配信システムの活用 +- 既存のソフトウェアではカメラを利用したビデオ通話に重点を置いて開発されており、PC画面を共有するとぼやけてしまう +- ビデオ通話にはそれぞれのサービスのサーバを経由しなければならない + +## 画面配信システムの活用 +<!-- - 画面配信システムTreeVNCは、自身のPC画面を他者のPCと共有できるソフトウェアである - javaで書かれているためOSに依存せず、物理的な制約なしに使用可能 - TreeVNCを使用することで、参加者は手元のPCを使用しながら講義を受ける事が可能になる。切り替えの際も、ボタン1つで共有する画面の切替を可能としている +--> +- 画面配信システムTreeVNCは、自身のPC画面を他者のPCと共有できるソフトウェアである +- + ## TreeVNCの講義等での活用 - 講義では先生のPC画面を手元のPCで見ることで、コマンドを手元で打ち間違えや、メモを取る際にPCのみに集中を向けることができるようになった
--- a/user/riono210/thesis.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/riono210/thesis.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,31 +1,6 @@ -title: 画面配信システム TreeVNC のマルチキャストの導入 +# 画面配信システム TreeVNC のマルチキャストの導入 author: Ryo Yasuda, Shinji Kono profile: 並列信頼研 -lang: Japanese -code-engine: coderay - -<!-- <\!-- slideshow の command -\-> --> -<!-- slide.htmlでは通常キーでのコマンドが存在している --> - -<!-- p,a,s : スライドを自動送り(1,2...) --> -<!-- : スライドを逆方向に自動送り(...,2,1) --> -<!-- n : Page数を on/off --> -<!-- f : 右下ロゴの on/off --> -<!-- t : slide.html.pdf に変更 --> -<!-- c : 右下スライド移動用UIの on/off --> -<!-- d : ロゴ部分の選択…? --> -<!-- [URL](http://~~~) --> -<!-- [FILE](file:///Users/ryokka/~~~) --> -<!-- slideshow build スライド.md -t s6cr --> - -<!-- ## 目次 -- **TreeVNC の概要** - - **基本概念** - - **構造** -- 研究内容 - - TreeVNC の改良 - - 送信データの Blocking ---> ## 画面配信システムの活用 - 講義やゼミではプロジェクタを使用して、先生が用意した資料を見ることが多い。その際接続不良など、物理的アクシデントが起きる恐れがある @@ -33,26 +8,34 @@ - AppleTVは画面共有先がTVに限定されている - Ustreamは画面の切り替えを行うことができない -<center><img src="./fig/AppleTVRogo.svg " alt="message" width="200" height="200"> -<img src="./fig/UstreamRogo.svg" alt="message" width="200" height="150"></center> + +<center><img src="https://i.imgur.com/5lT1RZ9.png" alt="message" width="200" height="200"> +<img src="https://i.imgur.com/qpeYXUl.png" alt="message" width="200" height="150"></center> + + ## 画面配信システムの活用 - 画面配信システムTreeVNCは、自身のPC画面を他者のPCと共有できるソフトウェアである -- javaで書かれているためOSに依存せず、物理的な制限なしに使用可能 -- TreeVNCを使用することで、参加者は手元のPCを使用しながら講義を受ける事が可能になる。切り替えの際も、ボタン一つで共有する画面の切替を可能としている +- javaで書かれているためOSに依存せず、物理的な制約なしに使用可能 +- TreeVNCを使用することで、参加者は手元のPCを使用しながら講義を受ける事が可能になる。切り替えの際も、ボタン1つで共有する画面の切替を可能としている ## TreeVNCの講義等での活用 - 講義では先生のPC画面を手元のPCで見ることで、コマンドを手元で打ち間違えや、メモを取る際にPCのみに集中を向けることができるようになった - ゼミにおいてもコードをつなげるために移動する必要がなく、各自の席で発表者の画面を見ることができる - 以上のようにTreeVNCは従来のプロジェクタなどよりも利便性が高い +## 本研究の概要 +- 画面配信は送信するデータ量が多いため、TreeVNCでは無線接続の場合、画面配信の遅延が大きくなってしまう +- 現在のTreeVNCのデータ転送方法だと、無線接続で送信するには大きすぎる +- 本研究ではMulticastの導入としてBlockingによるデータの分割を実装した + ## VNC - VNC(Virtual Network Computing)は、RFB(Remote Frame Buffer)プロトコルを用いてPCの遠隔操作を行うことを目的としたリモートデスクトップソフトウェア - サーバー側とクライアント側に分かれており、起動したサーバーにクライアントが接続することで遠隔操作を可能にしている - 全てのNodeが一台のサーバーに接続するため負担が大きい -<center><img src="./fig/vnc-crop.svg" alt="message" width="450" height="350"></center> +<center><img src="https://i.imgur.com/ufIEIe5.png)" alt="message" width="450" height="300"></center> ## TreeVNCとは @@ -60,50 +43,46 @@ - 木構造の接続方式によりNode間で画像データのやりとりを行う - 各ノードが2回ずつ画像データをコピーすることで配信側の負荷を分散し、大人数での画面配信が可能 -<center><img src="./fig/treevnc-crop.svg" alt="message" width="450" height="350"></center> +<center><img src="https://i.imgur.com/zpeYi9p.png" alt="message" width="450" height="300"></center> + +## UpdateRectangleによる画面更新 +- RFB (Remote Frame Buffer) プロトコルを利用し、自身の画面をネットワークを通じて送信し他者の画面に表示する +- クライアントに送信するデータは画面全てではなく、変更があった部分のFrameBufferを送る +- 配信PC画面の変更があった部分のみをRFBで、UpdateRectangleとしてマルチキャストで一度のみ送信する +- RFBプロトコルでは画像データをRectangleで送信しているため、UpdateRectangleとして送信されるPacketには複数のRectangleが入るような構成をとっている + +<center><img src="https://i.imgur.com/ZN6jMYI.png" alt="message" width="450" height="300"></center> -## 本研究の概要 -- 画面配信は送信するデータ量が多いため、TreeVNCでは無線接続の場合、画面配信の遅延が大きくなってしまう -- 現在のTreeVNCのデータ転送方法だと、無線接続で送信するには大きすぎる -- 本研究ではMulticastを導入することで、Wifi環境下における画面配信の遅延対策の検討を行なった - -## TreeVNCの画面配信方法 -- RFB (Remote Frame Buffer) プロトコルを利用し、自身の画面をネットワークを通じて送信し他者の画面に表示する -- 他人のPC画面が表示される側と、FrameBufferへの更新が行われる(自身のPC画面を送信する)側に分かれ、それぞれをRFBクライアント、RFBサーバと呼ぶ -- FrameBufferは、メモリ上に置かれた画像データのこと -- RFBクライアントに送信するデータは画面全てではなく、変更があった部分のFrameBufferを送る +## RFBプロトコルのエンコードタイプ +- ZRLEとはRFBプロトコルでサポートされているエンコードタイプの1つ +- zlib圧縮、タイリング、run lengthエンコードを組み合わせている + +<center><img src="https://i.imgur.com/CdGCftg.png" alt="message" width="500" height="350"></center> + +## RFBプロトコルのエンコードタイプ +- 解凍に必要な辞書を書き出すことができないため、途中からデータを受け取ると正確に解凍できなくなる + +<center><img src="https://i.imgur.com/VxeaTMD.png" +alt="message" width="500" height="350"></center> -## Multicastによる画面配信 -- 配信PC画面の変更があった部分のみをUpdateRectangleとしてマルチキャストで一度のみ送信する -- RFBプロトコルでは画像データをRectangleで送信しているため、UpdateRectangleには複数のRectangleが入るような構成をとる -<center><img src="./fig/UpdateRectangleStruct.svg" alt="message" width="450" height="350"></center> +## TreeVNCの画像データ圧縮方法 +- ZRLEを応用したZRLEEを使用している +- 辞書の書き出しを行えるようにし、データを途中から受け取っても解凍することが可能 +- ZRLEを一度解凍し、辞書を書き出して再圧縮を行う + + +<center><img src="https://i.imgur.com/VxeaTMD.png" alt="message" width="500" height="400"></center> + ## Multicastの問題点 - wifiのMulticast Paketの最大サイズは64KBである - HDや4Kの画面を更新するためのサイズは大きい - - 4Kの場合8MB x 8Byteで64MB + - 4Kディスプレイの場合8MB(画素数) x 8Byte(色情報)で64MB - 送信データの圧縮と64KB毎のパケット変換が必要 -## RFBプロトコルのエンコードタイプ -- ZRLEとはRFBプロトコルでサポートされているエンコードタイプの1つ -- zlib圧縮、タイリング、run lengthエンコードを組み合わせている -- 解凍に必要な辞書を書き出すことができないため、途中からデータを受け取ると正確に解凍できなくなる - -<center><img src="./fig/ZlibTiling.svg" alt="message" width="550" height="450"></center> - - -## TreeVNCの画像データ圧縮方法 -- ZRLEを改変したZRLEEを使用している -- 辞書の書き出しを行えるようにし、データを途中から受け取っても解凍することが可能 -- ZRLEを一度解凍し、辞書を書き出して再圧縮を行う -- zlibは適当なタイミングで圧縮を書き出し(flush)を行う必要がある - - zlibのAPIを用いて、適当なタイミングでflushを行なっている - - 1tileずつflushしてしまうと圧縮率を下げてしまう可能性がある - -<center><img src="./fig/EncodeZRLEE.svg" alt="message" width="550" height="450"></center> ## Blockingの考察 - 64KBのパケットに収めるため、ZRLEEで圧縮する前にBlockingを行い、Rectangleの再構成を行う @@ -112,92 +91,53 @@ - 行の最初から最後まで Phase1 - 行の最初から行の途中まで Phase2 -<center><img src="./fig/FrameUpdateRectangleColor.svg" alt="message" width="500" height="400"></center> +<center><img src="https://i.imgur.com/HrqYOhP.png" alt="message" width="600" height="400"></center> + ## Blockingの考察 - 最大3つのRectangleの再構成を行いつつ、ZRLEEで変換を行いパケットの構成をする -- UpdateRectangleには3つのRectangleが入る - -<center><img src="./fig/FrameUpdateRectangleColor.svg" alt="message" width="500" height="400"></center> +- Packetの先頭にはmessageIDなどが格納されているPacke Headerがある +- 各RectangleにはRectangleのx,y座標や圧縮されたデータ長などが格納されているRectangle Headerを持っている -## paket lossする可能性 -- wifiのMulticast paketは確実に送信されることが保証されておらず、paket lossする可能性がある -- その対策としては以下の2つが取れる - - 何もしない、定期的に全画面のデータが送信されるため問題ない考える - - 再送要求を行う、処理が複雑であることが予想される -- 現状では何もせず、全画面のデータの送信を待つ方式でも十分実用に耐えると考える +<center><img src="https://i.imgur.com/HrqYOhP.png" alt="message" width="600" height="400"></center> -<!-- ## TreeVNC の構造 -- TreeVNCは接続してきたクライアントをNodeとし、木構造状に管理する -- ルートのノードをRoot Nodeと呼び、その下に新たなNodeを接続していく -- Root Nodeが参照しているVNCServerからFrameBufferUpdateを取得し、各Nodeに送信する -- 木構造状に接続することで、画像データのコピーを各Nodeに負担させることができる - -<center><img src="./fig/treevnc-crop.svg" alt="message" width="450" height="350"></center> +## 圧縮方式 +- zlibには以下の3つの圧縮方法が存在する + * NO FLUSH : Stream に格納されたデータを最高率で 圧縮を行う。Stream にある入力データが規定量に満た ない場合は圧縮されない + * SYNC FLUSH : これまでに Stream に格納されたデー タの圧縮を行う。ただし圧縮率が低下する可能性がある + * FULL FLUSH : SYNC FLUSH 同様、これまでに Stream に格納されたデータの圧縮を行う。異なる点 はこれまでの辞書情報がリセットされるため、圧縮率 が極端に低くなる可能性がある -## 木構造の再構成 -- Nodeが切断されたことを検知できなければ木構造が維持できない -- Root Nodeが木構造のネットワークトポロジーを管理しているため、Root NodeにNodeの切断を知らせる必要がある -- 切断検知には画像データが入っているMulticastQueueを使用 -- MulticastQueueから画像データが一定時間取得されず、Timeoutを検知した場合切断したと判断する - -## 画像データのエンコード方法 -- TreeVNCではZRLEというエンコードタイプを元にした、ZRLEEというエンコードを用いて画像データを圧縮を行う -- ZRLEはZlibで圧縮されたデータとそのデータのバイト数がヘッダーとして送られる -- Zlibとはデータの可逆圧縮アルゴリズムが実装されているライブラリ - -## 画像データのエンコード方法 -- ZRLEでは解凍時に必要な辞書データを書き出すことができない -- ZRLEEはRoot Nodeで受け取ったZRLEのデータを一度解凍し、辞書データを付与して再圧縮している - -<center><img src="./fig/EncodeZRLEE.svg" alt="message" width="550" height="450"></center> +<!--## paket lossする可能性 +- wifiのMulticast paketは確実に送信されることが保証されておらず、paket lossする可能性がある +- その対策としては以下の2つが取れる + - 何もしない、定期的に全画面のデータが送信されるため問題ないと考える + - 再送要求を行う、処理が複雑であることが予想される +- 現状では定期的に全画面のデータを送信しており、十分実用に耐えると考える +--> -## 共有画面切り替え -- 従来のVNCでは、配信者が切り替わるたびに再起動、再接続を行う必要があった -- TreeVNCでは、画面上にあるShareScreenボタンを押すことで配信者の切り替えが実行できる -- ShareScreen実行後、Root Nodeに対しSERVER CHANGE REQUESTというメッセージが送信される -- メッセージを受け取ったRoot Nodeは配信を希望しているNodeのVNCサーバーと通信を行い、切り替え作業に入る - -<center><img src="./fig/ShareScreenSS.svg" alt="message" width="400" height="300"></center> +## 圧縮方法 +- 1TileごとにSYNC_FLUSHを行なっている +- 行末ではFULL_FLUSHを行う +- NO_FLUSHを利用していないためデータの圧縮率は下がる -## 有線接続との接続の違い -- 現状のTreeVNCでは画面配信のデータ量は多く、無線LAN接続を行うと画面配信の遅延が大きくなる -- WifiのMulticast機能を利用し、UpdateRectangleを一度だけ送信することで無線LAN接続でも十分に遅延が抑えられると考える -- HDや4kの画面更新には64MB程度となり、これを圧縮しつつwifiのMulticast paketの最大サイズ64KBに変換、送信する必要がある -- paket lossがあった場合、再送処理は複雑であると予想できるため、まずBlokingによる実験を行う - -## RFBプロトコルのUpdateRectangleの構成 -- 1つのUpdateRectangleには複数のRectangleが格納されている -- RectangleはZlibで圧縮されたデータが指定された長さだけ格納されており、そのデータはさらに64x64 ByteのTileに分割されている - -## RFBプロトコルのUpdateRectangleの構成 -- 無線接続の場合、一度に送信できるデータ量が64KBしかないため、それに合わせて更新された部分のRectangleを分割する必要がある - - Phase0 行の途中から始まる部分 - - Phase1 行の最初から最後までの部分 - - Phase2 行の途中で終わる部分 - -<center><img src="./fig/FrameUpdateRectangleColor.svg" alt="message" width="550" height="450"></center> +## その他の実装 +- TreeVNCのBuildに使用している、Gradleを4.8から6.1へのバージョンアップ対応 +- java9以降非推奨だったRetinaAIPの更新対応 +- デバッグオプションの修正 -## 木構造とマルチキャストの共存 -- ツリーに無線接続のNodeを加えてしまうと全体の配信遅延に繋がる -- 無線接続時のMulticastの実装を提案 -- Multicastならば、Serverからの送信は一度で済むため、ツリー構造の形成が必要ない -- 従って新しいNodeが無線接続であっても、有線接続のツリーの配信には影響が出ない +## まとめ +- WifiでBlockingを用いて、Multicast paketを利用する手法についての考察と実装を行なった + - Wifiの速度とMulticastの信頼性が高ければ実用的である可能性がある -<center><img src="./fig/interface-crop.svg" alt="message" width="500" height="450"></center> ---> - -## まとめ -- WifiでMulticast paketを利用する手法についての考察を行なった - - Wifiの速度とMulticastの信頼性が高ければ実用的である可能性がある - - Blockingは実装中、再圧縮の時間は実用的な時間で済むと予想されている +- TreeVNCのBuildやAPIのバージョンアップ対応、デバッグオプション修正を行なった - 今後の課題 - - Blockingの実装 + - Multicast通信の実装 - WifiのMulticast paket lossは接続環境や状況に依存すると思われるためさらなる実験が必要 - - Node接続じの有線接続と無線接続の判断、区別処理の実装 + - Node接続時の有線接続と無線接続の判断、区別処理の実装 + - SYNC_FLUSHを使っているため圧縮率が低下しているため、圧縮率の向上についての考察 \ No newline at end of file
--- a/user/ryokka/master-slide.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ryokka/master-slide.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,5 +1,603 @@ +Continuation Based C の Hoare Logic を用いた仕様記述と検証 +===== -# たいとる +琉球大学大学院 : 並列信頼研究室\ +外間 政尊 + +--- + +## OS の検証技術としての Hoare Logic の問題点 +- OS やアプリケーションの信頼性は重要な課題 + +- 信頼性を上げるために仕様の検証が必要 + +- 検証にはモデル検査や**定理証明**などが存在する + +- また、仕様検証の手法として **Hoare Logic** がある + -通常の関数でも実行する前に必要な引数があって何らかの出力がある + - Hoare Logic ではコマンドを実行する上で引数が存在するなどの事前に成り立つ条件があり、コマンド実行後に異なる条件が成り立つ +- Hoare Logic では関数が最低限のコマンドで分割されており記述が困難(変数の代入、コマンド実行の遷移等) + +--- +## Hoare Logic をベースにした Gears 単位での検証 +- 当研究室では 処理の単位を **CodeGear**、データの単位を **DataGear** としてプログラムを記述する手法を提案 +- CodeGear は Input DataGear を受け取り、処理を行って Output DataGear に書き込む +- CodeGear は継続を用いて次の CodeGear に接続される +- 定理証明支援機の Agda 上で Gears 単位を用いた検証を行う +- 本研究では Gears 単位を用いた Hoare Logic ベースの検証手法を提案する + +--- + +## Agda + Agda は関数型言語 +```AGAD + name : type + name = value +``` +関数には型と定義を与える\ +型は **:** で、 値は **=** で与える\ +仮定なしに使えるのは Set のみ + +構成要素としては以下の3種類 +1. 関数 + - 型は(A : Set かつ B : Set のとき) A → B + - 値は(x : A かつ y : B) λ x → y +1. record +1. data + +--- + +## Agda の record とその例 ∧ +導入は2つのものが同時に存在すること +``` + A B +------------ + A ∧ B +``` +除去は名前を区別する必要がある +``` + A ∧ B A ∧ B + --------- pi1 --------- pi2 + A B +``` +A ∧ B が成り立っていれば (pi1 A ∧ B) → A、 (pi2 A ∧ B) → B\ +Agda ではこのような同時に存在する型を **record** で書く +```AGDA + record _∧_ (A B : Set) : Set + field + pi1 : A + pi2 : B +``` +\_∧\_ は中間記法、変数が入る位置を _ で示せる\ +実際の構築は x : A かつ y : B のとき +```AGDA +createAnd : (A : Set) → (B : Set) → A ∧ B +createAnd x y = record {pi1 = x ; pi2 = y} +``` +のように記述する\ +C 言語での構造体のようなもの + +A や B に論理式が入ると2つのものが同時に成り立つ証明ができる + +--- + +## Agda の data とその例 Sum +導入\ +一つでも存在すること +``` + A B + ----------- p1 ---------- p2 + A ∨ B A ∨ B +``` +除去\ +A → C か B → C のとき C +``` + A B + : : + A ∨ B C C + ------------------------ + C +``` + + +A ∨ B が成り立っているとき A → A ∨ B、 B → A ∨ B\ +どちらかが成り立つ型を **data** で書く\ +```AGDA + data _∨_ (A B : Set) : Set where + p1 : A → A ∨ B + p2 : B → A ∨ B +``` +のように記述できる\ +C 言語での union のようなもの\ +p1、 p2 は case 文みたいな感じ + +--- + +## Hoare Logic +Hoare Logic はプログラム検証の手法\ +事前条件( P )が成り立つとき、コマンド( C )を実行すると事後条件( Q )が成り立つ + +これは **{ P } C { Q }** の形で表され、Hoare Triple と呼ばれる + + +今回は以下のような while program を検証する + +n = 10 となっているが検証では n は任意の自然数 +```C + n = 10; + i = 0; + + while (n>0) + { + i++; + n--; + } +``` + +--- + +## Agda での Hoare Logic +Hoare Logic のプログラムは Command で構成される + +Comm 型は data で記述されたコマンドのデータ構造 + +実際に実行するには解釈して動かす関数が必要 + +Commを使って while program を構築する + +```AGDA + data Comm : Set where + Skip : Comm + Abort : Comm + PComm : PrimComm → Comm + Seq : Comm → Comm → Comm + If : Cond → Comm → Comm → Comm + While : Cond → Comm → Comm +``` + +--- + +## Hoare Logic での while program +検証する while program の擬似コード +```C + n = 10; + i = 0; + + while (n>0) + { + i++; + n--; + } +``` +コマンドで構成した while program +```AGDA + program : ℕ → Comm + program c10 = + Seq ( PComm (λ env → record env {varn = c10})) + $ Seq ( PComm (λ env → record env {vari = 0})) + $ While (λ env → lt zero (varn env ) ) + (Seq (PComm (λ env → record env {vari = ((vari env) + 1)} )) + $ PComm (λ env → record env {varn = ((varn env) - 1)} )) +``` + +これは Hoare Logic のコマンドで以下のような構文木を記述している + +``` + Seq + / \ + PComm Seq + (n=c10) / \ + PComm While + (i=0) | + Cond + (0<n) + | + Seq + / \ + PComm PComm + (i+1) (n-1) +``` + +--- + +## Hoare Logic での Command に対応する仕様 +Command に対応する証明がある + +**HTProof** は Hoare Triple Proof + +**{P} Q {C}** が **Cond → Comm → Cond** に対応している + +```agda + data HTProof : Cond → Comm → Cond → Set where +``` +すべての Command に対応する Proof を載せると長いので +必要なものだけ + +\ +PrimRule は 代入のときに成り立ってほしいルール + +Axiom は Triple を受け取ってすべての Env は事前の Env が正しければ コマンドを実行した後のEnv も正しくなるという命題 +```AGDA + PrimRule : {bPre : Cond} → {pcm : PrimComm} → {bPost : Cond} → + (pr : Axiom bPre pcm bPost) → + HTProof bPre (PComm pcm) bPost +``` +WekeningRule は 条件を緩める規則 + +While コマンドなどで条件が厳しいときに同時に成り立つ異なる条件へ変更必要がある + +Tautology は2つの Cond 型 bPre、 bPre' を受け取り、 bPre が成り立つとき、 bPre'が成り立つという命題 +```agda + WeakeningRule : {bPre : Cond} → {bPre' : Cond} → {cm : Comm} → + {bPost' : Cond} → {bPost : Cond} → + Tautology bPre bPre' → + HTProof bPre' cm bPost' → + Tautology bPost' bPost → + HTProof bPre cm bPost +``` +SeqRule は Seqcuence が正しい順番で行われることを保証 + +cm1、cm2 という2つのCommを受け取ってそれらがcm1、cm2の順で実行される + +``` + SeqRule : {bPre : Cond} → {cm1 : Comm} → {bMid : Cond} → + {cm2 : Comm} → {bPost : Cond} → + HTProof bPre cm1 bMid → + HTProof bMid cm2 bPost → + HTProof bPre (Seq cm1 cm2) bPost +``` +WhileRule は Comm 型の cm と Cond型の bInv、 bが存在するとき、 +事前に +``` + WhileRule : {cm : Comm} → {bInv : Cond} → {b : Cond} → + HTProof (bInv and b) cm bInv → + HTProof bInv (While b cm) (bInv and neg b) +``` +検証をするためにはこの HTProof で program と同様の仕様を構成する必要がある + +## Hoare Logic での 仕様記述 +HTProof で記述した仕様 + +HTProof が コマンドに対応しているのでほとんど同じ形で書けてる +```AGDA + proof1 : (c10 : ℕ) → HTProof initCond (program c10 ) (termCond {c10}) + proof1 c10 = + SeqRule {λ e → true} ( PrimRule (init-case {c10} )) + $ SeqRule {λ e → Equal (varn e) c10} ( PrimRule lemma1 ) + $ WeakeningRule {λ e → (Equal (varn e) c10) ∧ (Equal (vari e) 0)} lemma2 ( + WhileRule {_} {λ e → Equal ((varn e) + (vari e)) c10} + $ SeqRule (PrimRule {λ e → whileInv e ∧ lt zero (varn e) } lemma3 ) + $ PrimRule {whileInv'} {_} {whileInv} lemma4 ) lemma5 +``` + +```AGDA + program : ℕ → Comm + program c10 = + Seq ( PComm (λ env → record env {varn = c10})) + $ Seq ( PComm (λ env → record env {vari = 0})) + $ While (λ env → lt zero (varn env ) ) + (Seq (PComm (λ env → record env {vari = ((vari env) + 1)} )) + $ PComm (λ env → record env {varn = ((varn env) - 1)} )) +``` +proof1 は条件がつながるのに必要な条件を lemma で記述している(lemma は長いので省略) + +部分正当性は示せている + +全体がつながっているが証明にはなっていない + + +--- +## Hoare Logic での健全性の証明 +実際に正しく動作すること(健全性)を証明する必要がある + +Satisfies は {P} C {Q} を受け取ってそれらが Comm で正しく成り立つ関係を返す + +PrimSoundness は HTProof を受け取って Satisfies が成り立つことを Soundness を用いて実際に証明する +```AGDA + PrimSoundness : {bPre : Cond} -> {cm : Comm} -> {bPost : Cond} -> + HTProof bPre cm bPost -> Satisfies bPre cm bPost + PrimSoundness {bPre} {cm} {bPost} ht = Soundness ht +``` +Soundness は HTProof に対応した非常に複雑な証明 + +HTProof を渡すと Ruleに対応した証明を行う + +proofOfProgram では 実際に構築した program と proof1 を使って健全性を証明している + +```AGDA + proofOfProgram : (c10 : ℕ) → (input output : Env ) + → initCond input ≡ true + → (SemComm (program c10) input output) + → termCond {c10} output ≡ true + proofOfProgram c10 input output ic sem = + PrimSoundness (proof1 c10) input output ic sem +``` + +--- +## Continuation based C について +Continuation based C (CbC) は当研究室で開発してるプログラミング言語 + +CbC では処理の単位を **CodeGear** 、データの単位を **DataGear** とする + +CodeGear は引数として Input の DataGear を受け取り、 Output の DataGear を返す + +Output の DataGear は次の CodeGear の Input として接続される + + +![](/attachment/5e42fdea7b378d004670d2fc) +![](./fig/cgdg-small.svg) +CodeGear の接続処理などのメタ計算は Meta CodeGear として定義 + +Meta CodeGear で信頼性の検証を行う + + +--- +## Agda での CodeGear、 DataGear の記述 + +- Agda での CodeGear は継続渡しで記述された関数 +```AGDA + whileTest : {t : Set} → (c10 : Nat) + → (Code : Env → t) → t + whileTest c10 next = next (record {varn = c10 + ; vari = 0} ) + ``` + - CodeGear の型は継続先を返す関数 + - **(Code : fa → t)** は継続先 + - 引数として継続先の CodeGear を受け取る + + + + + + + +--- +## CbC での Hoare Logic +CodeGear、DataGear を用いた Hoare Logic は図のようになる +![](/attachment/5e42baee7b378d004670d1f5) +![](./fig/hoare-cg-dg.svg) +CodeGear が条件を引数として受け、継続先の CodeGear が次の条件を満たす様になる + +下のコードは CodeGear、 DataGear を用いた Hoare Logic ベースの記述例である + +```AGDA + whileTestPwP : {l : Level} {t : Set l} → (c10 : ℕ) → ((env : Envc ) + → (vari env ≡ 0) ∧ (varn env ≡ c10 env) → t) → t + whileTestPwP c10 next = next (whileTestP c10 ( λ env → env )) + record { pi1 = refl ; pi2 = refl } +``` + + + + + + + + + + + + +--- +## CbC での while program +```C + n = 10; + i = 0; + + while (n>0) + { + i++; + n--; + } +``` + +CbC での while program +```AGDA + whileTestPCall : (c10 : ℕ ) → Envc + whileTestPCall c10 = whileTestP' {_} {_} c10 (λ env → loopP' env (λ env → env)) +``` +- whileTestP' が n = c10、 i = 0 の代入、 loopP' が while loop に対応している +- CbC での Hoare Logic 上でコマンドは CodeGear そのもの + - CodeGear は Hoare Logic のコマンドより自由な記述 + + +--- +## CbC での Hoare Logic 記述 +CbC での Hoare Logic 記述では CodeGear が条件を受け取る + +whileTestPwP は代入を行う CodeGear + +```AGDA + whileTestPwP : {l : Level} {t : Set l} → (c10 : ℕ) + → ((env : Envc ) → (vari env ≡ 0) ∧ (varn env ≡ c10 env) → t) → t + whileTestPwP c10 next = + next (whileTestP c10 ( λ env → env )) (record { pi1 = refl ; pi2 = refl }) +``` +loopPwP' は while loop をするための条件を持ち、ループをする CodeGear + +n と (n ≡ varn env) を受け取り varn でのパターンマッチをしている + +suc n の場合はループを抜けるか判断する CodeGear に継続する + +更に継続先で loopPwP' を呼ぶことで再帰的にループする +```AGDA + loopPwP' : {l : Level} {t : Set l} → (n : ℕ) → (env : Envc ) + → (n ≡ varn env) → (vari env + varn env ≡ c10 env) → + (exit : (env : Envc ) → (vari env ≡ c10 env) → t) → t + loopPwP' zero env refl refl exit = exit env refl + loopPwP' (suc n) env refl refl exit = + whileLoopPwP' (suc n) env refl refl + (λ env x y → loopPwP' n env x y exit) exit +``` +whileLoopPwP' は while loop を抜けるか判断する CodeGear + +loopPwP'から呼ばれている +```AGDA + whileLoopPwP' : {l : Level} {t : Set l} → (n : ℕ) → (env : Envc ) + → (n ≡ varn env) → (vari env + varn env ≡ c10 env) + → (next : (env : Envc ) → (pred n ≡ varn env) + → (vari env + varn env ≡ c10 env) → t) + → (exit : (env : Envc ) → (vari env ≡ c10 env) → t) → t + whileLoopPwP' zero env refl refl _ exit = exit env refl + whileLoopPwP' (suc n) env refl refl next _ = + next (record env {varn = pred (varn env) ; vari = suc (vari env)}) + refl (+-suc n (vari env)) +``` + +conv は whileTestPwP の事後条件から while loop のための loop invaliant に変更する + +```AGDA + conv : (env : Envc ) → (vari env ≡ 0) /\ (varn env ≡ c10 env) + → varn env + vari env ≡ c10 env + conv e record { pi1 = refl ; pi2 = refl } = +zero +``` + +whileTestPCallwP' は先程までの Hoare Logic の記述をつなげたもの + +継続先の CodeGear に渡す条件が +```AGDA + whileTestPCallwP' : (c : ℕ ) → Set + whileTestPCallwP' c = whileTestPwP {_} {_} c ( + λ env s → loopPwP' (varn env) env refl (conv env s) + ( λ env s → vari env ≡ c10 env ) ) +``` + +whileTestPCallwP' では Hoare Logic の条件が接続できた + +--- + +## Hoare Logic をベースにした CbC での while loop +先程条件を接続した whileTestPCallwP' を型に入れ、実際に実行してみる +```AGDA + whileCallwP : (c : ℕ) → whileTestPCallwP' c + whileCallwP c = whileTestPwP {_} {_} c (λ env s → + loopPwP' (c10 env) env (sym (pi2 s)) (conv env s) {!!}) +``` +loopPwP'は任意の値を取ってループを行う CodeGear であった + +しかし、引数で受け取った任意の自然数で実行するとループが停まらない + +任意の自然数回ループする loopPwP' が停まることを補助する loopHelper を記述した +```AGDA + loopHelper : (n : ℕ) → (env : Envc ) → (eq : varn env ≡ n) + → (varn env + vari env ≡ c10 env) + → loopPwP' n env (sym eq) seq (λ env₁ x → (vari env₁ ≡ c10 env₁)) + loopHelper zero env eq refl rewrite eq = refl + loopHelper (suc n) env eq refl rewrite eq = loopHelper n + (record { c10 = suc (n + vari env) ; varn = n ; vari = suc (vari env) }) + refl (+-suc n (vari env)) +``` +loopHelper を用いて記述した実行は実際に停止した +```AGDA + helperCallwP : (c : ℕ) → whileTestPCallwP' c + helperCallwP c = whileTestPwP {_} {_} c + (λ env s → loopHelper c (record { c10 = c ; varn = c ; vari = zero }) refl +zero) +``` + +--- +## CbC での Hoare Logic の健全性 + +implies という data を用いて健全性の証明を行う + +implies の型は A と B の条件を受け取る + +このとき proof として A → B が存在すれば A implies B が証明できる +```AGDA + data _implies_ (A B : Set ) : Set (succ Zero) where + proof : ( A → B ) → A implies B +``` +代入を行う CodeGear である **whileTestP** を実行したとき、\ +常に真の命題 **⊤** と代入を終えたときの事後条件である\ +**(vari env ≡ 0) ∧ (varn env ≡ c10 env)** +を implies に入れた型を記述する + +```AGDA + whileTestPSem : (c : ℕ) → whileTestP c + ( λ env → ⊤ implies (vari env ≡ 0) ∧ (varn env ≡ c10 env) ) + whileTestPSem c = proof ( λ _ → record { pi1 = refl ; pi2 = refl } ) +``` + +証明では proof に( ⊤ → (vari env ≡ 0) ∧ (varn env ≡ c10 env) )であると記述できればよく\ +ここでは λ _ → record { pi1 = refl ; pi2 = refl } がこれに対応する + +**whileTestPSemSound** は output ≡ whileTestP c (λ e → e) を受け取ることで whileTestP の実行が終わった結果、つまり停止した CodeGear の実行結果が事後条件を満たしていることを証明している + +```AGDA + whileTestPSemSound : (c : ℕ ) (output : Envc ) → + output ≡ whileTestP c (λ e → e) + → ⊤ implies ((vari output ≡ 0) ∧ (varn output ≡ c)) + whileTestPSemSound c output refl = whileTestPSem c +``` + +同様に他の CodeGear に対しても健全性の証明が可能 + +whileConvPSemSound は制約を緩める conversion の健全性の証明 +```AGDA +whileConvPSemSound : {l : Level} → (input : Envc) → ((vari input ≡ 0) ∧ (varn input ≡ c)) implies (varn input + vari input ≡ c10 input) +whileConvPSemSound input = proof λ x → (conversion input x) where + conversion : (env : Envc ) → (vari env ≡ 0) /\ (varn env ≡ c10 env) → varn env + vari env ≡ c10 env + conversion e record { pi1 = refl ; pi2 = refl } = +zero +``` + +whileLoopPSemSound は ループを行う CodeGear の 健全性の証明 + +```AGDA +whileLoopPSemSound : {l : Level} → (input output : Envc ) + → (varn input + vari input ≡ c10 input) + → output ≡ loopPP (varn input) input refl + → (varn input + vari input ≡ c10 input) implies (vari output ≡ c10 output) +whileLoopPSemSound {l} input output pre eq = loopPPSem input output eq pre +``` + +loopPPSem を使って証明を行っている + +```AGDA +loopPPSem : (input output : Envc ) → output ≡ loopPP (varn input) input refl + → (varn input + vari input ≡ c10 input ) + → (varn input + vari input ≡ c10 input ) implies (vari output ≡ c10 output) +loopPPSem input output refl s2p = loopPPSemInduct (varn input) input refl refl s2p +``` + +--- +## まとめと今後の課題 +- CodeGear、 DataGear を用いた Hoare Logic ベースの仕様記述を導入した +- Hoare Logic ベースの検証で停止性を含めて検証できた +- Hoare Logic ベースの検証の健全性を証明できた + - while Program で使用した CodeGear を使って証明できた +- 今後の課題 + - BinaryTree の有限ループに対する証明 + - Hoare Logic で検証されたコードの CbC 変換 + - 並列実行での検証 + +--- + +## Comm の実行 +Comm で記述した program を解釈して実行する関数 interpet を記述した + +interpret は 停止性を考慮していないため{-# TERMINATING #-}タグを付けてエラーを回避している +```AGDA +{-# TERMINATING #-} +interpret : Env → Comm → Env +interpret env Skip = env +interpret env Abort = env +interpret env (PComm x) = x env +interpret env (Seq comm comm1) = interpret (interpret env comm) comm1 +interpret env (If x then else) with x env +... | true = interpret env then +... | false = interpret env else +interpret env (While x comm) with x env +... | true = interpret (interpret env comm) (While x comm) +... | false = env +``` +実行する際は test1 のように interpret に Env と Comm を渡してやる +```AGDA +test1 : Env +test1 = interpret ( record { vari = 0 ; varn = 0 } ) (program 10) +``` +実行結果は以下のようになる +```AGDA +record { varn = 0 ; vari = 10 } +``` \ No newline at end of file
--- a/user/ryokka/poster-slide.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/ryokka/poster-slide.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,1 +1,121 @@ -# てすと \ No newline at end of file +Continuation Based C の Hoare Logic を用いた仕様記述と検証 +===== + +琉球大学大学院 : 並列信頼研究室\ +外間 政尊 + +--- + +## OS の検証技術としての Hoare Logic の問題点 +- OS やアプリケーションの信頼性は重要な課題 + +- 信頼性を上げるために仕様の検証が必要 + +- 検証にはモデル検査や**定理証明**などが存在する + + - 定理証明では証明の手法と型システムの対応を用いて検証 + +- また、仕様検証の手法として **Hoare Logic** がある + +- Hoare Logic ではコマンドを実行する上で事前の条件があり、実行が停止したとき成立する条件がある + +- コマンドが細かいため大きなプログラムを記述するのが大変 + +--- + +## Hoare Logic をベースにした Gears 単位での検証 +- 当研究室では 処理の単位を **CodeGear**、データの単位を **DataGear** としてプログラムを記述する手法を提案している + +- CodeGear は Input DataGear を受け取り、処理を行って Output DataGear に書き込む + +- CodeGear は継続を用いて次の CodeGear に接続される + +- **定理証明支援機**である **Agda** 上で CodeGear DataGear の単位を用いた検証を行う + +- 本研究では Gears 単位を用いた Hoare Logic ベースの検証手法を提案する + +--- + +## Hoare Logic +Hoare Logic はプログラム検証の手法 + +事前条件( P )が成り立つとき、コマンド( C )を実行すると事後条件( Q )が成り立つ + +これは **{ P } C { Q }** の形で表され、Hoare Triple と呼ばれる + +以下のような while program を検証した + +n = 10 となっているが検証では n は任意の自然数 + +```C + n = 10; + i = 0; + + while (n>0) + { + i++; + n--; + } +``` + +--- + +## Hoare Logic と while program + +**Seq** はコマンドを2つ受け取って順に実行する + +**PComm** は代入 + +**while** は変数の状態が(0<n)の間、コマンドを繰り返し実行 + +実際に while program を表すために、コマンドでの構文木を記述している + +``` + Seq + / \ + PComm Seq + (n=10) / \ + PComm While + (i=0) | + Cond + (0<n) + | + Seq + / \ + PComm PComm + (i++) (n--) +``` +更にこの後、プログラムの仕様を記述して証明する + +--- + +## CbC での Hoare Logic 概略 +CodeGear は処理の単位、更にメタレベルの処理を Meta CodeGear という単位で分けてる + +メタレベルの処理は今見えるところだと CodeGear 間を接続する処理とか + +![](./hoare-cg-dg.svg) +![](/attachment/5e469a577b378d004670d3d6) + +Meta CodeGear で信頼性の検証を行う + + + +## 詳しい話、質問等はポスターで! +よろしくお願いします + +ご静聴ありがとうございました + + +## CbC での Hoare Logic 記述 +「代入」、「ループ」の2つの CodeGear に分けた + +代入では「事前条件なし」 から 「n=10 かつ i=0」 + +ループでは少し条件を緩めて 「n + i = 10」 + +ループ終了後は 「i=0」が成り立ってるはず + +というのを Gears 単位上で Hoare Logic っぽく検証しましたというお話になる予定 + +--- \ No newline at end of file
--- a/user/soto.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,2 +1,1 @@ -# soto -This is soto's page \ No newline at end of file +no data \ No newline at end of file
--- a/user/soto/log/2020-04-28.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-04-28.md Wed Dec 16 15:11:16 2020 +0900 @@ -21,4 +21,6 @@ - しかし、CbCの記法なら、デバッグしてやればどこの関数でどの値が渡されたからバグが発生しているのかわかる。 ## 雑多やったこと -- Tobiuo君のページ更新の監督をしました \ No newline at end of file +- Tobiuo君のページ更新の監督をしました + - 卒業生のページもやって欲しかった模様…気が回らなくて申し訳ないっす… +- agdaの勉強は今は[ここ](http://agda.wiki.fc2.com/)を見ています \ No newline at end of file
--- a/user/soto/log/2020-05-19.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-05-19.md Wed Dec 16 15:11:16 2020 +0900 @@ -15,14 +15,16 @@ ## 今週の進捗 -バイトの時間以外ずっとソフ演3のoauthをずっとやっていました。 -そしたら日曜日体調を崩しました。 -vscodeのagdaプラグインを調べました。 +- バイトの時間以外ずっとソフ演3のoauthをずっとやっていました。 +- そしたら日曜日体調を崩しました。 +- vscodeのagdaプラグインを調べました。 ## sof3 node.jsでoauthを使ってユーザーの情報を管理したい。 + ですが、自分のwebの理解が足りないのもあってユーザー情報(メールアドレスやトークン情報があるはず)を取得できていない。 + 文献が少ない感じなのでnode.js諦めてもうdjangoでやってしまおうかなという話も… @@ -31,6 +33,9 @@ を調べたのですがどうもシンタックスハイライトと記号のスニペットはあるらしいですが実行は対応していなさそうです。 [コード](https://github.com/j-mueller/language-agda) -別手口でやるとしたらatomにプラグインをいれる方法と -spaceemacsにvimのキーマップをいれるかがありそうです(まだ詳しくは調べていません…) +別手口でやるとしたら +- atomにプラグインをいれる方法と +- spaceemacsにvimのキーマップをいれる +などがありそうです(まだ詳しくは調べていません…) +
--- a/user/soto/log/2020-06-02.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-06-02.md Wed Dec 16 15:11:16 2020 +0900 @@ -34,3 +34,12 @@ ## 今週の進捗 - 論文(axiomatic basis for computer Programming)を読んでいます。 - AtCoderで茶色になりました。 + +## 次 +- +- ryokkaさんが作成したものが少し混雑しているので整頓 + - Pre condition, Post conditionのもの + - Hoare Logicのもの + +## memo +- izaverafolte?でやったものもあるっぽい(あとで調べる)
--- a/user/soto/log/2020-06-16.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-06-16.md Wed Dec 16 15:11:16 2020 +0900 @@ -5,12 +5,12 @@ - CbCとは、Cからループ制御構造とサブルーチンコールを取り除き、継続を導入したCの下位言語である。継続呼び出しは引数付き goto 文で表現される。 -- プログラムの正当性を証明するためにHoare Logicという検証手法がある。これを説明すると、「プログラムの事前条件(P)が成立しているとき、コマンド(C)実行して停止すると(Q)が成り立つ」というもので、CbCの実行を継続するという性質に非常に相性が良い。 +- プログラムの正当性を証明するためにHoare Logicという検証手法がある。これを説明すると、「プログラムの事前条件(P)が成立しているとき、コマンド(C)実行して停止すると事後条件(Q)が成り立つ」というもので、CbCの実行を継続するという性質に非常に相性が良い。 - これらのことから、Hoare Logicを用いてCbCを検証できるか実験していく。 # pre-conditionとpost-conditionについて -- Hoare Logicで前提条件(P)、プログラム(C)、事後条件(P)とあるが、これをCbCに置き換えて考える。 +- Hoare Logicで前提条件(P)、プログラム(C)、事後条件(Q)とあるが、これをCbCに置き換えて考える。 - プログラムは単純にCodeGearとなる。 - 前提条件、事後条件はCodeGearの引数と戻り値であるDataGearとなるが、ここでは引数(前提条件)をPreCondition、戻り値(事後条件)をPostConditionとする。 @@ -27,7 +27,7 @@ - red-black treeもまずはpythonで実装してみて、必要な要素を理解してからagdaで記述したい。 # 近況として -- バイトを週3回から週2回に交渉してきました。(やったね) +- バイトを週3回から週2回に交渉してきました。 - 工学部の近くでハブが出たらしく夜にingressできなくなった。 # 来週は
--- a/user/soto/log/2020-07-14.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-07-14.md Wed Dec 16 15:11:16 2020 +0900 @@ -16,7 +16,7 @@ - 金曜日はrakuのintroをしました。 - [ここ](https://raku.guide/ja/)とかを見てやっていました。 - ~~所感としては結構pythonに似ている感じがしていました~~ -- 土日でAtcoderをしていました。(c++,raku,haskellで) +- 土日でAtcoderをしていました。(c++,raku,pythonで) - 月曜日は論文を読んでいました。 ## xv6 @@ -36,7 +36,7 @@ 退避するメモリが多くなったり、関数呼び出しの回数が増えるとCbCが高速になると考える。 ### やっている際に理解したこと -- `objdump somefilename`でアセンブラが読める +- `objdump somefilename`でアセンブラが読める。 - セグフォがでたら**lldb**で`process launch` するとセグフォの発生場所がわかる。 ### 謎
--- a/user/soto/log/2020-08-25.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-08-25.md Wed Dec 16 15:11:16 2020 +0900 @@ -1,10 +1,26 @@ # 研究目的 +- OSやアプリケーションの信頼性を高めることは重要な課題である。 + +- 研究室でCbCという言語を開発している。その信頼性を証明したい。 + +- CbCとは、Cからループ制御構造とサブルーチンコールを取り除き、継続を導入したCの下位言語である。継続呼び出しは引数付き goto 文で表現される。 + +- プログラムの正当性を証明するためにHoare Logicという検証手法がある。これを説明すると、「プログラムの事前条件(P)が成立しているとき、コマンド(C)実行して停止すると事後条件(Q)が成り立つ」というもので、CbCの実行を継続するという性質に非常に相性が良い。 + +- これらのことから、Hoare Logicを用いてCbCを検証できるか実験していく。 -# やっていること -- axiomとtautology -- +- 先行研究としてwhile programの検証をしている「Continuation based C での Hoare Logic を用いた仕様記述と検証」がある。そこではWhile Loopの検証を行なっていた。 + - ここで、他のループが発生するプログラムの検証が挙げられている。 **同様に検証が行えるのであれば、共通で使えるライブラリのような形でまとめることで、より容易な検証ができるようになるのではないかと考えている。** とあり、Binary Tree や RedBlack Tree などのデータ構造が挙げられる。 -# axiomとtautology +# やったこと +- 外間さんの論文の4章を読んでいました。 + - axiomとtautologyについて + - ploof1のremma1~5について + - soundness +- 土日月は気圧差による頭痛でぐったりしていた。 +- 今日はMK氏と一緒に中間予稿のテンプレートを探してhgにpushするなどしていた + +## axiomとtautology 慣習的なものとあったのですが論文などは見つからなかったです… axiomとtautologyの定義は以下 @@ -15,11 +31,11 @@ Tautology : Cond -> Cond -> Set Tautology pre post = ∀ (env : Env) → (pre env) ⇒ (post env) ≡ true ``` -axiomはつまりpre_condition,command,post_conditionを受け取ってそれを検証できる。 +axiomはつまりpre_condition,command,post_conditionを受け取ってそれを検証できる。普通にHoare Logicを使ってコマンドの検証をしているっぽい。 -Tautologyはpre_condとpost_condの2つを受け取ってそれの検証ができる +Tautologyはpre_condとpost_condの2つを受け取ってそれの検証ができる。 -# lemma1について +## lemma1について ```agda:remma1 lemma1 : {c10 : ℕ} → Axiom (stmt1Cond {c10}) (λ env → record { varn = varn env ; vari = 0 }) @@ -36,7 +52,7 @@ それだとstmt1のvarnは0と等しくして、代入が行われたからstmt2になるという感じのHoare Tripleになるのでは -# lemma2について +## lemma2について ```agda:remma2 lemma2 : {c10 : ℕ} → Tautology stmt2Cond whileInv @@ -46,31 +62,32 @@ lemma23 : {env : Env } → {c10 : ℕ} → stmt2Cond env ≡ true → varn env + vari env ≡ c10 ``` -lemma2の定義はtautologyでstmt2condとwhileInvを受け取っている。 -なのでstmt2condは代入直後のことを言っている。 -whileinvはvarnとvariを足した値が引数と同値であることを示している。 +lemma2の定義はTautologyでstmt2condとwhileInvを受け取っている。 +- stmt2condは代入直後のこと +- whileinvはvarnとvariを足した値が引数と同値であることを示している。 tautologyはconditionを二つ受け取り、両方が正しいことを示す。 つまり代入直後からループを動作させている間も値が等しいことを証明できる。 -# lemma3について +## lemma3について ```agda:lemma3 lemma3 : Axiom (λ e → whileInv e ∧ lt zero (varn e)) - (λ env → record { varn = varn env ; vari = vari env + 1 }) whileInv' + (λ env → record { varn = varn env ; vari = vari env + 1 }) + whileInv' ``` -lemma3の定義はaxiomでPcommの代入の証明となっているので +lemma3の定義はAxiomでPcommの代入の証明となっているので commandがvariに加算するものになっている。 post cond がwhileInv'で こいつの定義がvarnが0以上になっているので良さそう でもvarnが0以下にならない事しか保証されていないような… -# lemma4について +## lemma4について lemma4はループが動く度にvarnは減るけどvariと足して 入力と同地になるようにvariが動くことを保証している気がする。 -# lemma5について +## lemma5について lemma5はtautologyのなんかとtermcond -varnが0より小さいになっている気がするけど大丈夫なのかこれは +varnが0より小さいになっている気がする…? termcondはvariが入力と同じになっている感じ @@ -78,4 +95,10 @@ lemma3はループが動く度にvariが足されるけど varnと足しても入力(c10)と同値になるようにvarnが動く事、 - +## soundness +relOpが何もわからない +一番上のものすらわからない +``` +data Id {l} {X : Set} : Rel X l where + ref : {x : X} -> Id x x +```
--- a/user/soto/log/2020-09-29.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-09-29.md Wed Dec 16 15:11:16 2020 +0900 @@ -25,4 +25,10 @@ - 保険管理センターのバイトをしてきた。 - perlのしかもcgiで書かれていてむずかしかったです。 - 仕様のミスがあったので修正してきた。 -- 普通のバイトしたりもしていた。 \ No newline at end of file +- 普通のバイトしたりもしていた。 + +# 余談 +- ~~スパイウェア~~ Genshin Impact を若干触るなどしていた。 + - PC版はインストールするとカーネル側にアンチチートツールが入るとかで盛り上がっていた。 + - オープンワールドのゲームだったが、iphon11ではスムーズに動作していた。古いandroid機ではカクつく。 + - わりとたのしかった。 \ No newline at end of file
--- a/user/soto/log/2020-10-13.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-10-13.md Wed Dec 16 15:11:16 2020 +0900 @@ -7,7 +7,7 @@ - プログラムの正当性を証明するためにHoare Logicという検証手法がある。これを説明すると、「プログラムの事前条件(P)が成立しているとき、コマンド(C)実行して停止すると事後条件(Q)が成り立つ」というものである。 -- CbC では実行を継続するため、ある関数の実行結果は事後条 件になるが、その実行結果が遷移する次の関数の事前条件になる。それを繋げていくため、個々の関数の正当性を証明することと接続の健全性について証明するだけでプログラム全体の検証を行うことができる。 +- CbC では実行を継続するため、ある関数の実行結果は事後条件になるが、その実行結果が遷移する次の関数の事前条件になる。それを繋げていくため、個々の関数の正当性を証明することと接続の健全性について証明するだけでプログラム全体の検証を行うことができる。 - これらのことから、Hoare Logicを用いてCbCを検証できるか実験していく。 @@ -19,6 +19,7 @@ # 今週の進捗 - シス管の仕事を手伝ったりしていた。 +- SDNのメンターミーティングに参加するなど。 - 保険管理センターのバイトをしてきた。 - 無事終了した。 - 普通にバイトしたりもしていた。 @@ -26,4 +27,7 @@ - 今見てみるとまだ治せるところがありそうでした… # 余談 -- 自作pcを組んだ \ No newline at end of file +- 土日を使って自作pcを組んだ +- fireflyのhgをpathsにしようとしていた + - 切り分けをどうしようか悩んでいる +- 大学院入試の申し込みが明日から \ No newline at end of file
--- a/user/soto/log/2020-11-17.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-11-17.md Wed Dec 16 15:11:16 2020 +0900 @@ -22,10 +22,13 @@ - btとrbt(llrbt)のinsert部分を実装しました - ただ、CbCの要素や検証の要素などは無いです - CbCの方に対応するためには、実装を再起処理で書いてしまっているのでおそらく良く無い + - CbC側で一度実装してからの方が良さそうだった… + - 戻らない関数定義をどうやって定義しようか迷っている - 停電対応 - AtCoder - B問題がちょっと面倒だった - D問題はいもす法を使うらしい。なるほどわからん。 ## 余談 +- Apple m1 チップを搭載したMacが発売されたらしい - 先週はプリコネをしていた \ No newline at end of file
--- a/user/soto/log/2020-11-24.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-11-24.md Wed Dec 16 15:11:16 2020 +0900 @@ -19,17 +19,23 @@ - agdaが変数への再代入を許していない為、ループが存在し、かつ再代入がプログラムに含まれるデータ構造である赤黒木の検証を行う ## 今週の進捗 +- 外間先輩が研究室にきてくれて、Agdaの書き方について教えてもらいました + - 差し入れもくれました。ありがとう先輩! -- continuationなLLRB-Treeのinsertを実装しました。 +- continuationなLLRB-Treeのinsertを実装しました - 関数の最後の方に次の関数へ遷移するように実装したので、おそらく正しく実装できているはず - insertをする際に下のnodeを参照する。その際にkeyと参照するnodeの反対側を保持する - その後、mergeする際に保持したtreeをmergeすることでinsertを実行する -- 関数を循環させたかったのでプロトタイプ宣言のようにできることを発見した。 +- 関数を循環させたかったのでプロトタイプ宣言のようにできることを発見した + +- 関数の実行結果を (Env -> t) のようにして欲しいと言われたのでそのように実装した + - terminationを使っているので、消して行きたい + - これができたら検証をしていきたい - AtCoder - ARCはA問題しか解けなかった - ABCはB問題までしか解けなかった ## 余談 -- 今週はArknightsをやっていた(危機契約難しい) \ No newline at end of file +- 大学院入試の結果が出た。落ちたので悲しい \ No newline at end of file
--- a/user/soto/log/2020-12-1.md Wed Dec 16 15:04:03 2020 +0900 +++ b/user/soto/log/2020-12-1.md Wed Dec 16 15:11:16 2020 +0900 @@ -22,14 +22,54 @@ - continuationなLLRB-Treeのinsertを若干修正 - あまりよろしく無い実装をしていたのでそれを修正 - ループ部分のterminationは外せなさそう(外す際にその部分で実装を行わないといけなくなり、意味が変わってくる) - - rotate-right,leftのnextとexitをどうしようか迷っている。 - - 全てnext/exitのどちらかに統一する方法 - - 例外処理としてexitさせる - - 現在は例外処理としてexitさせているが、nextと同じ遷移先を示している。 + +- nextとexitに投げるものに着いて悩んでいる - 水を購入 -- ダージリンティーを購入 +- ダージリンを設置 + +### 修正部分 + +```Agda +skew' : {l : Level} {t : Set l} → Env → (exit : Env → t) → t +skew' env exit = skew-bt env (λ env → merge-rotate-left env exit exit ) exit + +split' : {l : Level} {t : Set l} → Env → (exit : Env → t) → t +split' env exit = split-branch env (λ env → merge-rotate-right env (λ env → split env exit exit ) (λ env → split env exit exit ) ) exit + +{-# TERMINATING #-} +mergeP : {l : Level} {t : Set l} → Env → (exit : Env → t) → t +mergeP env exit = merge-tree env (λ env → skew' env (λ env → split' env (λ env → mergeP env exit)) ) exit + +whileTestPCall' : (tree : rbt) → (n : ℕ) → Env +whileTestPCall' tree n = whileTestP {_} {_} tree n (λ env → insert env (λ env → mergeP env (λ env → init-col env (λ env → env ) ) ) ) +``` + +- skewとsplitの動作をまとめた +- skew,split関数はループしないのでterminationを落とした + +### nextとexitの話 + +``` Agda +-- 左回転、exitはsplit_branchへ nextもsplit_branchへ +merge-rotate-left : {le : Level} {t : Set le} → Env → (next : Env → t) → (exit : Env → t) → t +merge-rotate-left node@record { vart = bt-empty ; varn = varn ; varl = varl } next exit = exit node +merge-rotate-left node@record { vart = bt-node record { key = record { coler = coler ; number = number } ; ltree = ltree ; rtree = bt-empty } ; varn = varn ; varl = varl } next exit = exit node +merge-rotate-left record { vart = bt-node record { key = record { coler = y ; number = x } ; ltree = l ; rtree = (bt-node record { key = record { coler = ry ; number = rx } ; ltree = rl ; rtree = rr }) } ; varn = varn ; varl = varl } next exit + = next record { vart = bt-node record { key = record { coler = y ; number = rx } + ; ltree = (bt-node record { key = record { coler = red ; number = x } ; ltree = l ; rtree = rl }) + ; rtree = rr} + ; varn = varn ; varl = varl } +``` + +本来は動かない部分をexitとしている。この部分をどうしようか考えている。 +- 全てnext/exitのどちらかに統一する方法 +- exitに例外処理を渡す +- 現在はexitに、nextと同じ遷移先を示している。 + ## 余談 -- 12月になって寒くなってきた \ No newline at end of file +- air podsを買った + - コスパはあまりよくなさそうですが、apple製品との連携が良い +- Agdaのコードを一切ハイライトしてくれなかった… \ No newline at end of file