/*
 *  Copyright 2009 OpenSourceStewardshipFoundation.org
 *  Licensed under GNU General Public License version 2
 *
 * Author: seanhalle@yahoo.com
 * 
 */

#ifndef _VMS_H
#define	_VMS_H
#define _GNU_SOURCE

#include "VMS_primitive_data_types.h"
#include "Queue_impl/PrivateQueue.h"
#include "Histogram/Histogram.h"
#include "DynArray/DynArray.h"
#include "Hash_impl/PrivateHash.h"
#include "vmalloc.h"

#include <pthread.h>
#include <sys/time.h>

//=============  #defines  ===========
//
#include "VMS_defs.h"



//===========================================================================
typedef unsigned long long TSCount;
typedef union
 { uint32 lowHigh[2];
   uint64 longVal;
 }
TSCountLowHigh;

typedef struct _SchedSlot     SchedSlot;
typedef struct _VMSReqst      VMSReqst;
typedef struct _VirtProcr     VirtProcr;
typedef struct _IntervalProbe IntervalProbe;
typedef struct _GateStruc     GateStruc;


typedef VirtProcr * (*SlaveScheduler)  ( void *, int );   //semEnv, coreIdx
typedef void  (*RequestHandler)  ( VirtProcr *, void * ); //prWReqst, semEnv
typedef void  (*VirtProcrFnPtr)  ( void *, VirtProcr * ); //initData, animPr
typedef void    VirtProcrFn      ( void *, VirtProcr * ); //initData, animPr
typedef void  (*ResumePrFnPtr)   ( VirtProcr *, void * );


//============= Requests ===========
//

enum VMSReqstType   //avoid starting enums at 0, for debug reasons
 {
   semantic = 1,
   createReq,
   dissipate,
   VMSSemantic      //goes with VMSSemReqst below
 };

struct _VMSReqst
 {
   enum VMSReqstType  reqType;//used for dissipate and in future for IO requests
   void              *semReqData;

   VMSReqst *nextReqst;
 };
//VMSReqst

enum VMSSemReqstType   //These are equivalent to semantic requests, but for
 {                     // VMS's services available directly to app, like OS
   createProbe = 1,    // and probe services -- like a VMS-wide built-in lang
   openFile,
   otherIO
 };

typedef struct
 { enum VMSSemReqstType reqType;
   VirtProcr           *requestingPr;
   char                *nameStr;  //for create probe
 }
 VMSSemReq;


//====================  Core data structures  ===================

struct _SchedSlot
 {
   int         workIsDone;
   int         needsProcrAssigned;
   VirtProcr  *procrAssignedToSlot;
 };
//SchedSlot

/*WARNING: re-arranging this data structure could cause VP switching
 *         assembly code to fail -- hard-codes offsets of fields
 */
struct _VirtProcr
 { int         procrID;  //for debugging -- count up each time create
   int         coreAnimatedBy;
   void       *startOfStack;
   void       *stackPtr;
   void       *framePtr;
   void       *nextInstrPt;
   
   void       *coreLoopStartPt;  //allows proto-runtime to be linked later
   void       *coreLoopFramePtr; //restore before jmp back to core loop
   void       *coreLoopStackPtr; //restore before jmp back to core loop

   void       *initialData;

   SchedSlot  *schedSlot;
   VMSReqst   *requests;

   void       *semanticData; //this livesUSE_GNU here for the life of VP
   void       *dataRetFromReq;//values returned from plugin to VP go here

      //=========== MEASUREMENT STUFF ==========
       #ifdef MEAS__TIME_STAMP_SUSP
       uint32  preSuspTSCLow;
       uint32  postSuspTSCLow;
       #endif
       #ifdef MEAS__TIME_MASTER /* in VirtProcr because multiple masterVPs*/
       uint32  startMasterTSCLow;USE_GNU
       uint32  endMasterTSCLow;
       #endif
       #ifdef MEAS__TIME_2011_SYS
       TSCountLowHigh  startSusp;
       uint64  totalSuspCycles;
       uint32  numGoodSusp;
       #endif
      //========================================
   
   float64      createPtInSecs;  //have space but don't use on some configs
 };
//VirtProcr


/*WARNING: re-arranging this data structure could cause VP-switching
 *         assembly code to fail -- hard-codes offsets of fields
 *         (because -O3 messes with things otherwise)
 */
