Skip to main content

Source code file content

Revision: aa955f6dbe228289c7fa608a5bf1a18b0d5cc674

copyright FIT added
» Project Revision History

» Checkout URL

main / threadRelationControl.c

Size: 7745 bytes, 1 line
/*
 *
 * (c) Filip Voracek, FIT CTU in Prague, 2012
 */

#include "threadRelationControl.h"

#define START_MAX_THREADS 5

static int ** vectorClocks;
static jlong * threadTags;
static int max_threads = START_MAX_THREADS;
static int numberOfThreads = 0;

static bool mainThreadSet = false; // used for main thread

/**
 * Write given message as error and abort
 */
static void processImpossibleState(char * errorMsg) {
    error("getCurrentThreadState", errorMsg);
    abort();
}

/**
 * Resize all structures if needed
 */
static void resizeIfNeeded() {
    if (numberOfThreads > max_threads) { // theoretically cannot happen, just for sure
        processImpossibleState("Impossible state: numberOfThreads > max_threads");
    }

    if (numberOfThreads == max_threads) {
        debug("resizeIfNeeded", "resizing all thread relation structures");
        max_threads *= 2;

        // thread tags
        jlong * newThreadTags = (jlong*) calloc(max_threads, sizeof (jlong));
        int i;
        for (i = 0; i < numberOfThreads; i++) {
            newThreadTags[i] = threadTags[i];
        }

        free(threadTags);
        threadTags = newThreadTags;

        // vector clocks
        int ** newVectorClocks = (int**) calloc(max_threads, sizeof (int*));
        int * newVectorClock;
        int j;
        for (i = 0; i < numberOfThreads; i++) {
            newVectorClock = (int*) calloc(max_threads, sizeof (int));
            for (j = 0; j < numberOfThreads; j++) {
                newVectorClock[j] = vectorClocks[i][j];
            }
            for (j = numberOfThreads; j < max_threads; j++) {
                newVectorClock[j] = 0;
            }
            newVectorClocks[i] = newVectorClock;
        }
        for (i = numberOfThreads; i < max_threads; i++) {
            newVectorClocks[i] = (int*) calloc(max_threads, sizeof (int));
            for (j = 0; j < max_threads; j++) {
                newVectorClocks[i][j] = 0;
            }
        }

        for (i = 0; i < numberOfThreads; i++) {
            free(vectorClocks[i]);
        }
        free(vectorClocks);

        vectorClocks = newVectorClocks;
    }
}

static int getIndexOfThreadTag(jlong threadTag) {
    trace("getIndexOfThreadTag", "getting index of thread");
    int i;
    for (i = 0; i < numberOfThreads; i++) {
        if (threadTags[i] == threadTag) {
            return i;
        }
    }

    debug("getIndexOfThreadTag", "index of thread tag does not exist yet");
    return -1;
}

int getCurrentThreadState(jlong threadTag) {
    int index = getIndexOfThreadTag(threadTag);

    if (index == -1) { // only if -watchThreads is off
        return -1;
    }

    int currentState = vectorClocks[index][index];

    debug("getCurrentThreadState", "current state = %d, for threadTag = %ld, of index = %d",
            currentState, (long) threadTag, index);

    return currentState;
}

static int max(int a, int b) {
    return a > b ? a : b;
}

static void addNewThreadsIfNeeded(jlong threadTag1, jlong threadTag2) {
    if (getIndexOfThreadTag(threadTag1) == -1) {
        resizeIfNeeded();
        threadTags[numberOfThreads] = threadTag1;
        numberOfThreads++;
    }

    if (getIndexOfThreadTag(threadTag2) == -1) {
        resizeIfNeeded();
        threadTags[numberOfThreads] = threadTag2;
        numberOfThreads++;
    }
}

