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