right_fork->checkAndSet
はInterfaceのAPI呼び出し__code pickup_rfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* right_fork = phils->Rightfork;
goto right_fork->checkAndSet(-1, phils->self, pickup_lfork, pickup_rfork);
}
goto interfaceName->method()
のようにAPIを呼び出す
typedef struct Stack<>{
__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;
#include "../../../context.h"
#interface "Stack.h"
...
__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(...);
}
goto interfaceName->method()
のようにAPIを呼び出すStackTest
interfaceのinsertTest1
をAPI呼び出し
stack
、shutdown
を渡しているStackTest
の実装はcreateStackTestImpl3
で作っているStack* stack = createSingleLinkedStack(context);
StackTest* stackTest = createStackTestImpl3(context);
goto stackTest->insertTest1(stack, shutdown);
par goto
と書くと、並列実行される Phils* phils0 = createPhilsImpl(context,0,fork0,fork1);
Phils* phils1 = createPhilsImpl(context,1,fork1,fork2);
Phils* phils2 = createPhilsImpl(context,2,fork2,fork3);
Phils* phils3 = createPhilsImpl(context,3,fork3,fork4);
Phils* phils4 = createPhilsImpl(context,4,fork4,fork0);
par goto phils0->thinking(exit_code);
par goto phils1->thinking(exit_code);
par goto phils2->thinking(exit_code);
par goto phils3->thinking(exit_code);
par goto phils4->thinking(exit_code);
goto next
などで次の継続に飛ぶ
goto interface->method()
を使うpar goto
で並列実行union Data
型union Data
はすべてのDataGearにキャストすることが可能
union Data
としてDataGearを保存するunion Data
が利用されるunion Data {
struct Stack {
...
} Stack;
struct SingleLinkedStack {
...
} SingleLinkedStack;
struct Context Context;
...
}
ノーマルレベルのCodeGearの継続は、contextとCodeGearの番号のみ指定する
CodeGearの継続は直接行かず、MetaCodeGearを経由して継続する
goto meta
でcontextからCodeGearの取り出し__code
を数え上げる
enum Code {
C_checkAndSetAtomicReference,
C_clearSingleLinkedStack,
C_clearSynchronizedQueue,
C_createTask,
C_decrementTaskCountTaskManagerImpl,
C_exit_code,
C_get2SingleLinkedStack,
...
};
enum DataType {
D_Code,
D_Atomic,
D_AtomicReference,
D_CPUWorker,
D_Context,
D_Element,
...
};
__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, ...);
}
goto meta
に変更されている
next
に代入されている番号で決まるdata
は引数でもらった場所に書き込まれる
__code popSingleLinkedStack(struct Context *context,struct SingleLinkedStack* stack,
enum Code next,union Data **O_data) {
Data* data __attribute__((unused)) = *O_data;
if (stack->top) {
data = stack->top->data;
stack->top = stack->top->next;
} else {
data = NULL;
}
*O_data = data;
goto meta(context, next);
}
__code popSingleLinkedStack_stub(struct Context* context) {
SingleLinkedStack* stack = (SingleLinkedStack*)GearImpl(context, Stack, stack);
enum Code next = Gearef(context, Stack)->next;
Data** O_data = &Gearef(context, Stack)->data;
goto popSingleLinkedStack(context, stack, next, O_data);
}
ファイル名 | 内容 | 元にするファイル |
---|---|---|
*.c | メタレベルに変換したGearsOSのコード | *.cbc |
enumData.h | DataGearの番号を管理するenum | context.h |
enumCode.h | CodeGearの番号を管理するenum | 変換された.cファイル |
extern.h | CodeGearのextern一覧 | 変換された.cファイル |
project-context.c | Contextの初期化ルーチンなどのCodeGear | context.h |
typedefData.h | DataGearのtypef一覧 | context.h |
dataGearInit.c | DataGearのアロケート処理 | context.h |
Impl
の後ろに書く実装名.h
の命名規則 (PhilsImp.h
)typedef struct PhilsImpl <> impl Phils {
int self;
struct AtomicT_int* Leftfork;
struct AtomicT_int* Rightfork;
__code next(...);
} PhilsImpl;
[ 33%] Generating c/examples/DPP2/PhilsImpl.c
[ERROR] Not define eating at examples/DPP2/PhilsImpl.cbc
make[3]: *** [CMakeFiles/DPP2.dir/build.make:101: c/examples/DPP2/PhilsImpl.c] Error 25
make[2]: *** [CMakeFiles/Makefile2:442: CMakeFiles/DPP2.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:450: CMakeFiles/DPP2.dir/rule] Error 2
make: *** [Makefile:293: DPP2] Error 2
項目 | 従来 | 今回の修論 |
---|---|---|
実装の型ファイル | 無し | 新たに導入 |
union Dataの定義 | 手書き | 自動生成 |
context.h | 手書き | 自動生成 |
実装のCodeGearの型名 | 手書き | 自動生成 |
実装のCbCファイル | 手書き | 雛形を自動生成 |
別のInterfaceの出力を取得するStub | 手書き | 自動生成 |
Interfaceの未実装の場合の警告 | 無し | 新たに導入 |
Interfaceのparser | スクリプトに埋め込み | モジュール化 |
MetaCodeGearの差し替え処理 | 手書き | meta.pmによって自動化 |
par gotoのInterface呼び出し | 非対応 | 対応 |
goto meta
に継続するようにPerlで変換される
__code thinkingPhilsImpl(struct Context *context,struct PhilsImpl* phils,
struct Fork* fork, enum Code next) {
printf("%d: thinking\n", phils->self);
goto meta(context, C_pickup_lforkPhilsImpl);
}
mcMeta
)にgotoさせたい__code thinkingPhilsImpl(struct Context *context,struct PhilsImpl* phils,
struct Fork* fork, enum Code next) {
printf("%d: thinking\n", phils->self);
goto mcMeta(context, C_pickup_lforkPhilsImpl);
}
replaceMeta
関数に置換対象と生成するgoto
の組をリストで登録
qr//
に正規表現リテラルで置換対象のCodeGearの名前を指定=>
の先に対応するgoto文の生成関数を指定するPhilsImpl
が名前についているCodeGearが一括でgoto mcMeta
になるpackage meta;
sub replaceMeta {
return (
[qr/PhilsImpl/ => \&generateMcMeta],
);
}
sub generateMcMeta {
my ($context, $next) = @_;
return "goto mcMeta($context, $next);";
}
__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;
stack->top = stack->top->next;
} else {
data1 = NULL;
}
goto next(data, data1, ...);
}
pop2Test1
で受け取る__code pop2Test(struct StackTestImpl3* stackTest, struct Stack* stack, __code next(...)) {
goto stack->pop2(pop2Test1);
}
__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(...);
}
__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 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);
}
goto right_fork->checkAndSet()
なので、Interfaceを使った継続
right_fork->checkAndSet
には数値が入ってる__code pickup_rforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
struct AtomicT_int* right_fork = phils->Rightfork;
Gearef(context, AtomicT_int)->atomicT_int = (union Data*) right_fork;
Gearef(context, AtomicT_int)->oldData = -1;
Gearef(context, AtomicT_int)->newData = phils->self;
Gearef(context, AtomicT_int)->next = C_pickup_lforkPhilsImpl;
(cGearefontext, AtomicT_int)->fail = C_pickup_rforkPhilsImpl;
goto meta(context, right_fork->checkAndSet);
}
__code pickup_rfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* right_fork = phils->Rightfork;
goto right_fork->checkAndSet(-1, phils->self, pickup_lfork, pickup_rfork);
}
__code pickup_rforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
struct AtomicT_int* right_fork = phils->Rightfork;
Gearef(context, AtomicT_int)->atomicT_int = (union Data*) right_fork;
Gearef(context, AtomicT_int)->oldData = -1;
Gearef(context, AtomicT_int)->newData = phils->self;
Gearef(context, AtomicT_int)->next = C_pickup_lforkPhilsImpl;
(cGearefontext, AtomicT_int)->fail = C_pickup_rforkPhilsImpl;
goto meta(context, right_fork->checkAndSet);
}
__code pickup_rforkPhilsImpl_stub(struct Context* context) {
PhilsImpl* phils = (PhilsImpl*)GearImpl(context, Phils, phils);
enum Code next = Gearef(context, Phils)->next;
goto pickup_rforkPhilsImpl(context, phils, next);
}
__code pickup_lfork(struct PhilsImpl* phils, __code next(...)) {
struct AtomicT_int* left_fork = phils->Leftfork;
goto left_fork->checkAndSet(-1, phils->self, pickup_rfork, eating);
}
__code pickup_lforkPhilsImpl(struct Context *context,struct PhilsImpl* phils, enum Code next) {
struct AtomicT_int* left_fork = phils->Leftfork;
Gearef(context, AtomicT_int)->atomicT_int = (union Data*) left_fork;
...
Gearef(context, AtomicT_int)->next = C_pickup_rforkPhilsImpl;
Gearef(context, AtomicT_int)->fail = C_eatingPhilsImpl;
goto meta(context, left_fork->checkAndSet);
}