typedef struct
 {
   SlaveScheduler   slaveScheduler;
   RequestHandler   requestHandler;
   
   SchedSlot     ***allSchedSlots;
   VMSQueueStruc **readyToAnimateQs;
   VirtProcr      **masterVPs;

   void            *semanticEnv;
   void            *OSEventStruc;   //for future, when add I/O to BLIS
   MallocArrays    *freeLists;
   int32            amtOfOutstandingMem; //total currently allocated

   void            *coreLoopReturnPt;//addr to jump to to re-enter coreLoop

   int32            setupComplete;
   volatile int32   masterLock;

   int32            numMasterInARow[NUM_CORES];//detect back-to-back masterVP
   GateStruc       *workStealingGates[ NUM_CORES ]; //concurrent work-steal
   int32            workStealingLock;
   
   int32            numProcrsCreated; //gives ordering to processor creation

      //=========== MEASUREMENT STUFF =============
       IntervalProbe  **intervalProbes;
       PrivDynArrayInfo    *dynIntervalProbesInfo;
       HashTable       *probeNameHashTbl;
       int32            masterCreateProbeID;
       float64          createPtInSecs;
       Histogram      **measHists;
       PrivDynArrayInfo *measHistsInfo;
       #ifdef MEAS__TIME_PLUGIN
       Histogram       *reqHdlrLowTimeHist;
       Histogram       *reqHdlrHighTimeHist;
       #endif
       #ifdef MEAS__TIME_MALLOC
       Histogram       *mallocTimeHist;
       Histogram       *freeTimeHist;
       #endif
       #ifdef MEAS__TIME_MASTER_LOCK
       Histogram       *masterLockLowTimeHist;
       Histogram       *masterLockHighTimeHist;
       #endif
       #ifdef MEAS__TIME_2011_SYS
       TSCountLowHigh   startMaster;
       uint64           totalMasterCycles;
       uint32           numMasterAnimations;
       TSCountLowHigh   startReqHdlr;
       uint64           totalPluginCycles;
       uint32           numPluginAnimations;
       uint64           cyclesTillStartMasterLoop;
       TSCountLowHigh   endMasterLoop;
       #endif
      //==========================================
 }
MasterEnv;

//=========================  Extra Stuff Data Strucs  =======================
typedef struct
 {

 }
VMSExcp;

struct _GateStruc
 {
   int32 gateClosed;
   int32 preGateProgress;
   int32 waitProgress;
   int32 exitProgress;
 };
//GateStruc

//=======================  OS Thread related  ===============================

void * coreLoop( void *paramsIn );  //standard PThreads fn prototype
void * coreLoop_Seq( void *paramsIn );  //standard PThreads fn prototype
void masterLoop( void *initData, VirtProcr *masterVP );


typedef struct
 {
   void           *endThdPt;
   unsigned int    coreNum;
 }
ThdParams;

pthread_t       coreLoopThdHandles[ NUM_CORES ];  //pthread's virt-procr state
ThdParams      *coreLoopThdParams [ NUM_CORES ];
pthread_mutex_t suspendLock;
pthread_cond_t  suspend_cond;



//=====================  Global Vars ===================

volatile MasterEnv      *_VMSMasterEnv __align_to_cacheline__;




//===========================  Function Prototypes  =========================


//========== Setup and shutdown ==========
void
VMS__init();

void
VMS__init_Seq();

void
VMS__start_the_work_then_wait_until_done();

void
VMS__start_the_work_then_wait_until_done_Seq();

inline VirtProcr *
VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData );

void
VMS__dissipate_procr( VirtProcr *procrToDissipate );

   //Use this to create processor inside entry point & other places outside
   // the VMS system boundary (IE, not run in slave nor Master)
VirtProcr *
VMS_ext__create_procr( VirtProcrFnPtr fnPtr, void *initialData );

void
VMS_ext__dissipate_procr( VirtProcr *procrToDissipate );

void
VMS__throw_exception( char *msgStr, VirtProcr *reqstPr, VMSExcp *excpData );

void
VMS__shutdown();

void
VMS__cleanup_at_end_of_shutdown();

void *
VMS__give_sem_env_for( VirtProcr *animPr );


//==============  Request Related  ===============

void
VMS__suspend_procr( VirtProcr *callingPr );

inline void
VMS__add_sem_request_in_mallocd_VMSReqst( void *semReqData, VirtProcr *callingPr );

inline void
VMS__send_sem_request( void *semReqData, VirtProcr *callingPr );

void
VMS__send_create_procr_req( void *semReqData, VirtProcr *reqstingPr );

void inline
VMS__send_dissipate_req( VirtProcr *prToDissipate );

inline void
VMS__send_VMSSem_request( void *semReqData, VirtProcr *callingPr );

VMSReqst *
VMS__take_next_request_out_of( VirtProcr *procrWithReq );

inline void *
VMS__take_sem_reqst_from( VMSReqst *req );

void inline
VMS__handle_VMSSemReq( VMSReqst *req, VirtProcr *requestingPr, void *semEnv,
                       ResumePrFnPtr resumePrFnPtr );

//======================== MEASUREMENT ======================
uint64
VMS__give_num_plugin_cycles();
uint32
VMS__give_num_plugin_animations();



#include "ProcrContext.h"
#include "probes.h"
#include "vutilities.h"
#include "../VMS_lang_specific_defines.h"
#endif	/* _VMS_H */

