view src/parallel_execution/LockImpl.cbc @ 549:05fd14d8edbe

add update_context.pl
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Wed, 13 Nov 2019 16:04:34 +0900
parents a7127917c736
children
line wrap: on
line source

#include "../context.h"
#interface "Queue.h"
#interface "Atomic.h"
#interface "Lock.h"
#interface "Worker.h"
#interface "TaskManager.h"

Lock* createLockImpl(struct Context* context) {
    struct Lock* lock = new Lock();
    struct LockImpl* lockImpl = new LockImpl();
    lockImpl->lock = NULL;
    lockImpl->waitThreadQueue = createSynchronizedQueue(context);
    lockImpl->atomic = createAtomicReference(context);
    lock->lock = (union Data*)lockImpl;
    lock->doLock = C_doLockLockImpl;
    lock->doUnlock = C_doUnlockLockImpl;
    return lock;
}

__code doLockLockImpl(struct LockImpl* lock, __code next(...)) {
    struct Atomic* atomic = lock->atomic;
    goto atomic->checkAndSet(&lock->lock, NULL, 1, doLockLockImpl1, doLockLockImpl2);
}

__code doLockLockImpl1(struct LockImpl* lock, __code next(...)) {
    lock->lockContext = context;
    goto next(...);
}

__code doLockLockImpl2(struct LockImpl* lock, __code next(...)) {
    struct Queue* queue = lock->waitThreadQueue;
    context->next= C_doLockLockImpl;
    printf("Put task\n");
    goto queue->put(context, doLockLockImpl3);
}

__code doLockLockImpl3(struct LockImpl* lock, struct Worker* worker, __code next(...)) {
    goto worker->taskReceive(); // goto shceduler
}

__code doLockLockImpl3_stub(struct Context* context) {
    // switch worker context
    struct Context* workerContext = context->worker->worker->CPUWorker.context;
    LockImpl* lockImpl = (LockImpl*)GearImpl(context, Lock, lock);
    goto doLockLockImpl3(workerContext,
            lockImpl,
            context->worker,
            Gearef(context, Lock)->next);
}

__code doUnlockLockImpl(struct LockImpl* lock, __code next(...)) {
    if (lock->lockContext == context) {
        struct Atomic* atomic = lock->atomic;
        goto atomic->checkAndSet(&lock->lock, 1, NULL, doUnlockLockImpl1, doUnlockLockImpl);
    }
    goto next(...);
}

__code doUnlockLockImpl1(struct LockImpl* lock, __code next(...)) {
    struct Queue* queue = lock->waitThreadQueue;
    goto queue->isEmpty(doUnlockLockImpl2, doUnlockLockImpl4);
}

__code doUnlockLockImpl2(struct LockImpl* lock, __code next(...)) {
    struct Queue* queue = lock->waitThreadQueue;
    printf("%p: Take task\n", lock);
    goto queue->take(doUnlockLockImpl3);
}

__code doUnlockLockImpl3(struct LockImpl* lock, struct Context* waitTask, __code next(...)) {
    struct TaskManager* taskManager = waitTask->taskManager;
    goto taskManager->spawn(waitTask, next(...)); //notify
}

__code doUnlockLockImpl3_stub(struct Context* context) {
    LockImpl* lockImpl = (LockImpl*)GearImpl(context, Lock, lock);
    struct Context* waitTask = &Gearef(context, Queue)->data->Context;
    goto doUnlockLockImpl3(context,
            lockImpl,
            waitTask,
            Gearef(context, Lock)->next);
}

__code doUnlockLockImpl4(struct LockImpl* lock, __code next(...)) {
    goto next(...);
}