view src/parallel_execution/LockImpl.cbc @ 506:04441dd783c5

Add LockImpl
author Tatsuki IHA <innparusu@cr.ie.u-ryukyu.ac.jp>
date Tue, 02 Jan 2018 06:16:40 +0900
parents
children a7127917c736
line wrap: on
line source

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

Lock* createLockImpl(struct Context* context) {
    struct Lock* lock = new Lock();
    struct LockImpl* lockImpl = new LockImpl();
    lockImpl->lock = NULL;
    lockImpl->waitThreadList = createSynchornizedQueue(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(&lockImpl->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->waitThreadList;
    context->next= C_doLockLockImpl;
    goto queue->put(context, doLockLockImpl3);
}

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

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

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

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

__code doUnlockLockImpl2(struct LockImpl* lock, __code next(...)) {
    struct Queue* queue = lock->waitThreadQueue;
    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);
}