view src/parallel_execution/DebugWorker/DebugWorker.cbc @ 1016:3e8d89f271e2 debugger

debugger branch
author Takato Matsuoka <t.matsuoka@cr.ie.u-ryukyu.ac.jp>
date Wed, 19 Jan 2022 17:51:07 +0900
parents e6778c866876
children a747a99ae1f2
line wrap: on
line source

#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"
#interface "SingleLinkedQueue.h"

static void startWorker(Worker* worker);

static int dump = 1;

#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);

    // context->worker = 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;

    // init state DB
    struct DebugTaskManagerImpl* debugTaskManagerImpl = (struct DebugTaskManagerImpl *)debugWorker->taskManager->taskManager;
    StateNode st ;
    StateDB out = &st;
    out->memory = debugTaskManagerImpl->mem;
    out->hash = get_memory_hash(debugTaskManagerImpl->mem,0);    
    lookup_StateDB(out, &debugTaskManagerImpl->state_db, &out);
    if (dump) {
        dump_memory(debugTaskManagerImpl->mem);
        printf(" flag %0x %p -> %p hash %0x \n", out->flag, debugWorker->parent, out, out->hash);
    }

    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 printTrace(struct Context* context, enum Code next) {
    printf("[Debug log] print trace\n");

    context->next = next; // remember next Code
    
    // TODO: stateDBに保存したメモリ状態をトレースとして表示させる
    struct DebugWorker* debugWorker = (struct DebugWorker*) context->worker->worker;
    struct DebugTaskManagerImpl* debugTaskManagerImpl = (struct DebugTaskManagerImpl *)debugWorker->taskManager->taskManager;

    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
	struct DebugWorker* debugWorker = (struct DebugWorker*) context->worker->worker;
	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);
    int found = visit_StateDB(out, &debugTaskManagerImpl->state_db, &out,debugWorker->visit);
    // 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) {
            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]);
        } else if (strcmp(command_arr[0], "pt") == 0){
            goto printTrace(context, context->next);
        } else if (strcmp(command_arr[0], "dump") == 0){
            dump_memory(debugTaskManagerImpl->mem);
        //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();
}