/*
 *  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 "DynArray/DynArray.h"
#include "Hash_impl/PrivateHash.h"
#include "Histogram/Histogram.h"
#include "Queue_impl/PrivateQueue.h"
#include "Services_Offered_by_VMS/Memory_Handling/vmalloc.h"

#include <pthread.h>
#include <sys/time.h>

//=================  Defines: included from separate files  =================
//
// Note: ALL defines are in other files, none are in here
//
#include "Defines/VMS_defs.h"


//================================ Typedefs =================================
//
typedef unsigned long long TSCount;
typedef union
 { uint32 lowHigh[2];
   uint64 longVal;
 }
TSCountLowHigh;

typedef struct _SchedSlot     SchedSlot;
typedef struct _VMSReqst      VMSReqst;
typedef struct _SlaveVP       SlaveVP;
typedef struct _MasterVP      MasterVP;
typedef struct _IntervalProbe IntervalProbe;
typedef struct _GateStruc     GateStruc;


typedef SlaveVP *(*SlaveAssigner)  ( void *, int, SchedSlot *); //semEnv, coreIdx, slot for HW info
typedef void     (*RequestHandler) ( SlaveVP *, void * ); //prWReqst, semEnv
typedef void     (*TopLevelFnPtr)  ( void *, SlaveVP * ); //initData, animSlv
typedef void       TopLevelFn      ( void *, SlaveVP * ); //initData, animSlv
typedef void     (*ResumeSlvFnPtr) ( SlaveVP *, void * );
      //=========== MEASUREMENT STUFF ==========
        MEAS__Insert_Counter_Handler
      //========================================

//============================ HW Dependent Fns ================================

#include "Hardware_Dependent/VMS__HW_measurement.h"
#include "Hardware_Dependent/VMS__primitives.h"

//============================= Statistics ==================================

inline TSCount getTSCount();

//============= Request Related ===========
//

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;
   SlaveVP           *requestingSlv;
   char                *nameStr;  //for create probe
 }
 VMSSemReq;


//====================  Core data structures  ===================

struct _SchedSlot
 {
   int         slotIdx;     //needed by Holistic Model's data gathering
   int         workIsDone;
   int         needsSlaveAssigned;
   SlaveVP    *slaveAssignedToSlot;
 };
//SchedSlot

 enum VPtype {
     Slave = 1, //default
     Master,
     Shutdown
 };
 
/*WARNING: re-arranging this data structure could cause Slv switching
 *         assembly code to fail -- hard-codes offsets of fields
 */
struct _SlaveVP
 { int         slaveID;  //each slave given a unique ID
   int         coreAnimatedBy;
   void       *startOfStack;
   void       *stackPtr;
   void       *framePtr;
   void       *resumeInstrPtr;
   
   void       *coreCtlrStartPt;  //allows proto-runtime to be linked later
   void       *coreCtlrFramePtr; //restore before jmp back to core controller
   void       *coreCtlrStackPtr; //restore before jmp back to core controller

   SchedSlot  *schedSlot;
   VMSReqst   *requests;

   void       *semanticData; //this is live for the life of Slv
   void       *dataRetFromReq;//Used to return vals from plugin to Wrapper Lib

      //=========== MEASUREMENT STUFF ==========
       MEAS__Insert_Meas_Fields_into_Slave;
      //========================================
   
   enum VPtype type;
   int         numTimesAssigned;
       
   float64     createPtInSecs;  //have space but don't use on some configs
 };
//SlaveVP


/*WARNING: re-arranging this data structure could cause Slv-switching
 *         assembly code to fail -- hard-codes offsets of fields
 *         (because -O3 messes with things otherwise)
 */
typedef struct
 {    //The offset of these fields is hard-coded into assembly
   void            *coreCtlrReturnPt;    //offset of field used in asm
   int32            masterLock __align_to_cacheline__;   //used in asm
   
      //below this, no asm uses the field offsets
   SlaveAssigner    slaveAssigner;
   RequestHandler   requestHandler;
   
   SchedSlot     ***allSchedSlots;
   SlaveVP        **masterVPs;

   void            *semanticEnv;
   void            *OSEventStruc;   //for future, when add I/O to BLIS
   MallocArrays    *freeLists;
   int32            amtOfOutstandingMem; //total currently allocated

   int32            setupComplete;  //use while starting up coreCtlr
   GateStruc       *workStealingGates[ NUM_CORES ]; //concurrent work-steal
   int32            workStealingLock;
   
   int32            numSlavesCreated; //gives ordering to processor creation
   int32            numSlavesAlive;   //used to detect when to shutdown

      //=========== MEASUREMENT STUFF =============
       IntervalProbe   **intervalProbes;
       PrivDynArrayInfo *dynIntervalProbesInfo;
       HashTable        *probeNameHashTbl;
       int32             masterCreateProbeID;
       float64           createPtInSecs;
       Histogram       **measHists;
       PrivDynArrayInfo *measHistsInfo;
       MEAS__Insert_Susp_Meas_Fields_into_MasterEnv;
       MEAS__Insert_Master_Meas_Fields_into_MasterEnv;
       MEAS__Insert_Master_Lock_Meas_Fields_into_MasterEnv;
       MEAS__Insert_Malloc_Meas_Fields_into_MasterEnv;
       MEAS__Insert_Plugin_Meas_Fields_into_MasterEnv;
       MEAS__Insert_System_Meas_Fields_into_MasterEnv;
       MEAS__Insert_Counter_Meas_Fields_into_MasterEnv;
      //==========================================
 }