static void addRelationInner(jlong threadSourceTag, jlong threadCalledTag) {
    // adding new thread if needed
    addNewThreadsIfNeeded(threadSourceTag, threadCalledTag);

    // adding relations itself
    int sourceIndex = getIndexOfThreadTag(threadSourceTag);
    int calledIndex = getIndexOfThreadTag(threadCalledTag);

    int* sourceVectorClock = vectorClocks[sourceIndex];
    int* calledVectorClock = vectorClocks[calledIndex];

    sourceVectorClock[sourceIndex]++;

    // vector merging
    int i;
    for (i = 0; i < numberOfThreads; i++) {
        calledVectorClock[i] = max(calledVectorClock[i], sourceVectorClock[i]);
    }

    // time increasing

    calledVectorClock[calledIndex]++;

    // debugging
    debug("addRelationInner", "add relation to nodes: %ld, %ld", (long) threadSourceTag,
            (long) threadCalledTag);
}

static void debugVectorClocksIfDebug() {
    debug("debugVectorClocksIfDebug", "writing vector clocks");
    debugTable(vectorClocks, numberOfThreads);
}

void addRelation(jlong threadSourceTag, jlong threadCalledTag, ThreadRelationType relationType) {
    if (relationType == START) {
        addRelationInner(threadSourceTag, threadCalledTag);
        info("addRelation", "START relation added");
    } else if (relationType == JOIN) {
        addRelationInner(threadCalledTag, threadSourceTag);
        info("addRelation", "JOIN relation added");
    } else {
        processImpossibleState("Impossible state in switch, aborting..");
    }

    debugVectorClocksIfDebug();
}

bool hasRelation(jlong origTag, int origState, jlong currentTag) {
    trace("hasRelation", "in method hasRelation");
    debugVectorClocksIfDebug();

    int origIndex = getIndexOfThreadTag(origTag);
    int currentIndex = getIndexOfThreadTag(currentTag);

    if (origIndex == -1) { // finalizer
        return false;
    }
    if (currentIndex == -1) { // finalizer
        return true;
    }

    bool relation = (vectorClocks[currentIndex][origIndex] > origState) ? true : false;

    if (isDebug()) {
        debug("hasRelation", "origTag %ld of index %d, currentTag %ld of index %d, origState = %d, relation is %d",
                (long) origTag, origIndex, (long) currentTag, currentIndex, origState, relation);
    }

    return relation;
}

/*
bool hasRelation(jlong origTag, int origState, jlong currentTag) {
    trace("hasRelation", "in method hasRelation");
    debugVectorClocksIfDebug();

    int origIndex = getIndexOfThreadTag(origTag);
    int currentIndex = getIndexOfThreadTag(currentTag);

    bool relation;
    if (vectorClocks[currentIndex][origIndex] >= origState) {
        relation = true;
    } else {
        relation = false;
    }

    debug("hasRelation", "origTag %ld of index %d, currentTag %ld of index %d, origState = %d, relation is %d",
            (long) origTag, origIndex, (long) currentTag, currentIndex, origState, relation);

    return relation;
}
 */

void freeThreadRelationControl(void) {
    int i;
    for (i = 0; i < max_threads; i++) {
        free(vectorClocks[i]);
    }
    free(vectorClocks);
    free(threadTags);

    info("freeThreadRelationControl", "thread relation control freed");
}

void initMainThread(jlong mainThreadTag) {
    if (!mainThreadSet) {
        threadTags[0] = mainThreadTag;
        vectorClocks[0][0] = 0;
        numberOfThreads = 1;
        mainThreadSet = true;
        info("initMainThread", "Main thread initialized in thread relation control");
        debugVectorClocksIfDebug();
    } else {
        processImpossibleState("Main thread initialization can be called only once, aborting..");
    }
}

static void initVectorClocks() {
    vectorClocks = (int**) calloc(max_threads, sizeof (int*));
    int i;
    int j;
    for (i = 0; i < max_threads; i++) {
        vectorClocks[i] = (int*) calloc(max_threads, sizeof (int));
        for (j = 0; j < max_threads; j++) {
            vectorClocks[i][j] = 0;
        }
    }
}

void initThreadRelationControl(void) {
    threadTags = (jlong*) calloc(max_threads, sizeof (jlong));
    initVectorClocks();

    info("initThreadRelationControl", "thread relation control initialized");
}
 
 
Close
loading
Please Confirm
Close