changeset 1015:e6778c866876

add DebugWorker and DebugTaskManager
author Takato Matsuoka <t.matsuoka@cr.ie.u-ryukyu.ac.jp>
date Tue, 18 Jan 2022 19:54:28 +0900
parents a9c630cc1c65
children 3e8d89f271e2 e0a60e5f7f4f
files src/parallel_execution/CMakeLists.txt src/parallel_execution/DebugTaskManagerImpl.cbc src/parallel_execution/DebugTaskManagerImpl.h src/parallel_execution/DebugWorker/DebugWorker.cbc src/parallel_execution/DebugWorker/DebugWorker.h src/parallel_execution/DebugWorker/TaskIterator.c src/parallel_execution/DebugWorker/TaskIterator.h src/parallel_execution/DebugWorker/crc32.c src/parallel_execution/DebugWorker/crc32.h src/parallel_execution/DebugWorker/memory.c src/parallel_execution/DebugWorker/memory.h src/parallel_execution/DebugWorker/state_db.c src/parallel_execution/DebugWorker/state_db.h src/parallel_execution/examples/DebughelloWorld/Hello.h src/parallel_execution/examples/DebughelloWorld/HelloImpl.cbc src/parallel_execution/examples/DebughelloWorld/HelloImpl.h src/parallel_execution/examples/DebughelloWorld/main.cbc src/parallel_execution/examples/DebughelloWorld/meta.pm
diffstat 18 files changed, 1378 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/parallel_execution/CMakeLists.txt	Sat Jan 15 17:43:04 2022 +0900
+++ b/src/parallel_execution/CMakeLists.txt	Tue Jan 18 19:54:28 2022 +0900
@@ -180,6 +180,14 @@
   TaskManagerImpl.cbc CPUWorker.cbc SynchronizedQueue.cbc AtomicReference.cbc SingleLinkedStack.cbc examples/helloWorld/main.cbc examples/helloWorld/HelloImpl.cbc
 )
 
+GearsCommand(
+  TARGET
+  Debug_hello_world
+  SOURCES
+  CPUWorker.cbc SynchronizedQueue.cbc AtomicReference.cbc SingleLinkedStack.cbc examples/DebughelloWorld/main.cbc examples/DebughelloWorld/HelloImpl.cbc
+    DebugWorker/DebugWorker.cbc DebugTaskManagerImpl.cbc DebugWorker/crc32.c DebugWorker/memory.c DebugWorker/state_db.c
+)
+
 
 GearsCommand(
   TARGET
@@ -212,6 +220,14 @@
     TaskManagerImpl.cbc CPUWorker.cbc SingleLinkedQueue.cbc AtomicReference.cbc SynchronizedQueue.cbc examples/gearsFile/GearsFileImpl.cbc examples/gearsFile/GearsFile_test.cbc 
 )
 