MasterEnv;

//=========================  Extra Stuff Data Strucs  =======================
typedef struct
 {

 }
VMSExcp;

struct _GateStruc
 {
   int32 gateClosed;
   int32 preGateProgress;
   int32 waitProgress;
   int32 exitProgress;
 };
//GateStruc

//=======================  OS Thread related  ===============================

void * coreController( void *paramsIn );  //standard PThreads fn prototype
void * coreCtlr_Seq( void *paramsIn );  //standard PThreads fn prototype
void schedulingMaster( void *initData, SlaveVP *masterVP );


typedef struct
 {
   void           *endThdPt;
   unsigned int    coreNum;
 }
ThdParams;

//=============================  Global Vars ================================

volatile MasterEnv      *_VMSMasterEnv __align_to_cacheline__;

pthread_t       coreCtlrThdHandles[ NUM_CORES ]; //pthread's virt-procr state
ThdParams      *coreCtlrThdParams [ NUM_CORES ];

pthread_mutex_t suspendLock;
pthread_cond_t  suspendCond;

//=========================  Function Prototypes  ===========================

/* MEANING OF   WL  PI  SS  int
 * These indicate which places the function is safe to use.  They stand for:
 * WL: Wrapper Library
 * PI: Plugin 
 * SS: Startup and Shutdown
 * int: internal to the VMS implementation
 */

//========== Setup and shutdown ==========
void
VMS_SS__init();

void
VMS_SS__start_the_work_then_wait_until_done();

SlaveVP* 
VMS_SS__create_shutdown_slave();

void
VMS_SS__shutdown();

void
VMS_SS__cleanup_at_end_of_shutdown();


//==============    ===============

inline SlaveVP *
VMS_int__create_slaveVP( TopLevelFnPtr fnPtr, void *dataParam );
#define VMS_PI__create_slaveVP VMS_int__create_slaveVP
#define VMS_WL__create_slaveVP VMS_int__create_slaveVP

   //Use this to create processor inside entry point & other places outside
   // the VMS system boundary (IE, don't animate with a SlaveVP or MasterVP)
SlaveVP *
VMS_ext__create_slaveVP( TopLevelFnPtr fnPtr, void *dataParam );

inline SlaveVP *
VMS_int__create_slaveVP_helper( SlaveVP *newSlv,       TopLevelFnPtr  fnPtr,
                                void      *dataParam, void           *stackLocs );

inline void
VMS_int__point_slaveVP_to_Fn( SlaveVP *slaveVP, TopLevelFnPtr fnPtr,
                              void    *dataParam);

void
VMS_int__dissipate_slaveVP( SlaveVP *slaveToDissipate );
#define VMS_PI__dissipate_slaveVP VMS_int__dissipate_slaveVP
//WL: dissipate a SlaveVP by sending a request

void
VMS_ext__dissipate_slaveVP( SlaveVP *slaveToDissipate );

void
VMS_int__throw_exception( char *msgStr, SlaveVP *reqstSlv, VMSExcp *excpData );
#define VMS_PI__throw_exception VMS_int__throw_exception
#define VMS_WL__throw_exception VMS_int__throw_exception

void *
VMS_int__give_sem_env_for( SlaveVP *animSlv );
#define VMS_PI__give_sem_env_for  VMS_int__give_sem_env_for
#define VMS_SS__give_sem_env_for  VMS_int__give_sem_env_for
//No WL version -- not safe!  if use in WL, be sure data rd & wr is stable

//==============  Request Related  ===============

void
VMS_int__suspend_slaveVP_and_send_req( SlaveVP *callingSlv );

inline void
VMS_WL__add_sem_request_in_mallocd_VMSReqst( void *semReqData, SlaveVP *callingSlv );

inline void
VMS_WL__send_sem_request( void *semReqData, SlaveVP *callingSlv );

void
VMS_WL__send_create_slaveVP_req( void *semReqData, SlaveVP *reqstingSlv );

void inline
VMS_WL__send_dissipate_req( SlaveVP *prToDissipate );

inline void
VMS_WL__send_VMSSem_request( void *semReqData, SlaveVP *callingSlv );

VMSReqst *
VMS_PI__take_next_request_out_of( SlaveVP *slaveWithReq );

inline void *
VMS_PI__take_sem_reqst_from( VMSReqst *req );

void inline
VMS_PI__handle_VMSSemReq( VMSReqst *req, SlaveVP *requestingSlv, void *semEnv,
                       ResumeSlvFnPtr resumeSlvFnPtr );

//======================== MEASUREMENT ======================
uint64
VMS_WL__give_num_plugin_cycles();
uint32
VMS_WL__give_num_plugin_animations();


//========================= Utilities =======================
inline char *
VMS_int__strDup( char *str );


//========================= Probes =======================
#include "Services_Offered_by_VMS/Measurement_and_Stats/probes.h"

//================================================
#endif	/* _VMS_H */

