- Gears OS では Context と呼ばれる、使用されるすべての Code Gear、Data Gear を持つ Meta Data Gear を持っている。
@@ -289,6 +341,17 @@
Context
+
+ - CbC はポインタを扱えるので、アセンブラ的に書けてしまう。
+ - Code Gear は関数型プログラミング的に意味があるように書きたい。
+ - Code Gear は入力された型の決まった Data Gear のみ扱えるように Context を利用する。
+
+
+
+
+
+
+
Context
- Context は全ての Code Gear のリストを持っており、enum で番号とアドレスを対応付けている。
@@ -310,7 +373,7 @@
-
Context
+
Context
- Data Gear も Code Gear と同様に Context が全ての Data Gear のリストを持っている。
- Data Gear のリストも enum で管理されている。
@@ -330,6 +393,20 @@
+
目次
+
+ - Code Gear と Data Gear
+ - Gears OS におけるメタ計算
+ - Context
+ - Meta Code Gear
+ - Interface
+ - Interface 導入についての評価
+
+
+
+
+
+
stub Code Gear
- ノーマルレベルの Gears OS では継続先に渡す Data Gear は引数の集合に見える。
@@ -416,6 +493,20 @@
+
目次
+
+ - Code Gear と Data Gear
+ - Gears OS におけるメタ計算
+ - Context
+ - Meta Code Gear
+ - Interface
+ - Interface 導入についての評価
+
+
+
+
+
+
Interface
- Interface は Gears OS のモジュール化の仕組みである。
@@ -580,6 +671,85 @@
+
目次
+
+ - Code Gear と Data Gear
+ - Gears OS におけるメタ計算
+ - Context
+ - Meta Code Gear
+ - Interface
+ - Interface 導入についての評価
+
+
+
+
+
+
+
Interface を用いない pushStack の記述
+
+ - Interface を用いない場合の Code Gear では、完全にメタレベルとノーマルレベルが分離されておらず、
+Code Gear の引数の Data Gear に対応する番号を示さなくてはならなかった。
+ - また、継続先も直接指定しなければならなかった。
+
+
+
__code cg1 (struct Context* context, struct Element* element) {
+ allocate->size = sizeof(struct Node);
+ allocator(context);
+ goto meta(context, putSingleLinkedStack)
+}
+
+__code pushSingleLinkedStack(struct Context* context, struct SingleLinkedStack* stack, struct Node* node) {
+ ...
+}
+
+__code pushSingleLinkedStack_stub(struct Context* context){
+ SingleLinkedStack* stack = &context->data[SingleLinkedStack]->SingleLinkedStack;
+ Node *node = &context->data[context->dataNum]->node;
+ goto pushSingleLinkedStack(context, stack, data);
+}
+
+
+
+
+
+
+
Interface を用いた pushStack の記述
+
+ - Interface を用いることでノーマルレベルとメタレベルが分離され、stub も自動生成されるようになった。
+ - 継続先も stack->push となることで、抽象化され、異なる実装にも対応できるようになった。
+
+
__code cg1 (struct Stack* stack) {
+ struct Node* node1 = new Node();
+ goto stack->push((union Data*)node1,cg2);
+}
+
+__code pushSingleLinkedStack(struct SingleLinkedStack* stack, union Data* data, __code next(...)) {
+ ...
+}
+
+__code pushSingleLinkedStack_stub(struct Context* context){
+ SingleLinkedStack* stack = (SingleLinkedStack*)context->data[D_Stack]->Stack.stack->Stack.stack;
+ Data* data = &context->data[D_Stack]->Stack->data;
+ enum Code next = &context->data[D_Stack]->Stack->next;
+ goto pushSingleLinkedStack(context, stack, data, next);
+}
+
+
+
+
+
+
+
目次
+
+ - xv6 の書き換えの方針について
+ - cbc_read の実装
+ - CbC 書き換えについての評価
+
+
+
+
+
+
xv6 の CbC 書き換え
- xv6 は UNIX V6 を x86 向けに再実装した OS である。
@@ -603,7 +773,7 @@
-
システムコールの書き換え
+
システムコールの書き換え
- CbC は C と互換性のある言語であるため、元のソースコードから大きく崩すことなく必要な機能のみを CbC へと書き換えることが可能である。
- ここでは実際にシステムコールを CbC で書き換えることによって、状態遷移ベースで書き換えるには何が必要か示すことにした。
@@ -614,6 +784,17 @@
+
目次
+
+ - xv6 の書き換えの方針について
+ - cbc_read の実装
+ - CbC 書き換えについての評価
+
+
+
+
+
+
syscall関数
- syscall 関数 はシステムコールを呼び出す関数である。
@@ -794,6 +975,322 @@
...
+
+
+
+
+
consoleread
+
+ - console への入力を読み込み、待っている間スリープする
+
+
int consoleread (struct inode *ip, char *dst, int n)
+{
+ uint target;
+ int c;
+ iunlock(ip);
+ target = n;
+ acquire(&input.lock);
+
+ while (n > 0) {
+ while (input.r == input.w) {
+ if (proc->killed) {
+ release(&input.lock);
+ ilock(ip);
+ return -1;
+ }
+ sleep(&input.r, &input.lock);
+ }
+ c = input.buf[input.r++ % INPUT_BUF];
+ if (c == C('D')) { // EOF
+ if (n < target) {
+ input.r--;
+ }
+ break;
+ }
+ *dst++ = c;
+ --n;
+ if (c == '\n') {
+ break;
+ }
+ }
+ release(&input.lock);
+ ilock(ip);
+ return target - n;
+}
+
+
+
+
+
+
+
cbc_consoleread
+
+
__code cbc_consoleread (struct inode *ip, char *dst, int n, __code(*next)(int ret))
+{
+ uint target;
+
+ iunlock(ip);
+
+ target = n;
+ acquire(&input.lock);
+
+ if (n > 0) {
+ proc->cbc_arg.cbc_console_arg.n = n;
+ proc->cbc_arg.cbc_console_arg.target = target;
+ proc->cbc_arg.cbc_console_arg.dst = dst;
+ proc->cbc_arg.cbc_console_arg.ip = ip;
+ proc->cbc_arg.cbc_console_arg.next = next;
+ goto cbc_consoleread2();
+ }
+ goto cbc_consoleread1();
+}
+
+
+
+
+
+
+
cbc_consoleread
+
__code cbc_consoleread2 ()
+{
+ struct inode *ip = proc->cbc_arg.cbc_console_arg.ip;
+ __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next;
+ if (input.r == input.w) {
+ if (proc->killed) {
+ release(&input.lock);
+ ilock(ip);
+ goto next(-1);
+ }
+ goto cbc_sleep(&input.r, &input.lock, cbc_consoleread2);
+ }
+ goto cbc_consoleread1();
+}
+
+__code cbc_consoleread1 ()
+{
+ int cont = 1;
+ int n = proc->cbc_arg.cbc_console_arg.n;
+ int target = proc->cbc_arg.cbc_console_arg.target;
+ char* dst = proc->cbc_arg.cbc_console_arg.dst;
+ struct inode *ip = proc->cbc_arg.cbc_console_arg.ip;
+ __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next;
+
+ int c = input.buf[input.r++ % INPUT_BUF];
+
+ if (c == C('D')) { // EOF
+ if (n < target) {
+ input.r--;
+ }
+ cont = 0;
+ }
+
+ *dst++ = c;
+ --n;
+ if (c == '\n') {
+ cont = 0;
+ }
+ if (cont == 1) {
+ if (n > 0) {
+ proc->cbc_arg.cbc_console_arg.n = n;
+ proc->cbc_arg.cbc_console_arg.target = target;
+ proc->cbc_arg.cbc_console_arg.dst = dst;
+ proc->cbc_arg.cbc_console_arg.ip = ip;
+ proc->cbc_arg.cbc_console_arg.next = next;
+ goto cbc_sleep(&input.r, &input.lock, cbc_consoleread2);
+ }
+ }
+ release(&input.lock);
+ ilock(ip);
+ goto next(target - n);
+}
+
+
## sleep
+- プロセスをスリープ状態にしてスケジューラーへ引き渡す。
+
void sleep(void *chan, struct spinlock *lk)
+{
+ 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;
+ sched();
+
+ proc->chan = 0;
+
+ if(lk != &ptable.lock){ //DOC: sleeplock2
+ release(&ptable.lock);
+ acquire(lk);
+ }
+}
+
+
+
+
+
+
+
cbc_sleep
+
__code cbc_sleep1()
+{
+ struct spinlock *lk = proc->lk;
+ proc->chan = 0;
+
+ if(lk != &ptable.lock){ //DOC: sleeplock2
+ release(&ptable.lock);
+ acquire(lk);
+ }
+ goto proc->cbc_next();
+}
+
+__code cbc_sleep(void *chan, struct spinlock *lk, __code(*next1)())
+{
+ 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;
+ proc->cbc_next = next1;
+
+ goto cbc_sched(cbc_sleep1);
+}
+
+
+
+
+
+
+
sched
+
+ - レジスタの値を切り替えて、スケジューラーへと戻る
+ - 再開時は swtch の下から再開する。
+
+
void sched(void)
+{
+ 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;
+}
+
+
+
+
+
+
+
cbc_sched
+
__code cbc_sched(__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();
+}
+
+
## 目次
+- xv6 の書き換えの方針について
+- cbc_read の実装
+- CbC 書き換えについての評価
+
+
+
+
+
+
read システムコールの遷移図
+
+ - CbC へ書き換えることで状態遷移ベースのプログラムに書き換えることができた。
+ - 現在はシステムコールのみだが、カーネル全体を書き換えることで、OS の状態遷移モデルができる。
+
+
+
+
+
+
+
+
+
+
CbC 書き換えについて
+
+ - xv6 のシステムコールを CbC に書き換えると、関数は分割され、継続後の元の環境がなくなるためプロセス構造体に値を保持しておかなくてはならないことがわかった。
+ - しかしこれは、操作によってどの値が書き換えられるかということが明示的になり、
+また、このプロセス構造体が Context と同等の役割を果たすことがわかった。
+ - プロセス構造体を Context として扱い、Interface を用いてモジュール化することで、値渡しなどは Meta Gear に押し込むことができると考察できる。
+
+
+
+
+
+
+
まとめ
+
+ - Interface の導入と、Meta Gear の自動変換・生成によって、ノーマルレベルのプログラミングの見通しが良くなった。
+ - xv6 のシステムコールの書き換えにより、xv6 の CbC 書き換えの方針の考察ができた。
+
+
+
+
+
+
+
今後の課題
+
+ - 現在はシステムコールのみの書き換えだが、カーネル全体の書き換えを行う。
+ - モジュール化された xv6 の機能を Gears OS のものと書き換えることで Gears OS に OS の機能を持たせる。
+ - また、QEMU でのみの動作でしか確認できていないため、実機上での動作を可能にしたい。
+
diff -r 09c168f8116a -r ecf9d73f18f5 slide/slide.md
--- a/slide/slide.md Wed Feb 13 09:47:53 2019 +0900
+++ b/slide/slide.md Wed Feb 13 15:15:59 2019 +0900
@@ -1,4 +1,4 @@
-title: 継続を基本とした言語による OS のモジュール化
+title: 継続を基本とした言語による
OS のモジュール化
author: 宮城 光希
profile: 琉球大学理工学研究科 河野研
lang: Japanese
@@ -52,11 +52,12 @@
- 第2部では xv6 の CbC による書き換え について発表する。
## 目次
-- Code Gear と Data Gear
+- **Code Gear と Data Gear**
- Gears OS におけるメタ計算
- Context
- Meta Code Gear
- Interface
+- Interface 導入についての評価
## CbC のコード例
- Code Gear は\_\_code Code Gear 名 (引数) の形で記述される。
@@ -103,6 +104,13 @@
};
```
+## 目次
+- Code Gear と Data Gear
+- **Gears OS におけるメタ計算**
+- Context
+- Meta Code Gear
+- Interface
+
## Gears でのメタ計算
- Gears OS ではメタ計算を Meta Code/Data Gear で表現する。
- Meta Code Gear は通常の Code Gear の直後で遷移し、メタ計算を実行する。
@@ -126,12 +134,25 @@