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

#include "VMS_primitive_data_types.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 struct _AnimSlot     AnimSlot;
typedef struct _VMSReqst      VMSReqst;
typedef struct _SlaveVP       SlaveVP;
typedef struct _MasterVP      MasterVP;
typedef struct _IntervalProbe IntervalProbe;


typedef SlaveVP *(*SlaveAssigner)  ( void *, AnimSlot*); //semEnv, 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 "HW_Dependent_Primitives/VMS__HW_measurement.h"
#include "HW_Dependent_Primitives/VMS__primitives.h"


//============= 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
   make_probe = 1,    // and probe services -- like a VMS-wide built-in lang
   throw_excp,
   openFile,
   otherIO
 };

typedef struct
 { enum VMSSemReqstType reqType;
   SlaveVP             *requestingSlv;
   char                *nameStr;  //for create probe
   char                *msgStr;   //for exception
   void                *exceptionData;
 }
 VMSSemReq;


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

typedef struct
 {
   //for future expansion
 }
SlotPerfInfo;

struct _AnimSlot
 {
   int           workIsDone;
   int           needsSlaveAssigned;
   SlaveVP      *slaveAssignedToSlot;
   
   int           slotIdx;  //needed by Holistic Model's data gathering
   int           coreSlotIsOn;
   SlotPerfInfo *perfInfo; //used by assigner to pick best slave for core
 };
//AnimSlot

 enum VPtype {
     Slave = 1, //default
     Master,
     Shutdown,
     Idle
 };
 
/*This structure embodies the state of a slaveVP.  It is reused for masterVP
 * and shutdownVPs.
 */
struct _SlaveVP
 {    //The offsets of these fields are hard-coded into assembly
   void       *stackPtr;         //save the core's stack ptr when suspend
   void       *framePtr;         //save core's frame ptr when suspend
   void       *resumeInstrPtr;   //save core's program-counter when suspend
   void       *coreCtlrFramePtr; //restore before jmp back to core controller
   void       *coreCtlrStackPtr; //restore before jmp back to core controller
   
      //============ below this, no fields are used in asm =============
   
   int         slaveID;       //each slave given a globally unique ID
   int         coreAnimatedBy; 
   void       *startOfStack;  //used to free, and to point slave to Fn
   enum VPtype typeOfVP;      //Slave vs Master vs Shutdown..
   int         assignCount;   //Each assign is for one work-unit, so IDs it
      //note, a scheduling decision is uniquely identified by the triple:
      // <slaveID, coreAnimatedBy, assignCount> -- used in record & replay
   
      //for comm -- between master and coreCtlr & btwn wrapper lib and plugin
   AnimSlot   *animSlotAssignedTo;
   VMSReqst   *requests;      //wrapper lib puts in requests, plugin takes out
   void       *dataRetFromReq;//Return vals from plugin to Wrapper Lib

      //For using Slave as carrier for data
   void       *semanticData;  //Lang saves lang-specific things in slave here

        //=========== MEASUREMENT STUFF ==========
         MEAS__Insert_Meas_Fields_into_Slave;
         float64     createPtInSecs;  //time VP created, in seconds
        //========================================
 };
//SlaveVP

 
/* The one and only global variable, holds many odds and ends
 */
typedef struct
 {    //The offsets of these fields are hard-coded into assembly
   void            *coreCtlrReturnPt;    //offset to this field used in asm
   int8             falseSharePad1[256 - sizeof(void*)];
   int32            masterLock;          //offset to this field used in asm
   int8             falseSharePad2[256 - sizeof(int32)];
      //============ below this, no fields are used in asm =============

      //Basic VMS infrastructure
   SlaveVP        **masterVPs;
   AnimSlot      ***allAnimSlots;
   
      //plugin related
   SlaveAssigner    slaveAssigner;
   RequestHandler   requestHandler;
   void            *semanticEnv;
   
      //Slave creation
   int32            numSlavesCreated;  //gives ordering to processor creation
   int32            numSlavesAlive;    //used to detect fail-safe shutdown

      //Initialization related
   int32            setupComplete;      //use while starting up coreCtlr

      //Memory management related
   MallocArrays    *freeLists;
   int32            amtOfOutstandingMem;//total currently allocated

      //Random number seeds -- random nums used in various places  
   uint32_t seed1;
   uint32_t seed2;

      //=========== MEASUREMENT STUFF =============
       IntervalProbe   **intervalProbes;
       PrivDynArrayInfo *dynIntervalProbesInfo;
       HashTable        *probeNameHashTbl;
       int32             masterCreateProbeID;
       float64           createPtInSecs; //real-clock time VMS initialized
       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;

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

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


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

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

volatile MasterEnv      *_VMSMasterEnv __align_to_cacheline__;

   //these are global, but only used for startup and shutdown
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 VMSOS
 * These indicate which places the function is safe to use.  They stand for:
 * 
 * WL   Wrapper Library -- wrapper lib code should only use these
 * PI   Plugin          -- plugin code should only use these
 * SS   Startup and Shutdown -- designates these relate to startup & shutdown
 * int  internal to VMS -- should not be used in wrapper lib or plugin
 * VMSOS means "OS functions for applications to use"
 * 
 * VMS_int__ functions touch internal VMS data structs and are only safe
 *  to be used inside the master lock.  However, occasionally, they appear
 * in wrapper-lib or plugin code.  In those cases, very careful analysis
 * has been done to be sure no concurrency issues could arise.
 * 
 * VMS_WL__ functions are all safe for use outside the master lock.
 * 
 * VMSOS are only safe for applications to use -- they're like a second
 * language mixed in -- but they can't be used inside plugin code, and
 * aren't meant for use in wrapper libraries, because they are themselves
 * wrapper-library calls!
 */
//========== Startup 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__reset_slaveVP_to_TopLvlFn( SlaveVP *slaveVP, TopLevelFnPtr fnPtr,
                              void    *dataParam);

inline void
VMS_int__point_slaveVP_to_OneParamFn( SlaveVP *slaveVP, void *fnPtr,
                              void    *param);

inline void
VMS_int__point_slaveVP_to_TwoParamFn( SlaveVP *slaveVP, void *fnPtr,
                              void    *param1, void *param2);

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
void
VMS_WL__throw_exception( char *msgStr, SlaveVP *reqstSlv,  VMSExcp *excpData );
#define VMS_App__throw_exception VMS_WL__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


inline void
VMS_int__get_master_lock();

#define VMS_int__release_master_lock() _VMSMasterEnv->masterLock = UNLOCKED

inline uint32_t
VMS_int__randomNumber();

//==============  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 );
//#define VMS_PI__take_next_request_out_of( slave ) slave->requests

//inline void *
//VMS_PI__take_sem_reqst_from( VMSReqst *req );
#define VMS_PI__take_sem_reqst_from( req ) req->semReqData

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 */

