msach@146: /* msach@146: * Copyright 2009 OpenSourceStewardshipFoundation.org msach@146: * Licensed under GNU General Public License version 2 msach@146: * msach@146: * Author: seanhalle@yahoo.com msach@146: * msach@146: */ msach@146: msach@146: #ifndef _VMS_H msach@146: #define _VMS_H msach@146: #define __USE_GNU msach@146: msach@146: #include "VMS_primitive_data_types.h" msach@146: #include "Queue_impl/PrivateQueue.h" msach@146: #include "Histogram/Histogram.h" msach@146: #include "DynArray/DynArray.h" msach@146: #include "Hash_impl/PrivateHash.h" msach@146: #include "vmalloc.h" msach@146: msach@146: #include msach@146: #include msach@146: msach@146: msach@146: //=============================== Debug =================================== msach@146: // msach@146: //When SEQUENTIAL is defined, VMS does sequential exe in the main thread msach@146: // It still does co-routines and all the mechanisms are the same, it just msach@146: // has only a single thread and animates VPs one at a time msach@146: //#define SEQUENTIAL msach@146: msach@146: //#define USE_WORK_STEALING msach@146: msach@146: //turns on the probe-instrumentation in the application -- when not msach@146: // defined, the calls to the probe functions turn into comments msach@146: #define STATS__ENABLE_PROBES msach@146: //#define TURN_ON_DEBUG_PROBES msach@146: msach@146: //These defines turn types of bug messages on and off msach@146: // be sure debug messages are un-commented (next block of defines) msach@146: #define dbgAppFlow TRUE /* Top level flow of application code -- general*/ msach@146: #define dbgProbes FALSE /* for issues inside probes themselves*/ msach@146: #define dbgB2BMaster FALSE /* in coreloop, back to back master VPs*/ msach@146: #define dbgRqstHdlr FALSE /* in request handler code*/ msach@146: msach@146: //Comment or un- the substitute half to turn on/off types of debug message msach@146: #define DEBUG( bool, msg) \ msach@146: // if( bool){ printf(msg); fflush(stdin);} msach@146: #define DEBUG1( bool, msg, param) \ msach@146: // if(bool){printf(msg, param); fflush(stdin);} msach@146: #define DEBUG2( bool, msg, p1, p2) \ msach@146: // if(bool) {printf(msg, p1, p2); fflush(stdin);} msach@146: msach@146: #define ERROR(msg) printf(msg); msach@146: #define ERROR1(msg, param) printf(msg, param); msach@146: #define ERROR2(msg, p1, p2) printf(msg, p1, p2); msach@146: msach@146: //=========================== STATS ======================= msach@146: msach@146: //when MEAS__TIME_STAMP_SUSP is defined, causes code to be inserted and msach@146: // compiled-in that saves the low part of the time stamp count just before msach@146: // suspending a processor and just after resuming that processor. It is msach@146: // saved into a field added to VirtProcr. Have to sanity-check for msach@146: // rollover of low portion into high portion. msach@146: //#define MEAS__TIME_STAMP_SUSP msach@146: //#define MEAS__TIME_MASTER msach@146: #define MEAS__TIME_PLUGIN msach@146: #define MEAS__TIME_MALLOC msach@146: //#define MEAS__TIME_MASTER_LOCK msach@146: #define MEAS__NUM_TIMES_TO_RUN 100000 msach@146: msach@146: //For code that calculates normalization-offset between TSC counts of msach@146: // different cores. msach@146: #define NUM_TSC_ROUND_TRIPS 10 msach@146: msach@146: msach@146: //========================= Hardware related Constants ===================== msach@146: //This value is the number of hardware threads in the shared memory msach@146: // machine msach@146: #define NUM_CORES 4 msach@146: msach@146: // tradeoff amortizing master fixed overhead vs imbalance potential msach@146: // when work-stealing, can make bigger, at risk of losing cache affinity msach@146: #define NUM_SCHED_SLOTS 5 msach@146: msach@146: #define MIN_WORK_UNIT_CYCLES 20000 msach@146: msach@146: #define MASTERLOCK_RETRIES 10000 msach@146: msach@146: // stack size in virtual processors created msach@146: #define VIRT_PROCR_STACK_SIZE 0x4000 /* 16K */ msach@146: msach@146: // memory for VMS__malloc msach@146: #define MALLOC_ADDITIONAL_MEM_FROM_OS_SIZE 0x10000000 /* 256M */ msach@146: msach@146: msach@146: //============================== msach@146: msach@146: #define SUCCESS 0 msach@146: msach@146: #define writeVMSQ writePrivQ msach@146: #define readVMSQ readPrivQ msach@146: #define makeVMSQ makeVMSPrivQ msach@146: #define numInVMSQ numInPrivQ msach@146: #define VMSQueueStruc PrivQueueStruc msach@146: msach@146: msach@146: msach@146: //=========================================================================== msach@146: typedef unsigned long long TSCount; msach@146: msach@146: typedef struct _SchedSlot SchedSlot; msach@146: typedef struct _VMSReqst VMSReqst; msach@146: typedef struct _VirtProcr VirtProcr; msach@146: typedef struct _IntervalProbe IntervalProbe; msach@146: typedef struct _GateStruc GateStruc; msach@146: msach@146: msach@146: typedef VirtProcr * (*SlaveScheduler) ( void *, int ); //semEnv, coreIdx msach@146: typedef void (*RequestHandler) ( VirtProcr *, void * ); //prWReqst, semEnv msach@146: typedef void (*VirtProcrFnPtr) ( void *, VirtProcr * ); //initData, animPr msach@146: typedef void VirtProcrFn ( void *, VirtProcr * ); //initData, animPr msach@146: typedef void (*ResumePrFnPtr) ( VirtProcr *, void * ); msach@146: msach@146: msach@146: //============= Requests =========== msach@146: // msach@146: msach@146: enum VMSReqstType //avoid starting enums at 0, for debug reasons msach@146: { msach@146: semantic = 1, msach@146: createReq, msach@146: dissipate, msach@146: VMSSemantic //goes with VMSSemReqst below msach@146: }; msach@146: msach@146: struct _VMSReqst msach@146: { msach@146: enum VMSReqstType reqType;//used for dissipate and in future for IO requests msach@146: void *semReqData; msach@146: msach@146: VMSReqst *nextReqst; msach@146: }; msach@146: //VMSReqst msach@146: msach@146: enum VMSSemReqstType //These are equivalent to semantic requests, but for msach@146: { // VMS's services available directly to app, like OS msach@146: createProbe = 1, // and probe services -- like a VMS-wide built-in lang msach@146: openFile, msach@146: otherIO msach@146: }; msach@146: msach@146: typedef struct msach@146: { enum VMSSemReqstType reqType; msach@146: VirtProcr *requestingPr; msach@146: char *nameStr; //for create probe msach@146: } msach@146: VMSSemReq; msach@146: msach@146: msach@146: //==================== Core data structures =================== msach@146: msach@146: struct _SchedSlot msach@146: { msach@146: int workIsDone; msach@146: int needsProcrAssigned; msach@146: VirtProcr *procrAssignedToSlot; msach@146: }; msach@146: //SchedSlot msach@146: msach@146: /*WARNING: re-arranging this data structure could cause VP switching msach@146: * assembly code to fail -- hard-codes offsets of fields msach@146: */ msach@146: struct _VirtProcr msach@146: { int procrID; //for debugging -- count up each time create msach@146: int coreAnimatedBy; msach@146: void *startOfStack; msach@146: void *stackPtr; msach@146: void *framePtr; msach@146: void *nextInstrPt; msach@146: msach@146: void *coreLoopStartPt; //allows proto-runtime to be linked later msach@146: void *coreLoopFramePtr; //restore before jmp back to core loop msach@146: void *coreLoopStackPtr; //restore before jmp back to core loop msach@146: msach@146: void *initialData; msach@146: msach@146: SchedSlot *schedSlot; msach@146: VMSReqst *requests; msach@146: msach@146: void *semanticData; //this lives here for the life of VP msach@146: void *dataRetFromReq;//values returned from plugin to VP go here msach@146: msach@146: //=========== MEASUREMENT STUFF ========== msach@146: #ifdef MEAS__TIME_STAMP_SUSP msach@146: unsigned int preSuspTSCLow; msach@146: unsigned int postSuspTSCLow; msach@146: #endif msach@146: #ifdef MEAS__TIME_MASTER /* in VirtProcr because multiple masterVPs*/ msach@146: unsigned int startMasterTSCLow; msach@146: unsigned int endMasterTSCLow; msach@146: #endif msach@146: //======================================== msach@146: msach@146: float64 createPtInSecs; //have space but don't use on some configs msach@146: }; msach@146: //VirtProcr msach@146: msach@146: msach@146: /*WARNING: re-arranging this data structure could cause VP-switching msach@146: * assembly code to fail -- hard-codes offsets of fields msach@146: * (because -O3 messes with things otherwise) msach@146: */ msach@146: typedef struct msach@146: { msach@146: SlaveScheduler slaveScheduler; msach@146: RequestHandler requestHandler; msach@146: msach@146: SchedSlot ***allSchedSlots; msach@146: VMSQueueStruc **readyToAnimateQs; msach@146: VirtProcr **masterVPs; msach@146: msach@146: void *semanticEnv; msach@146: void *OSEventStruc; //for future, when add I/O to BLIS msach@146: MallocProlog *freeListHead; msach@146: int32 amtOfOutstandingMem; //total currently allocated msach@146: msach@146: void *coreLoopStartPt;//addr to jump to to re-enter coreLoop msach@146: void *coreLoopEndPt; //addr to jump to to shut down a coreLoop msach@146: msach@146: int32 setupComplete; msach@146: int32 masterLock; msach@146: msach@146: int32 numMasterInARow[NUM_CORES];//detect back-to-back masterVP msach@146: GateStruc *workStealingGates[ NUM_CORES ]; //concurrent work-steal msach@146: int32 workStealingLock; msach@146: msach@146: int32 numProcrsCreated; //gives ordering to processor creation msach@146: msach@146: //=========== MEASUREMENT STUFF ============= msach@146: IntervalProbe **intervalProbes; msach@146: PrivDynArrayInfo *dynIntervalProbesInfo; msach@146: HashTable *probeNameHashTbl; msach@146: int32 masterCreateProbeID; msach@146: float64 createPtInSecs; msach@146: Histogram **measHists; msach@146: PrivDynArrayInfo *measHistsInfo; msach@146: #ifdef MEAS__TIME_PLUGIN msach@146: Histogram *reqHdlrLowTimeHist; msach@146: Histogram *reqHdlrHighTimeHist; msach@146: #endif msach@146: #ifdef MEAS__TIME_MALLOC msach@146: Histogram *mallocTimeHist; msach@146: Histogram *freeTimeHist; msach@146: #endif msach@146: #ifdef MEAS__TIME_MASTER_LOCK msach@146: Histogram *masterLockLowTimeHist; msach@146: Histogram *masterLockHighTimeHist; msach@146: #endif msach@146: } msach@146: MasterEnv; msach@146: msach@146: //========================= Extra Stuff Data Strucs ======================= msach@146: typedef struct msach@146: { msach@146: msach@146: } msach@146: VMSExcp; msach@146: msach@146: struct _GateStruc msach@146: { msach@146: int32 gateClosed; msach@146: int32 preGateProgress; msach@146: int32 waitProgress; msach@146: int32 exitProgress; msach@146: }; msach@146: //GateStruc msach@146: msach@146: //======================= OS Thread related =============================== msach@146: msach@146: void * coreLoop( void *paramsIn ); //standard PThreads fn prototype msach@146: void * coreLoop_Seq( void *paramsIn ); //standard PThreads fn prototype msach@146: void masterLoop( void *initData, VirtProcr *masterPr ); msach@146: msach@146: msach@146: typedef struct msach@146: { msach@146: void *endThdPt; msach@146: unsigned int coreNum; msach@146: } msach@146: ThdParams; msach@146: msach@146: pthread_t coreLoopThdHandles[ NUM_CORES ]; //pthread's virt-procr state msach@146: ThdParams *coreLoopThdParams [ NUM_CORES ]; msach@146: pthread_mutex_t suspendLock; msach@146: pthread_cond_t suspend_cond; msach@146: msach@146: msach@146: msach@146: //===================== Global Vars =================== msach@146: msach@146: volatile MasterEnv *_VMSMasterEnv; msach@146: msach@146: msach@146: msach@146: msach@146: //=========================== Function Prototypes ========================= msach@146: msach@146: msach@146: //========== Setup and shutdown ========== msach@146: void msach@146: VMS__init(); msach@146: msach@146: void msach@146: VMS__init_Seq(); msach@146: msach@146: void msach@146: VMS__start_the_work_then_wait_until_done(); msach@146: msach@146: void msach@146: VMS__start_the_work_then_wait_until_done_Seq(); msach@146: msach@146: VirtProcr * msach@146: VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ); msach@146: msach@146: void msach@146: VMS__dissipate_procr( VirtProcr *procrToDissipate ); msach@146: msach@146: //Use this to create processor inside entry point & other places outside msach@146: // the VMS system boundary (IE, not run in slave nor Master) msach@146: VirtProcr * msach@146: VMS_ext__create_procr( VirtProcrFnPtr fnPtr, void *initialData ); msach@146: msach@146: void msach@146: VMS_ext__dissipate_procr( VirtProcr *procrToDissipate ); msach@146: msach@146: void msach@146: VMS__throw_exception( char *msgStr, VirtProcr *reqstPr, VMSExcp *excpData ); msach@146: msach@146: void msach@146: VMS__shutdown(); msach@146: msach@146: void msach@146: VMS__cleanup_at_end_of_shutdown(); msach@146: msach@146: void * msach@146: VMS__give_sem_env_for( VirtProcr *animPr ); msach@146: msach@146: msach@146: //============== Request Related =============== msach@146: msach@146: void msach@146: VMS__suspend_procr( VirtProcr *callingPr ); msach@146: msach@146: inline void msach@146: VMS__add_sem_request_in_mallocd_VMSReqst( void *semReqData, VirtProcr *callingPr ); msach@146: msach@146: inline void msach@146: VMS__send_sem_request( void *semReqData, VirtProcr *callingPr ); msach@146: msach@146: void msach@146: VMS__send_create_procr_req( void *semReqData, VirtProcr *reqstingPr ); msach@146: msach@146: void inline msach@146: VMS__send_dissipate_req( VirtProcr *prToDissipate ); msach@146: msach@146: inline void msach@146: VMS__send_VMSSem_request( void *semReqData, VirtProcr *callingPr ); msach@146: msach@146: VMSReqst * msach@146: VMS__take_next_request_out_of( VirtProcr *procrWithReq ); msach@146: msach@146: inline void * msach@146: VMS__take_sem_reqst_from( VMSReqst *req ); msach@146: msach@146: //======================== STATS ====================== msach@146: msach@146: //===== RDTSC wrapper ===== msach@146: msach@146: #define saveTimeStampCountInto(low, high) \ msach@146: asm volatile("RDTSC; \ msach@146: movl %%eax, %0; \ msach@146: movl %%edx, %1;" \ msach@146: /* outputs */ : "=m" (low), "=m" (high)\ msach@146: /* inputs */ : \ msach@146: /* clobber */ : "%eax", "%edx" \ msach@146: ); msach@146: msach@146: #define saveLowTimeStampCountInto(low) \ msach@146: asm volatile("RDTSC; \ msach@146: movl %%eax, %0;" \ msach@146: /* outputs */ : "=m" (low) \ msach@146: /* inputs */ : \ msach@146: /* clobber */ : "%eax", "%edx" \ msach@146: ); msach@146: msach@146: //==================== msach@146: #define makeAMeasHist( idx, name, numBins, startVal, binWidth ) \ msach@146: makeHighestDynArrayIndexBeAtLeast( _VMSMasterEnv->measHistsInfo, idx ); \ msach@146: _VMSMasterEnv->measHists[idx] = \ msach@146: makeFixedBinHist( numBins, startVal, binWidth, name ); msach@146: msach@146: msach@146: #define MEAS__SUB_CREATE /*turn on/off subtraction of create from plugin*/ msach@146: #define createHistIdx 0 msach@146: #define mutexLockHistIdx 1 msach@146: #define mutexUnlockHistIdx 2 msach@146: #define condWaitHistIdx 3 msach@146: #define condSignalHistIdx 4 msach@146: msach@146: msach@146: #define MakeTheMeasHists \ msach@146: _VMSMasterEnv->measHistsInfo = \ msach@146: makePrivDynArrayOfSize( &(_VMSMasterEnv->measHists), 200);\ msach@146: makeAMeasHist( createHistIdx, "Create", 50, 0, 200 ) \ msach@146: makeAMeasHist( mutexLockHistIdx, "mutex lock", 50, 0, 100 ) \ msach@146: makeAMeasHist( mutexUnlockHistIdx, "mutex unlock", 50, 0, 100 ) \ msach@146: makeAMeasHist( condWaitHistIdx, "cond wait", 50, 0, 100 ) \ msach@146: makeAMeasHist( condSignalHistIdx, "cond signal", 50, 0, 100 ) msach@146: msach@146: #define Meas_startCreate \ msach@146: int32 startStamp, endStamp; \ msach@146: saveLowTimeStampCountInto( startStamp ); \ msach@146: msach@146: #define Meas_endCreate \ msach@146: saveLowTimeStampCountInto( endStamp ); \ msach@146: addIntervalToHist( startStamp, endStamp, \ msach@146: _VMSMasterEnv->measHists[ createHistIdx ] ); msach@146: msach@146: #define Meas_startMutexLock \ msach@146: int32 startStamp, endStamp; \ msach@146: saveLowTimeStampCountInto( startStamp ); \ msach@146: msach@146: #define Meas_endMutexLock \ msach@146: saveLowTimeStampCountInto( endStamp ); \ msach@146: addIntervalToHist( startStamp, endStamp, \ msach@146: _VMSMasterEnv->measHists[ mutexLockHistIdx ] ); msach@146: msach@146: #define Meas_startMutexUnlock \ msach@146: int32 startStamp, endStamp; \ msach@146: saveLowTimeStampCountInto( startStamp ); \ msach@146: msach@146: #define Meas_endMutexUnlock \ msach@146: saveLowTimeStampCountInto( endStamp ); \ msach@146: addIntervalToHist( startStamp, endStamp, \ msach@146: _VMSMasterEnv->measHists[ mutexUnlockHistIdx ] ); msach@146: msach@146: #define Meas_startCondWait \ msach@146: int32 startStamp, endStamp; \ msach@146: saveLowTimeStampCountInto( startStamp ); \ msach@146: msach@146: #define Meas_endCondWait \ msach@146: saveLowTimeStampCountInto( endStamp ); \ msach@146: addIntervalToHist( startStamp, endStamp, \ msach@146: _VMSMasterEnv->measHists[ condWaitHistIdx ] ); msach@146: msach@146: #define Meas_startCondSignal \ msach@146: int32 startStamp, endStamp; \ msach@146: saveLowTimeStampCountInto( startStamp ); \ msach@146: msach@146: #define Meas_endCondSignal \ msach@146: saveLowTimeStampCountInto( endStamp ); \ msach@146: addIntervalToHist( startStamp, endStamp, \ msach@146: _VMSMasterEnv->measHists[ condSignalHistIdx ] ); msach@146: msach@146: msach@146: //===== msach@146: msach@146: #include "SwitchAnimators.h" msach@146: #include "probes.h" msach@146: #include "vutilities.h" msach@146: msach@146: #endif /* _VMS_H */ msach@146: