view src/context.h @ 41:087d7b61c86b

cbc cmake version
author kono
date Sat, 02 Mar 2019 19:01:03 +0900
parents
children 233a68a261fe
line wrap: on
line source

/* Context definition for llrb example */
#ifndef CONTEXT_H
#define CONTEXT_H
#include <stdlib.h>
#include <pthread.h>
#ifdef USE_CUDAWorker
#include <cuda.h>
#include <driver_types.h>
#include <cuda_runtime.h>
#include "helper_cuda.h"
#endif

#define ALLOCATE_SIZE 20000000
#define NEW(type) (type*)(calloc(1, sizeof(type)))
#define NEWN(n, type) (type*)(calloc(n, sizeof(type)))

#define ALLOC_DATA(context, dseg) ({\
    Meta* meta = (Meta*)context->heap;\
    meta->type = D_##dseg;\
    meta->size = sizeof(dseg);\
    meta->len = 1;\
    context->heap += sizeof(Meta);\
    context->data[D_##dseg] = context->heap; context->heap += sizeof(dseg); (dseg *)context->data[D_##dseg]; })

#define ALLOC_DATA_TYPE(context, dseg, t) ({\
    Meta* meta = (Meta*)context->heap;\
    meta->type = D_##t;\
    meta->size = sizeof(t);\
    meta->len = 1;\
    context->heap += sizeof(Meta);\
    context->data[D_##dseg] = context->heap; context->heap += sizeof(t); (t *)context->data[D_##dseg]; })

#define ALLOCATE(context, t) ({ \
    Meta* meta = (Meta*)context->heap;\
    context->heap += sizeof(Meta);\
    union Data* data = context->heap; \
    context->heap += sizeof(t); \
    meta->type = D_##t; \
    meta->size = sizeof(t);     \
    meta->len = 1;\
    data; })

#define ALLOCATE_ARRAY(context, t, length) ({ \
    Meta* meta = (Meta*)context->heap;\
    context->heap += sizeof(Meta);\
    union Data* data = context->heap; \
    context->heap += sizeof(t)*length; \
    meta->type = D_##t; \
    meta->size = sizeof(t)*length; \
    meta->len = length; \
    data;   })

#define ALLOCATE_PTR_ARRAY(context, dseg, length) ({\
    Meta* meta = (Meta*)context->heap;\
    context->heap += sizeof(Meta);\
    union Data* data = context->heap; \
    context->heap += sizeof(dseg *)*length; \
    meta->type = D_##dseg; \
    meta->size = sizeof(dseg *)*length; \
    meta->len = length; \
    data; })

#define ALLOCATE_DATA_GEAR(context, t) ({ \
        union Data* data = ALLOCATE(context, t); \
        Meta* meta = GET_META(data); \
        meta->wait = createSynchronizedQueue(context); \
        data; })

#define ALLOC(context, t) (&ALLOCATE(context, t)->t)

#define GET_META(dseg) ((Meta*)(((void*)dseg) - sizeof(Meta)))
#define GET_TYPE(dseg) (GET_META(dseg)->type)
#define GET_SIZE(dseg) (GET_META(dseg)->size)
#define GET_LEN(dseg) (GET_META(dseg)->len)
#define GET_WAIT_LIST(dseg) (GET_META(dseg)->wait)

#define Gearef(context, t) (&(context)->data[D_##t]->t)

// (SingleLinkedStack *)context->data[D_Stack]->Stack.stack->Stack.stack

#define GearImpl(context, intf, name) (Gearef(context, intf)->name->intf.name)

#include "c/enumCode.h"

enum Relational {
    EQ,
    GT,
    LT,
};

#include "c/enumData.h"

struct Context {
    enum Code next;
    struct Worker* worker;
    struct TaskManager* taskManager;
    int codeNum;
    __code (**code) (struct Context*);
    union Data **data;
    void* heapStart;
    void* heap;
    long heapLimit;
    int dataNum;

    // task parameter
    int idgCount; //number of waiting dataGear
    int idg;
    int maxIdg;
    int odg;
    int maxOdg;
    int gpu; // GPU task
    struct Context* task;
    struct Element* taskList;
#ifdef USE_CUDAWorker
    int num_exec;
    CUmodule module;
    CUfunction function;
#endif
    /* multi dimension parameter */
    int iterate;
    struct Iterator* iterator;
    enum Code before;
};