+GearsCommand(
+  TARGET
+    Debug_gearsFile
+  SOURCES
+    CPUWorker.cbc SingleLinkedQueue.cbc AtomicReference.cbc SynchronizedQueue.cbc examples/gearsFile/GearsFileImpl.cbc examples/gearsFile/GearsFile_test.cbc 
+    DebugWorker/DebugWorker.cbc DebugTaskManagerImpl.cbc
+)
+
 
 GearsCommand(
   TARGET
@@ -270,4 +286,4 @@
   socket_wc
   SOURCES
   examples/socketQueue/RemoteDGMQueue.cbc  examples/socketQueue/wordCount_Remote.cbc AtomicReference.cbc SingleLinkedStack.cbc
-)
\ No newline at end of file
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugTaskManagerImpl.cbc	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,240 @@
+#include "../context.h"
+#interface "TaskManager.h"
+#interface "Iterator.h"
+#interface "Queue.h" 
+#interface "Worker.h" 
+
+#include <stdio.h>
+#include <unistd.h>
+
+// プロトタイプ宣言
+static void defaultStatefunc(DebugTaskManagerImpl* debugTaskManagerImpl, struct DebugWorker* debugWorker , StateDB now,StateDB next,int flag) {
+}
+void createWorkers(struct Context* context, DebugTaskManagerImpl* taskManager);
+
+// DebugTaskManagerの作成。enumや変数の初期化を行う。
+TaskManager* createDebugTaskManagerImpl(struct Context* context, int numCPU, int numGPU, int numIO) {
+    printf("[Debug log] createDebugTaskManagerImpl in DebugTaskManager\n");
+    // TaskManager構造体の生成および、構造体で定義された関数とenumの紐付け。
+    struct TaskManager* taskManager = new TaskManager();
+    taskManager->spawnTasks = C_spawnTasksDebugTaskManagerImpl;
+    taskManager->spawn = C_spawnDebugTaskManagerImpl;
+    taskManager->shutdown  = C_shutdownDebugTaskManagerImpl;
+    taskManager->incrementTaskCount = C_incrementTaskCountDebugTaskManagerImpl;
+    taskManager->decrementTaskCount = C_decrementTaskCountDebugTaskManagerImpl;
+    taskManager->setWaitTask = C_setWaitTaskDebugTaskManagerImpl;
+
+    // Impl構造体の生成および、構造体で定義された変数の初期化
+    struct DebugTaskManagerImpl* taskManagerImpl = new DebugTaskManagerImpl(); 
+    // 0...numIO-1 IOProcessor
+    // numIO...numIO+numGPU-1 GPUProcessor
+    // numIO+numGPU...numIO+numGPU+numCPU-1 CPUProcessor
+    taskManagerImpl->io = 0;
+    taskManagerImpl->gpu = numIO;
+    taskManagerImpl->cpu = numIO+numGPU;
+    taskManagerImpl->maxCPU = numIO+numGPU+numCPU;
+    taskManagerImpl->numWorker = taskManagerImpl->maxCPU;
+    taskManagerImpl->sendGPUWorkerIndex = taskManagerImpl->gpu;
+    taskManagerImpl->sendCPUWorkerIndex = taskManagerImpl->cpu;
+    taskManagerImpl->taskCount = 0;
+    taskManagerImpl->loopCounter = 0;
+    taskManagerImpl->mem = 0;
+    taskManagerImpl->statefunc = defaultStatefunc;
+    context->taskManager = taskManager;
+    createWorkers(context, taskManagerImpl);
+    taskManager->taskManager = (union Data*)taskManagerImpl;
+    return taskManager;
+}
+
+// workerの作成。CPUやGPU, モデル検査など環境によって作成するWorkerを変更する。
+void createWorkers(struct Context* context, DebugTaskManagerImpl* taskManager) {
+    printf("[Debug log] createWorkers in DebugTaskManager\n");
+    int i = 0;
+    taskManager->workers = (Worker**)ALLOCATE_PTR_ARRAY(context, Worker, taskManager->maxCPU);
+    for (;i<taskManager->gpu;i++) {
+        Queue* queue = createSynchronizedQueue(context);
+        taskManager->workers[i] = (Worker*)createCPUWorker(context, i, queue);
+    }
+    for (;i<taskManager->cpu;i++) {
+        Queue* queue = createSynchronizedQueue(context);
+#ifdef USE_CUDAWorker
+        taskManager->workers[i] = (Worker*)createCUDAWorker(context, i, queue,0);
+#else
+        taskManager->workers[i] = (Worker*)createDebugWorker(context, i, queue);
+#endif
+    }
+    for (;i<taskManager->maxCPU;i++) {
+        Queue* queue = createSynchronizedQueue(context);
+        taskManager->workers[i] = (Worker*)createDebugWorker(context, i, queue);
+    }
+}
+
+// 一連のspawnTaskの始動関数
+__code spawnTasksDebugTaskManagerImpl(struct DebugTaskManagerImpl* taskManager, struct Element* taskList, __code next1(...)) {
+    printf("[Debug log] spawnTaskDebugTaskManagerImpl in DebugTaskManager\n");
+    taskManager->taskList = taskList;
+    goto spawnTasksDebugTaskManagerImpl1();
+}
+
+__code spawnTasksDebugTaskManagerImpl1(struct DebugTaskManagerImpl* taskManagerImpl, struct TaskManager* taskManager) {
+    printf("[Debug log] spawnTasksDebugTaskManagerImpl1 in DebugTaskManager\n");
+    // TaskListにTaskがない場合
+    if (taskManagerImpl->taskList == NULL) {
+        goto spawnTasksDebugTaskManagerImpl2();
+    }
+    // TaskListにTaskがあった場合、taskListからtaskを取り出し、taskListを次のtaskへ更新してsetWaitTaskへ継続。
+    struct Context* task = (struct Context*)taskManagerImpl->taskList->data;
+    taskManagerImpl->taskList = taskManagerImpl->taskList->next;
+    goto taskManager->setWaitTask(task, spawnTasksDebugTaskManagerImpl1);
+}
+
+__code spawnTasksDebugTaskManagerImpl1_stub(struct Context* context) {
+    DebugTaskManagerImpl* taskManagerImpl = (DebugTaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    TaskManager* taskManager = &Gearef(context, TaskManager)->taskManager->TaskManager;
+    goto spawnTasksDebugTaskManagerImpl1(context, taskManagerImpl, taskManager);
+}
+
+__code spawnTasksDebugTaskManagerImpl2(struct DebugTaskManagerImpl* taskManager, struct Element* taskList, __code next1(...)) {
+    printf("[Debug log] spawnTasksDebugTaskManagerImpl2 DebugTaskManager\n");
+    taskManager->taskList = taskList;
+    goto spawnTasksDebugTaskManagerImpl3();
+}
+
+__code spawnTasksDebugTaskManagerImpl3(struct DebugTaskManagerImpl* taskManagerImpl, __code next1(...), struct TaskManager* taskManager) {
+    printf("[Debug log] spawnTasksDebugTaskManagerImpl3 in DebugTaskManager\n");
+    if (taskManagerImpl->taskList == NULL) {
+        // struct Queue* tasks = taskManagerImpl->workers[0]->tasks;
+        // printf("put NULL\n");
+        printf("execute spawnDebugTaskManagerImpl3\n");
+        goto next1(...);
+    }
+    struct Context* task = (struct Context*)taskManagerImpl->taskList->data;
+    taskManagerImpl->taskList = taskManagerImpl->taskList->next;
+    goto taskManager->spawn(task, spawnTasksDebugTaskManagerImpl3);
+}
+
+__code spawnTasksDebugTaskManagerImpl3_stub(struct Context* context) {
+    DebugTaskManagerImpl* taskManagerImpl = (DebugTaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    enum Code next1 = Gearef(context, TaskManager)->next1;
+    TaskManager* taskManager = &Gearef(context, TaskManager)->taskManager->TaskManager;
+    goto spawnTasksDebugTaskManagerImpl3(context, taskManagerImpl, next1, taskManager);
+}
+
+// TaskをQueueにputする
+__code setWaitTaskDebugTaskManagerImpl(struct DebugTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    printf("[Debug log] setWaitTaskDebugTaskManagerImpl in DebugTaskManager\n");
+    int i = taskManager->loopCounter;
+    if (task->idg+i < task->maxIdg) {
+        struct Queue* queue = GET_WAIT_LIST(task->data[task->idg + i]);
+        taskManager->loopCounter++;
+        goto queue->put(task, setWaitTaskDebugTaskManagerImpl);
+    }
+    taskManager->loopCounter = 0;
+    goto incrementTaskCountDebugTaskManagerImpl();
+}
+
+__code incrementTaskCountDebugTaskManagerImpl(struct DebugTaskManagerImpl* taskManager, __code next(...)) {
+    printf("[Debug log] incrementTaskCountDebugTaskManagerImpl in DebugTaskManager\n");
+    __sync_fetch_and_add(&taskManager->taskCount, 1);
+    goto next(...);
+}
+
+__code decrementTaskCountDebugTaskManagerImpl(struct DebugTaskManagerImpl* taskManager, __code next(...)) {
+    printf("[Debug log] decrementTaskCountDebugTaskManagerImpl in DebugTaskManager\n");
+    __sync_fetch_and_sub(&taskManager->taskCount, 1);
+    goto next(...);
+}
+
+__code spawnDebugTaskManagerImpl(struct DebugTaskManagerImpl* taskManagerImpl, struct Context* task, __code next(...), struct TaskManager* taskManager) {
+    printf("[Debug log] spawnDebugTaskManagerImpl in DebugTaskManager\n");
+    task->taskManager = taskManager;
+    if (task->idgCount == 0) {
+        // iterator task is normal task until spawned
+        if (task->iterator != NULL && task->iterate == 0) {
+            pthread_mutex_unlock(&taskManagerImpl->mutex);
+            struct Iterator* iterator = task->iterator;
+            goto iterator->exec(task, taskManagerImpl->cpu - taskManagerImpl->gpu, next(...));
+        }
+        goto taskSend();
+    }
+    pthread_mutex_unlock(&taskManagerImpl->mutex);
+    goto next(...);
+}
+
+__code spawnDebugTaskManagerImpl_stub(struct Context* context) {
+    DebugTaskManagerImpl* taskManagerImpl = (DebugTaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    struct Context* task = Gearef(context, TaskManager)->task;
+    TaskManager* taskManager = &Gearef(context, TaskManager)->taskManager->TaskManager;
+    goto spawnDebugTaskManagerImpl(context,
+                              taskManagerImpl,
+                              task,
+                              Gearef(context, TaskManager)->next,
+                              taskManager);
+}
+
+
+__code taskSend(struct DebugTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    printf("[Debug log] taskSend in DebugTaskManager\n");
+    // set workerId
+    if (task->gpu) {
+        goto taskSend1();
+    } else {
+        goto taskSend2();
+    }
+}
+
+__code taskSend1(struct DebugTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    int workerId = taskManager->sendGPUWorkerIndex;
+    if (++taskManager->sendGPUWorkerIndex >= taskManager->cpu) {
+        taskManager->sendGPUWorkerIndex = taskManager->gpu;
+    }
+    pthread_mutex_unlock(&taskManager->mutex);
+    struct Queue* queue = taskManager->workers[workerId]->tasks;
+    // printf("tasks->put taskSend1\n");
+    goto queue->put(task, next(...));
+}
+
+__code taskSend2(struct DebugTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    printf("[Debug log] taskSend2 in DebugTaskManager\n");
+    int workerId = taskManager->sendCPUWorkerIndex;
+    if (++taskManager->sendCPUWorkerIndex >= taskManager->maxCPU) {
+        taskManager->sendCPUWorkerIndex = taskManager->cpu;
+    }
+    pthread_mutex_unlock(&taskManager->mutex);
+    struct Queue* queue = taskManager->workers[workerId]->tasks;
+    printf("execute taskSend2\n");
+    goto queue->put(task, next(...));
+}
+
+__code shutdownDebugTaskManagerImpl(struct DebugTaskManagerImpl* taskManager, __code next(...)) {
+    printf("[Debug log] shutdownDebugTaskManagerImpl in DebugTaskManager\n");
+    if (taskManager->taskCount != 0) {
+        usleep(1000);
+        goto shutdownDebugTaskManagerImpl();
+    }
+    int i = taskManager->loopCounter;
+    if (i < taskManager->numWorker) {
+        struct Queue* tasks = taskManager->workers[i]->tasks;
+        goto tasks->put(NULL, shutdownDebugTaskManagerImpl1);
+    }
+    taskManager->loopCounter = 0;
+    goto shutdownDebugTaskManagerImpl2();
+}
+
+__code shutdownDebugTaskManagerImpl1(struct DebugTaskManagerImpl* taskManager, __code next(...)) {
+    printf("[Debug log] shutdownDebugTaskManagerImpl1 in DebugTaskManager\n");
+    taskManager->loopCounter++;
+    goto shutdownDebugTaskManagerImpl();
+}
+
+__code shutdownDebugTaskManagerImpl2(struct DebugTaskManagerImpl* taskManager, __code next(...)) {
+    printf("[Debug log] shutdownDebugTaskManagerImpl2 in DebugTaskManager\n");
+    int i = taskManager->loopCounter;
+    if (i < taskManager->numWorker) {
+        pthread_join(taskManager->workers[i]->thread, NULL);
+        taskManager->loopCounter++;
+        goto shutdownDebugTaskManagerImpl2();
+    }
+    taskManager->loopCounter = 0;
+    goto next(...);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugTaskManagerImpl.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,19 @@
+typedef struct DebugTaskManagerImpl <> impl TaskManager {
+  int numWorker;
+  int sendCPUWorkerIndex;
+  int sendGPUWorkerIndex;
+  int taskCount;
+  pthread_mutex_t mutex;
+  struct Queue* activeQueue;
+  struct Worker** workers;
+  struct Element* taskList;
+  MemoryPtr mem; // memorylenge for Debugger
+  StateDB state_db;
+  int loopCounter;
+  int cpu;
+  int gpu;
+  int io;
+  int maxCPU;
+  void (*statefunc)(struct DebugTaskManagerImpl* debugTaskManagerImpl, struct DebugWorker* debugWorker, StateDB now, StateDB next, int flag);
+  __code next(...);
+} DebugTaskManagerImpl;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/DebugWorker.cbc	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,250 @@
+#include "../../context.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "../../DebugWorker/state_db.h"
+
+#interface "TaskManager.h"
+#interface "Worker.h"
+#interface "Iterator.h"
+#interface "Queue.h"
+
+
+static void startWorker(Worker* worker);
+
+#define INPUT_BUFFER_SIZE 256
+#define NUM_OF_COMMAND 2
+
+// workerの作成、初期化、スレッド作成
+Worker* createDebugWorker(struct Context* context, int id, Queue* queue) {
+    printf("[Debug log] createDebugWorker in DebugWorker\n");
+    struct Worker* worker = new Worker();
+    struct DebugWorker* debugWorker = new DebugWorker();
+    worker->worker = (union Data*)debugWorker;
+    worker->tasks = queue;
+    debugWorker->id = id;
+
+    // debugWorker->depth = 0;
+    // debugWorker->count = 0;
+    // debugWorker->change = 0;
+    // debugWorker->debugContext = NULL;
+    // debugWorker->masterContext = context; //singleton
+    
+	debugWorker->loopCounter = 0;
+    debugWorker->taskManager = context->taskManager;
+    worker->taskReceive = C_taskReceiveDebugWorker;
+    worker->shutdown = C_shutdownDebugWorker;
+    pthread_create(&worker->thread, NULL, (void*)&startWorker, worker);
+    return worker;
+}
+
+// スレッド用Contextの作成
+static void startWorker(struct Worker* worker) {
+    printf("[Debug log] startWorker in DebugWorker\n");
+    struct DebugWorker* debugWorker = &worker->worker->DebugWorker;
+    debugWorker->context = NEW(struct Context);
+    initContext(debugWorker->context);
+    debugWorker->context->worker = worker;
+    Gearef(debugWorker->context, Worker)->worker = (union Data*)worker;
+    Gearef(debugWorker->context, Worker)->tasks = worker->tasks;
+    printf("[Debug log] finished startWorker in DebugWorker\n");
+    goto meta(debugWorker->context, worker->taskReceive);
+}
+
+// task Queueからtaskの取得
+__code taskReceiveDebugWorker(struct DebugWorker* worker, struct Queue* tasks) {
+    printf("[Debug log] taskReceiveDebugWorker in debug worker\n");
+    goto tasks->take(getTaskDebugWorker);
+}
+
+// extern int visit_StateDB(StateDB s, StateDB *parent, StateDB* out, int visit);
+
+__ncode printDataGear(struct Context* context, enum Code next, char *dataGear_name) {
+    context->next = next; // remember next Code 
+    
+    if (strcmp(dataGear_name, "Context") == 0) {
+        printf("DataGear Name: %s\n", dataGear_name);
+        printf("next CodeGear: %i\n", context->next);
+        // printf("Worker: %i\n", context->worker);
+
+    } else if (strcmp(dataGear_name, "Phils") == 0) {
+        printf("DataGear Name: %s\n", dataGear_name);
+        printf("DataGear Address: %p\n", context->data);
+        printf("Phils Address: %p\n", Gearef(context, Phils));
+        printf("putdown_rfork: %i\n", Gearef(context, Phils)->putdown_rfork);
+        printf("thinking: %i\n", Gearef(context, Phils)->thinking);
+        printf("pickup_lfork: %i\n", Gearef(context, Phils)->pickup_lfork);
+        printf("pickup_rfork: %i\n", Gearef(context, Phils)->pickup_rfork);
+        printf("eating: %i\n", Gearef(context, Phils)->eating);
+        printf("next: %i\n", Gearef(context, Phils)->next);
+    } else {
+        printf("invalid options. Please enter correct DataGear name option.\n");
+    }
+    goto debugMeta(context, context->next);
+}
+
+__ncode debugMeta(struct Context* context, enum Code next) {
+    printf("[Debug log] debugMeta in DebugWorker\n");
+    context->next = next; // remember next Code Gear
+    printf("start get debugWorker\n");
+    struct DebugWorker* debugWorker = (struct DebugWorker*) Gearef(context, Worker);
+	// struct DebugWorker* debugWorker = (struct DebugWorker*) context->worker->worker;
+    printf("finish get debugWorker\n");
+	StateNode st;
+	StateDB out = &st;
+    struct Element* list = NULL;
+	struct DebugTaskManagerImpl* debugTaskManagerImpl = (struct DebugTaskManagerImpl *)debugWorker->taskManager->taskManager;
+	out->memory = debugTaskManagerImpl->mem;
+    out->hash = get_memory_hash(debugTaskManagerImpl->mem,0);
+    // debugTaskManagerImpl->statefunc(debugTaskManagerImpl, debugWorker, debugWorker->parent, out, debugWorker->checking);
+
+    char command_arr[NUM_OF_COMMAND][INPUT_BUFFER_SIZE];
+
+    while(1) {
+        printf("\n(Gears Debugger) ");
+        // ユーザーインプット処理
+        int i=0;
+        char user_input[INPUT_BUFFER_SIZE], *command;
+
+        fgets(user_input, sizeof(user_input), stdin);
+        command = strtok(user_input, " \n");
+
+        while (command != NULL) {
+            strcpy(command_arr[i], command);
+            command = strtok(NULL, " \n");
+            i++;
+        }
+        
+        // checking for input
+        for (i = 0; i < NUM_OF_COMMAND; i++) {
+            printf("command_arr[%d] : %s\n", i, command_arr[i]);
+        }
+        
+        // next
+        // nextする前にstateDBへ保存する処理を書きたい
+        if (strcmp(command_arr[0], "next") == 0 || strcmp(command_arr[0], "n") == 0) {
+            dump_memory(debugTaskManagerImpl->mem);
+            // printf(" flag %0x %p -> %p hash %0x \n", out->flag, debugWorker->parent, out, out->hash);
+            goto meta(context, context->next);       
+        // quit
+        } else if (strcmp(command_arr[0], "quit") == 0 || strcmp(command_arr[0], "q") == 0) {
+            printf("quit program\n");
+            exit(0);
+        // help
+        } else if (strcmp(command_arr[0], "help") == 0 || strcmp(command_arr[0], "h") == 0){
+            printf("Debugger commands:\n");
+            printf("next, n:\t Go next step.\n");
+            printf("help, h:\t Show a list of all debugger commands\n");
+            printf("quit, q:\t Quit program.\n");
+            printf("pd:\t\t Show DataGear. Specify the datagear name. ex) pd Phils\n");
+        // pd(print DataGear)
+        } else if (strcmp(command_arr[0], "pd") == 0){
+            goto printDataGear(context, context->next, &command_arr[1]);
+        //others    
+        } else {
+            printf("invalid input. Please enter correct debugger commands.\n");
+        }
+    }
+}
+
+__code getTaskDebugWorker(struct DebugWorker* debugWorker, struct Context* task, struct Worker* worker) {
+    printf("[Debug log] getTaskDebugWorker in DebugWorker\n");
+    if (!task) {
+        printf("debug worker take task finished\n");
+        goto worker->shutdown();
+    }
+    printf("debug worker get task\n");
+    task->worker = worker;
+    enum Code taskCg = task->next;
+    task->next = C_odgCommitDebugWorker; // commit outputDG after task exec
+    goto meta(task, taskCg); // switch task context
+}
+
+__code getTaskDebugWorker_stub(struct Context* context) {
+    DebugWorker* debugWorker = (DebugWorker*)GearImpl(context, Worker, worker);
+    Worker* worker = &Gearef(context,Worker)->worker->Worker;
+    struct Context* task = &Gearef(context, Queue)->data->Context;
+    goto getTaskDebugWorker(context, debugWorker, task, worker);
+}
+
+__code odgCommitDebugWorker(struct DebugWorker* worker, struct Context* task) {
+    printf("[Debug log] odgCommitDebugWorker in DebugWorker\n");
+    if (task->iterate) {
+        struct Iterator* iterator = task->iterator;
+        goto iterator->barrier(task, odgCommitDebugWorker1, odgCommitDebugWorker6);
+    } else {
+        goto odgCommitDebugWorker1();
+    }
+}
+
+__code odgCommitDebugWorker_stub(struct Context* context) {
+    // switch worker context
+    struct Context* workerContext = context->worker->worker->DebugWorker.context;
+    Gearef(workerContext, Worker)->worker = (union Data*)context->worker;
+    Gearef(workerContext, Worker)->task = context;
+    DebugWorker* debugWorker = (DebugWorker*)GearImpl(workerContext, Worker, worker);
+    goto odgCommitDebugWorker(workerContext,
+                            debugWorker,
+                            context);
+}
+
+__code odgCommitDebugWorker1(struct DebugWorker* worker, struct Context* task) {
+    printf("[Debug log] odgCommitDebugWorker1 in DebugWorker\n");
+    int i = worker->loopCounter;
+    if (task->odg+i < task->maxOdg) {
+        goto odgCommitDebugWorker2();
+    }
+    worker->loopCounter = 0;
+    struct TaskManager* taskManager = task->taskManager;
+    goto taskManager->decrementTaskCount(odgCommitDebugWorker6);
+}
+
+__code odgCommitDebugWorker2(struct DebugWorker* worker, struct Context* task) {
+    printf("[Debug log] odgCommitDebugWorker2 in DebugWorker\n");
+    int i = worker->loopCounter;
+    struct Queue* queue = GET_WAIT_LIST(task->data[task->odg+i]);
+    goto queue->isEmpty(odgCommitDebugWorker3, odgCommitDebugWorker5);
+}
+
+__code odgCommitDebugWorker3(struct DebugWorker* worker, struct Context* task) {
+    printf("[Debug log] odgCommitDebugWorker3 in DebugWorker\n");
+    int i = worker->loopCounter;
+    struct Queue* queue = GET_WAIT_LIST(task->data[task->odg+i]);
+    goto queue->take(odgCommitDebugWorker4);
+}
+
+__code odgCommitDebugWorker4(struct DebugWorker* worker, struct Context* task, struct Context* waitTask) {
+    printf("[Debug log] odgCommitDebugWorker4 in DebugWorker\n");
+    if (__sync_fetch_and_sub(&waitTask->idgCount, 1) == 1) { // atomic decrement idg counter(__sync_fetch_and_sub function return initial value of waitTask->idgCount point)
+        struct TaskManager* taskManager = waitTask->taskManager;
+        goto taskManager->spawn(waitTask, odgCommitDebugWorker2);
+    }
+    goto odgCommitDebugWorker2();
+}
+
+__code odgCommitDebugWorker4_stub(struct Context* context) {
+    DebugWorker* debugWorker     = (DebugWorker*)GearImpl(context, Worker, worker);
+    struct Context* task     = Gearef(context, Worker)->task;
+    struct Context* waitTask = &Gearef(context, Queue)->data->Context;
+    goto odgCommitDebugWorker4(context,
+                             debugWorker,
+                             task,
+                             waitTask);
+}
+
+__code odgCommitDebugWorker5(struct DebugWorker* worker, struct Context* task) {
+    printf("[Debug log] odgCommitDebugWorker5 in DebugWorker\n");
+    worker->loopCounter++;
+    goto odgCommitDebugWorker1();
+}
+
+__code odgCommitDebugWorker6(struct DebugWorker* worker, struct Context* task) {
+    printf("[Debug log] odgCommitDebugWorker6 in DebugWorker\n");
+    struct Worker* taskWorker = task->worker;
+    goto taskWorker->taskReceive(taskWorker->tasks);
+}
+
+__code shutdownDebugWorker(struct DebugWorker* worker) {
+    printf("[Debug log] shutdownDebugWorker in DebugWorker\n");
+    goto exit_code();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/DebugWorker.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,23 @@
+// #include "state_db.h"
+// #include "memory.h"
+// #include "TaskIterator.h"
+
+typedef struct DebugWorker <> {
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+  struct Context* context; //simulated task
+  // struct Context* mcContext; // context for mcWorker
+  // struct Context* masterContext; // context for McTaskManager (singleton)
+  struct TaskManager* taskManager;
+  int id;
+  int loopCounter;
+  // struct Queue* mcQueue; // simulated task queue par thread
+  // TaskIterator* task_iter;
+  StateDB parent;
+  // StateDB root;
+  // int depth;
+  int visit;
+  // int count;
+  // int change;    // state db flag is changed
+  int checking;  // state checking phase
+} DebugWorker;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/TaskIterator.c	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include "../context.h"
+#include "TaskIterator.h"
+#include "state_db.h"
+
+TaskIterator* createQueueIterator(Element* elements, StateDB s, TaskIterator* prev) {
+    TaskIterator* new = (TaskIterator*)calloc(1, sizeof(TaskIterator));
+    if (!new) exit(1);
+    new->prev  = prev;
+    new->state = s; //
+    new->list  = elements;
+    return new;
+}
+
+Element* takeNextIterator(TaskIterator* iterator) {
+  struct Element* elem = iterator->list;
+  if (!elem) {
+    return NULL;
+  }
+  struct Element* next = elem->next;
+  if (next == NULL) {
+    return NULL;
+  }
+  iterator->list = next;
+  return next;
+}
+
+int iteratorLength(TaskIterator* iterator) {
+  int i = 0;
+  struct Element* elem = iterator->list;
+  for(; elem; elem = elem->next) i++;
+  return i;
+}
+
+void freeIterator(TaskIterator* iterator) {
+  free(iterator);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/TaskIterator.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,8 @@
+#ifndef TASKITERATOR
+typedef struct TaskIterator {
+    struct TaskIterator* prev;
+    StateDB state;
+    struct Element* list;
+} TaskIterator;
+#define TASKITERATOR
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/crc32.c	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,78 @@
+/*
+    $Id: crc32.c,v 1.1.1.1 2007/03/06 06:34:39 atsuki Exp $
+    Shinji KONO <kono@ie.u-ryukyu.ac.jp>
+       based on open source CRCtextDlg.cpp Richard A. Ellingson
+
+    This is generated by Perl, do not edit this. Edit Perl script.
+ */
+
+static unsigned crc32_table[256] = {
+	0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,
+	0x1a864db2,0x1e475005,0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,
+	0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,0x4c11db70,0x48d0c6c7,
+	0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
+	0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,
+	0x709f7b7a,0x745e66cd,0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,
+	0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,0xbe2b5b58,0xbaea46ef,
+	0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
+	0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,
+	0xceb42022,0xca753d95,0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,
+	0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,0x34867077,0x30476dc0,
+	0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
+	0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,
+	0x0808d07d,0x0cc9cdca,0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,
+	0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,0x5e9f46bf,0x5a5e5b08,
+	0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
+	0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,
+	0xb6238b25,0xb2e29692,0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,
+	0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,0xe0b41de7,0xe4750050,
+	0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
+	0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,
+	0xdc3abded,0xd8fba05a,0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,
+	0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,0x4f040d56,0x4bc510e1,
+	0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
+	0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,
+	0x3f9b762c,0x3b5a6b9b,0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,
+	0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,0xf12f560e,0xf5ee4bb9,
+	0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
+	0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,
+	0xcda1f604,0xc960ebb3,0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,
+	0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,0x9b3660c6,0x9ff77d71,
+	0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
+	0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,
+	0x470cdd2b,0x43cdc09c,0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,
+	0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,0x119b4be9,0x155a565e,
+	0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
+	0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,
+	0x2d15ebe3,0x29d4f654,0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,
+	0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,0xe3a1cbc1,0xe760d676,
+	0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
+	0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,
+	0x933eb0bb,0x97ffad0c,0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,
+	0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4
+};
+
+
+
+// Once the lookup table has been filled in by the two functions above,
+// this function creates all CRCs using only the lookup table.
+
+// Be sure to use unsigned variables,
+// because negative values introduce high bits
+// where zero bits are required.
+// Start out with all bits set high.
+
+unsigned Get_CRC(unsigned char *buffer,int len,unsigned ulCRC)
+{
+    // Perform the algorithm on each character
+    // in the string, using the lookup table values.
+
+    while(len-->0) {
+      ulCRC = (ulCRC >> 8) ^ crc32_table[(ulCRC & 0xFF) ^ *buffer++];
+    }
+    // Exclusive OR the result with the beginning value.
+    return ulCRC ^ 0xffffffff;
+}
+
+// ******* End custom code *******
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/crc32.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,8 @@
+/*
+    $Id: crc32.h,v 1.1.1.1 2007/03/06 06:34:39 atsuki Exp $
+    Shinji KONO <kono@ie.u-ryukyu.ac.jp>
+       based on open source
+ */
+
+extern  unsigned Get_CRC(unsigned char *buffer,int len, unsigned ulCRC);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/memory.c	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,379 @@
+/*
+
+    memory fragment management library
+
+    Shinji Kono (2006)
+
+    usage:
+
+    MemoryPtr db = 0;
+    add_memory(address,length,&db);
+
+	memory pattern is copyied and stored in a binary tree in db.
+	All patterns are shared.
+
+    memory pattern database (binary tree by pattern)
+
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "memory.h"
+#include "crc32.h"
+#include <string.h>
+
+#define MEMORY_REPORT 1
+
+#if MEMORY_REPORT
+int    memory_header;
+int    memcmp_count;
+int    memory_body;
+int    restore_count;
+int    restore_size;
+int    range_count;
+int    range_size;
+#endif
+
+extern void die_exit(char *);
+
+void
+die_exit(char *msg)
+{
+    fprintf(stderr,"%s\n",msg);
+    exit(1);
+}
+
+// static MemoryPtr memory_root;
+
+
+/*
+
+    make memory fragment as a part of the program state
+
+ */
+
+MemoryPtr
+create_memory(void *adr, int length)
+{
+    MemoryPtr m = (MemoryPtr)malloc(sizeof(Memory));
+    if (!m) die_exit("Cann't alloc memory list.");
+    m->left = m->right = 0;
+    m->length = length;
+    m->adr = m->body = adr;
+#if MEMORY_REPORT
+    memory_header++;
+#endif
+    return m;
+}
+
+/*
+
+    Compute hash value of a memory fragment
+
+ */
+
+unsigned
+compute_memory_hash1(MemoryPtr m,unsigned hash)
+{
+    return Get_CRC((unsigned char *)m->adr,m->length, hash);
+}
+
+void
+free_memory(MemoryPtr m)
+{
+    m->left = m->right = 0;
+    m->adr = m->body = 0;
+    free(m);
+}
+
+/*
+
+   Compare memory contents ( doesn't care about its address )
+
+ */
+
+int
+cmp_content(MemoryPtr a,MemoryPtr b)
+{
+    if (a->length != b->length) {
+      if (a->length > b->length) {
+        return 1;
+      } else {
+        return -1;
+      }
+    }
+    if (a->hash == b->hash) {
+#if MEMORY_REPORT
+      memcmp_count ++;
+#endif
+      return memcmp(a->body,b->body,a->length);
+    } else if (a->hash > b->hash) {
+        return 1;
+    } else {
+        return -1;
+    }
+}
+
+/*
+
+   Compare entire memory contents ( doesn't care about its address )
+
+ */
+
+static int
+cmp_memory1(MemoryPtr a,MemoryPtr b)
+{
+    int r;
+    if ((r=cmp_content(a,b))) return r;
+
+    if (a->adr==b->adr) {
+      return 0;
+    }
+    return (a->adr > b->adr) ? 1 : -1;
+}
+
+int
+cmp_memory(MemoryPtr a,MemoryPtr b)
+{
+    int r;
+    while(1) {
+      if ((r=cmp_memory1(a,b))) return r;
+      if (a->left && b->left) {
+          if ((r=cmp_memory(a->left,b->left))) return r;
+      } else if (a->left || b->left) {
+          return (a->left > b->left)? 1 : -1;
+      }
+      if (a->right && b->right) {
+          a = a->right; b = b->right;
+          // recursive loop
+      } else if (a->right || b->right) {
+          return (a->right > b->right)? 1 : -1;
+      } else {
+          return 0;  // singleton
+      }
+    }
+}
+
+/*
+    Make a copy of real memory fragments
+ */
+
+MemoryPtr
+copy_memory1(MemoryPtr m)
+{
+    MemoryPtr new = create_memory(m->adr,m->length);
+    void *p = (void *)malloc(m->length);
+    if (!p) {
+      die_exit("can't alloc memory body");
+      return 0;
+    }
+#if MEMORY_REPORT
+    memory_body += m->length;
+#endif
+    memcpy(p,m->adr,m->length);
+    m->body = new->body = p;     // abondon original memory pattern
+    new->hash = m->hash;
+    return new;
+}
+
+MemoryPtr
+copy_memory(MemoryPtr m, MemoryPtr *db)
+{
+    MemoryPtr new, out;
+    if (!m) return m;
+    new = create_memory(m->adr,m->length);
+    new->hash = m->hash;
+    // look up is necessary to share its memory pattern
+    memory_lookup(new, db, copy_memory1, &out);
+    if (m->left)  new->left = copy_memory(m->left, db);
+    if (m->right) new->right = copy_memory(m->right, db);
+    return new;
+}
+
+/*
+    restore copied memory save to the original addresses
+ */
+
+void
+restore_memory(MemoryPtr m)
+{
+    while (m) {
+      memcpy(m->adr,m->body,m->length);
+#if MEMORY_REPORT
+      restore_count ++;
+      restore_size += m->length;
+#endif
+      if (m->left)  restore_memory(m->left);
+      m = m->right;
+    }
+}
+
+
+/*
+    get hash for all memeory fragments
+	initial value of hash should be zero
+ */
+
+unsigned
+get_memory_hash(MemoryPtr m, unsigned hash)
+{
+    if (!m) return hash;
+    if (m->left)  hash = get_memory_hash(m->left, hash);
+    m->hash = compute_memory_hash1(m, 0xffffffff);        // for each memory segment
+    hash =  Get_CRC((unsigned char *)&m->hash,sizeof(m->hash), hash);  // for entire chain
+    if (m->right) hash = get_memory_hash(m->right, hash);
+    return hash;
+}
+
+/*
+    add modified memory fragments to the pattern database
+ */
+
+MemoryPtr
+add_memory(void *ptr,int length, MemoryPtr *parent)
+{
+    Memory m, *out;
+    m.adr = m.body = ptr;
+    m.length = length;
+    m.left = m.right = 0;
+    m.hash = compute_memory_hash1(&m, 0xffffffff);
+    memory_lookup(&m, parent, copy_memory1, &out);
+    return out;
+}
+
+int
+memory_lookup(MemoryPtr m, MemoryPtr *parent,
+		    MemoryPtr (*new_memory)(MemoryPtr), MemoryPtr *out)
+{
+    MemoryPtr db;
+    int r;
+
+    while(1) {
+        db = *parent;
+        if (!db) {
+	    /* not found */
+          if (new_memory && out) {
+              db = new_memory(m);
+              db->left = db->right = 0;
+              *out = *parent = db;
+          }
+          return 0;
+        }
+        if(!(r = cmp_memory1(m,db))) {
+            /* bingo */
+          if (out) {
+            *out = db;
+          }
+          return 1;
+        } else if (r>0) {
+            parent = &db->left;
+        } else if (r<0) {
+            parent = &db->right;
+        }
+    }
+    /* !NOT REACHED */
+}
+
+/*
+    memory range list management for state registration
+	this list points the real memory
+ */
+
+MemoryPtr
+add_memory_range(void *ptr,int length, MemoryPtr *parent)
+{
+    Memory m, *out;
+    m.adr = ptr;
+    m.length = length;
+    m.left = m.right = 0;
+
+    memory_range_lookup(&m, parent, &out);
+    return out;
+}
+
+static int
+cmp_range(MemoryPtr a,MemoryPtr b)
+{
+    if (a->adr==b->adr) {
+      if (a->length != b->length)
+        die_exit("memory range inconsitency");
+      return 0;
+    }
+    return (a->adr > b->adr) ? 1 : -1;
+}
+
+int
+memory_range_lookup(MemoryPtr m, MemoryPtr *parent, MemoryPtr *out)
+{
+    MemoryPtr db;
+    int r;
+
+    while(1) {
+        db = *parent;
+        if (!db) {
+	    /* not found */
+          if (out) {
+            db = create_memory(m->adr, m->length);
+            *out = *parent = db;
+          }
+#if MEMORY_REPORT
+        range_count++;
+        range_size+=m->length;
+#endif
+        return 0;
+      }
+      if(!(r = cmp_range(m,db))) {
+            /* bingo (actually an error) */
+        if (out) {
+          *out = db;
+        }
+        return 1;
+      } else if (r>0) {
+        parent = &db->left;
+      } else if (r<0) {
+            parent = &db->right;
+      }
+  }
+    /* !NOT REACHED */
+}
+
+/*
+    dump memory
+ */
+
+void
+dump_memory(MemoryPtr m)
+{
+    while (m) {
+      // printf("\n%p : ",m->adr);
+      unsigned char *p = (unsigned char *)m->adr;
+      for(int i=0; i<m->length ;i++) {
+          printf("%02x",p[i]);
+          if ((i+1)%4==0) putchar(' ');
+      }
+      if (m->left)  dump_memory(m->left);
+      m = m->right;
+    }
+}
+
+
+/*
+ */
+
+void
+memory_usage()
+{
+#if MEMORY_REPORT
+    printf("	memory_header %d\n",memory_header);
+    printf("	memcmp_count %d\n",memcmp_count);
+    printf("	memory_body %d\n",memory_body);
+    printf("	restore_count %d\n",restore_count);
+    printf("	restore_size %d\n",restore_size);
+    printf("	range_count %d\n",range_count);
+    printf("	range_size %d\n",range_size);
+#endif
+}
+
+
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/memory.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,60 @@
+#ifndef _MEMORY_H_
+#define _MEMORY_H_
+
+
+typedef struct memory {
+	void *adr;
+	int  length;
+	void *body;
+	int  hash;
+	struct memory *left,*right;
+} Memory, *MemoryPtr;
+
+extern void die_exit(char *);
+
+extern MemoryPtr
+create_memory(void *adr, int length);
+
+extern unsigned
+compute_memory_hash1(MemoryPtr m, unsigned hash);
+
+extern void
+free_memory(MemoryPtr m);
+
+extern int
+cmp_content(MemoryPtr a,MemoryPtr b);
+
+extern int
+cmp_memory(MemoryPtr a,MemoryPtr b);
+
+extern MemoryPtr 
+copy_memory(MemoryPtr m, MemoryPtr *db);
+
+extern void
+restore_memory(MemoryPtr m) ;
+
+extern unsigned 
+get_memory_hash(MemoryPtr m,unsigned  hash);
+
+MemoryPtr
+add_memory(void *ptr,int length, MemoryPtr *parent);
+
+extern int
+memory_lookup(MemoryPtr m, MemoryPtr *parent,
+                    MemoryPtr (*new_memory)(MemoryPtr), MemoryPtr *out);
+
+extern MemoryPtr
+add_memory_range(void *ptr,int length, MemoryPtr *parent);
+
+extern int
+memory_range_lookup(MemoryPtr m, MemoryPtr *parent, MemoryPtr *out);
+
+extern void
+memory_usage();
+
+extern void
+dump_memory(MemoryPtr m);
+
+
+#endif
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/state_db.c	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,94 @@
+#include <stdlib.h>
+
+#include "state_db.h"
+#include "memory.h"
+
+StateDB
+create_stateDB()
+{
+    StateDB s = (StateDB)malloc(sizeof(StateNode));
+    if (!s) die_exit("Cann't alloc state db node.");
+    return s;
+}
+
+static MemoryPtr mem_db;
+
+static int state_count0;
+
+void
+reset_state_count()
+{
+    state_count0 = 0;
+}
+
+int
+state_count()
+{
+    return state_count0;
+}
+
+
+/*
+
+    lookup_StateDB(struct state *s, StateDB *parent, StatePtr *out)
+
+    s->memory points the real memory
+    if s is new, it is copied in the database (parent).
+    if s is in the database, existing state is returned.
+
+    if return value is 0, it returns new state.
+    if out is null, no copy_state is created. (lookup mode)
+
+    Founded state or newly created state is returned in out.
+    
+ */
+
+int
+lookup_StateDB(StateDB s, StateDB *parent, StateDB *out)
+{
+    StateDB db;
+    int r;
+    
+    while(1) {
+      db = *parent;
+      if (!db) {
+	    /* not found */
+        if (out) {
+          db = create_stateDB();
+          db->left = db->right = 0;
+          db->memory = copy_memory(s->memory,&mem_db);
+          db->hash = s->hash;
+          state_count0 ++;
+          *parent = db;
+          *out = db;
+        }
+        return 0;
+      }
+      if (s->hash == db->hash) {
+          r =  cmp_memory(s->memory,db->memory);
+      } else
+          r =  (s->hash > db->hash)? 1 : -1;
+      if(!r) {
+          /* bingo */
+          if (out) *out = db;
+          return 1;
+      } else if (r>0) {
+          parent = &db->left;
+      } else if (r<0) {
+          parent = &db->right;
+      }
+    }
+}
+
+int
+visit_StateDB(StateDB s, StateDB *parent, StateDB* out, int visit)
+{
+  int exists = lookup_StateDB(s,parent,out);
+  if (!exists) return 0;
+  if ((*out)->visit >= visit) {
+    return 1;
+  }
+  (*out)->visit = visit;
+  return 0;
+ }
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/DebugWorker/state_db.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,21 @@
+#ifndef _STATE_DB_H_
+#define _STATE_DB_H_
+
+typedef struct state_db {
+    struct memory *memory;
+    unsigned hash;
+    int visit; // visiting count for repeating search
+    int flag;  // CTL state
+    struct state_db *left;
+    struct state_db *right;
+} StateNode, *StateDB;
+
+extern int
+lookup_StateDB(StateDB s, StateDB *db, StateDB *out);
+
+extern int state_count();
+extern void reset_state_count();
+
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/examples/DebughelloWorld/Hello.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,7 @@
+typedef struct Hello <> {
+  union Data* hello;
+  char* string;
+  __code h(Impl* hello, __code next(...));
+  __code w(Impl* hello, __code next(...));
+  __code next(...);
+} Hello;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/examples/DebughelloWorld/HelloImpl.cbc	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,42 @@
+#include "../../../context.h"
+#include <stdio.h>
+#impl "Hello.h" as "HelloImpl.h"
+#interface "Hello.h"
+#interface "Worker.h"
+#interface "TaskManager.h"
+
+extern __code debugMeta(struct Context*, enum Code);
+
+// ----
+// typedef struct HelloImpl <> impl Hello {
+//   char* hString;
+//   char* wString;
+// } HelloImpl;
+// ----
+
+Hello* createHelloImpl(struct Context* context) {
+    printf("[Debug log] createHelloImpl in HelloImpl\n");
+    struct Hello* hello  = new Hello();
+    struct HelloImpl* hello_impl = new HelloImpl();
+    hello->hello = (union Data*)hello_impl;
+    hello->string = NULL;
+    hello_impl->hString = NULL;
+    hello_impl->wString = NULL;
+    hello->h = C_hHelloImpl;
+    hello->w = C_wHelloImpl;
+    return hello;
+}
+__code h(struct HelloImpl* hello, __code next(...)) {
+    printf("[Debug log] h in HelloImpl\n");
+    hello->hString = "Hello, "; //createImpl部分では_implなのだが動く
+    printf("%s", hello->hString);
+    goto w(hello, next);
+}
+
+__code w(struct HelloImpl* hello, __code next(...)) {
+    printf("[Debug log] w in HelloImpl\n");
+    hello->wString = "World.\n";
+    printf("%s", hello->wString);
+    goto next(...);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/examples/DebughelloWorld/HelloImpl.h	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,4 @@
+typedef struct HelloImpl <> impl Hello {
+  char* hString;
+  char* wString;
+} HelloImpl;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/examples/DebughelloWorld/main.cbc	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#include "../../../context.h"
+#interface "TaskManager.h"
+#interface "Hello.h"
+
+int cpu_num = 1;
+int length = 102400;
+int split = 8;
+int* array_ptr;
+int gpu_num = 0;
+int CPU_ANY = -1;
+int CPU_CUDA = -1;
+
+__code initDataGears(struct LoopCounter* loopCounter, struct TaskManager* taskManager) {
+    printf("[Debug log] initDataGears in main\n");
+    // loopCounter->tree = createRedBlackTree(context);
+    loopCounter->i = 0;
+    taskManager->taskManager = (union Data*)createDebugTaskManagerImpl(context, cpu_num, gpu_num, 0);
+    goto code1();
+}
+
+__code code1(struct LoopCounter* loopCounter) {
+    printf("[Debug log] code1 in main\n");
+    printf("cpus:\t\t%d\n", cpu_num);
+    printf("gpus:\t\t%d\n", gpu_num);
+    printf("length:\t\t%d\n", length);
+    printf("length/task:\t%d\n", length/split);
+    goto createTask1();
+}
+
+
+__code createTask1(struct LoopCounter* loopCounter, struct TaskManager* taskManager) {
+    printf("[Debug log] createTask1 in main\n");
+    Hello* hello = createHelloImpl(context);
+    goto hello->h(code2); 
+}
+
+
+__code code2(struct TaskManager* taskManager) {
+    printf("[Debug log] code2 in main\n");
+    goto taskManager->shutdown(exit_code);
+}
+
+__code code2_stub(struct Context* context) {
+    goto code2(context, &Gearef(context, TaskManager)->taskManager->TaskManager);
+}
+
+void init(int argc, char** argv) {
+    printf("[Debug log] init in main\n");
+    for (int i = 1; argv[i]; ++i) {
+        if (strcmp(argv[i], "-cpu") == 0)
+            cpu_num = (int)atoi(argv[i+1]);
+        else if (strcmp(argv[i], "-l") == 0)
+            length = (int)atoi(argv[i+1]);
+        else if (strcmp(argv[i], "-s") == 0)
+            split = (int)atoi(argv[i+1]);
+        else if (strcmp(argv[i], "-cuda") == 0) {
+            gpu_num = 1;
+            CPU_CUDA = 0;
+        }
+    }
+}
+
+int main(int argc, char** argv) {
+    printf("[Debug log] main in main\n");
+    init(argc, argv);
+    goto initDataGears();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/examples/DebughelloWorld/meta.pm	Tue Jan 18 19:54:28 2022 +0900
@@ -0,0 +1,17 @@
+package meta;
+use strict;
+use warnings;
+
+sub replaceMeta {
+  return (
+    [qr/HelloImpl/ => \&generatedebugMeta],
+  );
+}
+
+#my ($currentCodeGearName, $context, $next) = @_;
+
+sub generatedebugMeta {
+  my ($context, $next) = @_;
+  return "goto debugMeta($context, $next);";
+}
+1;