typedef int Int;
#ifndef USE_CUDAWorker
typedef unsigned long long CUdeviceptr;
#endif
union Data {
    struct Meta {
        enum DataType type;
        long size;
        long len;
        struct Queue* wait; // tasks waiting this dataGear
    } Meta;
    struct Context Context;
    struct Timer {
        union Data* timer;
        enum Code start;
        enum Code end;
        enum Code next;
    } Timer;
    struct TimerImpl {
        double time;
    } TimerImpl;
    struct LoopCounter {
        int i;
    } LoopCounter;
    struct TaskManager {
        union Data* taskManager;
        enum Code spawn;      // start NEW context on the worker
        enum Code spawnTasks; // start NEW tasks on the worker
        enum Code shutdown;
        enum Code incrementTaskCount;
        enum Code decrementTaskCount;
        enum Code next;
        enum Code next1;
        enum Code setWaitTask;
        struct Context* task;
        struct Element* taskList;
        union Data* data;
    } TaskManager;
    struct TaskManagerImpl {
        enum Code next;
        int numWorker;
        int sendCPUWorkerIndex;
        int sendGPUWorkerIndex;
        int taskCount;
        pthread_mutex_t mutex;
        struct Queue* activeQueue;
        struct Worker** workers;
        struct Element* taskList;
        int loopCounter;
        int cpu;
        int gpu;
        int io;
        int maxCPU;
    } TaskManagerImpl;
    struct Worker {
        union Data* worker;
        enum Code taskReceive;
        enum Code shutdown;
        enum Code next;
        struct Queue* tasks;
        pthread_t thread;
        struct TaskManager* taskManager;
        struct Context* task;
    } Worker;
    struct CPUWorker {
        pthread_mutex_t mutex;
        pthread_cond_t cond;
        struct Context* context;
        int id;
        int loopCounter;
    } CPUWorker;
#ifdef USE_CUDAWorker
    struct CUDAWorker {
        CUdevice device;
        CUcontext cuCtx;
        struct Context* context;
        int id;
        int loopCounter;
        int deviceNum;
        struct Queue* tasks;
        int runFlag;
        enum Code next;
        int numStream;
        struct Executor* executor;
        CUstream *stream;
    } CUDAWorker;
#else
    struct CUDAWorker {
    } CUDAWorker;
#endif
    struct Main {
        enum Code code;
        enum Code next;
        struct Queue* args;
    } Main;
    // Queue Interface
    struct Queue {
        union Data* queue;
        union Data* data;
        enum Code whenEmpty;
        enum Code clear;
        enum Code put;
        enum Code take;
        enum Code isEmpty;
        enum Code next;
    } Queue;
    struct SingleLinkedQueue {
        struct Element* top;
        struct Element* last;
    } SingleLinkedQueue;
    struct SynchronizedQueue {
        struct Element* top;
        struct Element* last;
        struct Atomic* atomic;
    } SynchronizedQueue;
    // Stack Interface
    struct Stack {
        union Data* stack;
        union Data* data;
        union Data* data1;
        enum Code whenEmpty;
        enum Code clear;
        enum Code push;
        enum Code pop;
        enum Code pop2;
        enum Code isEmpty;
        enum Code get;
        enum Code get2;
        enum Code next;
    } Stack;
    // Stack implementations
    struct SingleLinkedStack {
        struct Element* top;
    } SingleLinkedStack;
    struct ArrayStack {
        int size;
        int limit;
        struct Element* array;
    } ArrayStack;
    // Stack implementation end
    struct Element {
        union Data* data;
        struct Element* next;
    } Element;
    struct Array {
        int prefix;
        Int* array;
    } Array;
    struct Tree {
        union Data* tree;
        struct Node* node;
        enum Code put;
        enum Code get;
        enum Code remove;
        enum Code clear;
        enum Code next;
    } Tree;
    struct RedBlackTree {
        struct Node* root;
        struct Node* current; // reading node of original tree
        struct Node* previous; // parent of reading node of original tree
        struct Node* newNode; // writing node of new tree
        struct Node* parent;
        struct Node* grandparent;
        struct Stack* nodeStack;
        enum Code findNodeNext;
        int result;
    } RedBlackTree;
    struct RotateTree {
        enum Code next;
        struct RedBlackTree* traverse;
        struct Tree* tree;
    } RotateTree;
    struct Node {
        int key; // comparable data segment
        union Data* value;
        struct Node* left;
        struct Node* right;
        // need to balancing
        enum Color {
            Red,
            Black,
            // Red eq 0,Black eq 1. enum name convert intager.
        } color;
    } Node;
    struct Atomic {
        union Data* atomic;
        union Data** ptr;
        union Data* oldData;
        union Data* newData;
        enum Code checkAndSet;
        enum Code next;
        enum Code fail;
    } Atomic;
    struct AtomicReference {
    } AtomicReference;
    struct Semaphore {
        union Data* semaphore;
        enum Code p;
        enum Code v;
        enum Code next;
    } Semaphore;
    struct SemaphoreImpl {
        int value;
        struct Lock* lock;
        struct Queue* waitThreadQueue;
    } SemaphoreImpl;
    struct Allocate {
        enum Code next;
        long size;
    } Allocate;
    struct Integer {
        int value;
    } Integer;
    struct SortArray {
        struct Integer *array; //Array arrayじゃできない?
        int loopCounter;
        int block;
        int first;
        int prefix;
    } SortArray;
    struct Iterator {
        union Data* iterator;
        struct Context* task;
        int numGPU;
        enum Code exec;
        enum Code barrier;
        enum Code whenWait;
        enum Code next;
    } Iterator;
    struct MultiDimIterator {
        int x;
        int y;
        int z;
        int count;
        int counterX;
        int counterY;
        int counterZ;
    } MultiDimIterator;
    struct MultiDim {
        int x;
        int y;
        int z;
    } MultiDim;
    struct Executor {
        union Data* executor;
        struct Context* task;
        enum Code read;
        enum Code exec;
        enum Code write;
        enum Code next;
    } Executor;
#ifdef USE_CUDAWorker
    struct CUDAExecutor {
        CUdeviceptr** kernelParams;
        struct CUDABuffer* buffer;
        int maxThreadPerBlock;
        int maxThreadPerBlockX;
        int maxThreadPerBlockY;
        int maxThreadPerBlockZ;
        struct Timer* timer;
    } CUDAExecutor;
    struct CUDABuffer {
        int inputLen;
        int outputLen;
        union Data** inputData;
        union Data** outputData;
    } CUDABuffer;
    CUdeviceptr CUdeviceptr;
#else
    struct CUDAExecutor {
    } CUDAExecutor;
    struct CUDABuffer {
    } CUDABuffer;
    CUdeviceptr CUdeviceptr;
#endif
    Int Int;
    struct Memory {
        union Data* adr;
        int length;
        union Data* body;
        int hash;
    } Memory;
    struct Buffer {
        union Data* buffer;
        union Data* data;
        enum Code put;
        enum Code take;
        enum Code next;
    } Buffer;
    struct BoundedBuffer {
        struct Element* top;
        struct Element* last;
        struct Semaphore* fullCount;
        struct Semaphore* emptyCount;
        struct Semaphore* lock;
    } BoundedBuffer;
    struct Lock {
        union Data* lock;
        enum Code doLock;
        enum Code doUnlock;
        enum Code next;
    } Lock;
    struct LockImpl {
        Int* lock;
        struct Queue* waitThreadQueue;
        struct Atomic* atomic;
        struct Context* lockContext;
    } LockImpl;
    struct SpinLock {
        volatile Int* lock;
        struct Atomic* atomic;
        struct Context* lockContext;
    } SpinLock;
}; // union Data end       this is necessary for context generator
typedef union Data Data;

#include "c/typedefData.h"

#include "c/extern.h"

extern __code start_code(struct Context* context);
extern __code exit_code(struct Context* context);
extern __code meta(struct Context* context, enum Code next);
//extern __code par_meta(struct Context* context, enum Code spawns, enum Code next);
extern __code parGotoMeta(struct Context* context, enum Code next);
extern void initContext(struct Context* context);

#endif