/*
 *  Copyright 2009 OpenSourceStewardshipFoundation.org
 *  Licensed under GNU General Public License version 2
 *
 * Author: seanhalle@yahoo.com
 *
 */

#ifndef _VMS_H
#define	_VMS_H
#define __USE_GNU

#include "VMS_primitive_data_types.h"
#include "Queue_impl/BlockingQueue.h"
#include <pthread.h>

   //When DEBUG is defined, VMS does sequential exe in the main thread
   // It still does co-routines and all the mechanisms are the same, it just
   // has only a single thread and animates VPs one at a time
//#define DEBUG

   //This value is the number of hardware threads in the shared memory
   // machine
#define NUM_CORES        4

   // make double-num-cores scheduling slots, plus extra for master
//#define NUM_SCHED_SLOTS  (2 * NUM_CORES + 1)
#define NUM_SCHED_SLOTS  3

#define READYTOANIMATE_RETRIES 10000

   // stack
#define VIRT_PROCR_STACK_SIZE 0x10000

   //256M of total memory for VMS application to VMS__malloc
#define MASSIVE_MALLOC_SIZE 0x10000000

#define NUM_PREPEND_BYTES sizeof(FreeListElem) + sizeof(ownerElem);

#define SUCCESS 0

#define writeVMSQ     writeCASQ
#define readVMSQ      readCASQ
#define makeVMSQ      makeCASQ
#define VMSQueueStruc CASQueueStruc

//#define thdAttrs NULL  //For PThreads

typedef struct _SchedSlot  SchedSlot;
typedef struct _VMSReqst   VMSReqst;
typedef struct _VirtProcr  VirtProcr;

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 struct
 {
   void           *endThdPt;
   unsigned int    coreNum;
//   void           *framePtr;
//   void           *stackPtr;
 }
ThdParams;


struct _SchedSlot
 {
   int         workIsDone;
   int         needsProcrAssigned;
   VirtProcr  *procrAssignedToSlot;
 };
//SchedSlot
 
enum ReqstType
 {
   semantic = 1,
   dissipate,
   regCreated,
   IO
 };

struct _VMSReqst
 {
//   VirtProcr   *virtProcrFrom;
   enum ReqstType  reqType;//used for dissipate and in future for IO requests
   void           *semReqData;

   VMSReqst *nextReqst;
 };
//VMSReqst

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;
 };
//VirtProcr



typedef struct
 {
   SlaveScheduler   slaveScheduler;
   RequestHandler   requestHandler;
   
   SchedSlot     ***allSchedSlots;
   SRSWQueueStruc **readyToAnimateQs;
   VirtProcr      **masterVPs;

   void            *semanticEnv;
   void            *OSEventStruc;   //for future, when add I/O to BLIS

   void            *coreLoopStartPt;//addr to jump to to re-enter coreLoop
   void            *coreLoopEndPt;  //addr to jump to to shut down a coreLoop

   int              setupComplete;
   int              masterLock;
 }
MasterEnv;


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

void * coreLoop( void *paramsIn );  //standard PThreads fn prototype
void * coreLoop_Seq( void *paramsIn );  //standard PThreads fn prototype
void masterLoop( void *initData, VirtProcr *masterPr );


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


pthread_t       coreLoopThdHandles[ NUM_CORES ];  //pthread's virt-procr state
ThdParams      *coreLoopThdParams [ NUM_CORES ];
pthread_mutex_t suspendLock;
pthread_cond_t  suspend_cond;

volatile MasterEnv      *_VMSMasterEnv;

//==========================
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();

VirtProcr *
VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData );

VirtProcr *
VMS__create_the_shutdown_procr();

//==========================
inline void
VMS__add_sem_request( void *semReqData, VirtProcr *callingPr );

void
VMS__send_register_new_procr_request( VirtProcr *newPrToRegister,
                                      VirtProcr *reqstingPr );

void
VMS__free_request( VMSReqst *req );

void
VMS__remove_and_free_top_request( VirtProcr *reqstingPr );

VMSReqst *
VMS__take_top_request_from( VirtProcr *reqstingPr );

VMSReqst *
VMS__free_top_and_give_next_request_from( VirtProcr *procrWithReq );

inline void *
VMS__take_sem_reqst_from( VMSReqst *req );

inline int
VMS__isSemanticReqst( VMSReqst *req );

inline int
VMS__isDissipateReqst( VMSReqst *req );

inline int
VMS__isCreateReqst( VMSReqst *req );

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

void
VMS__suspend_procr( VirtProcr *callingPr );

void
VMS__dissipate_procr( VirtProcr *prToDissipate );

void
VMS__handle_dissipate_reqst( VirtProcr *procrToDissipate );

void
VMS__cleanup_after_shutdown();

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

typedef unsigned long long TSCount;

   //Frequency of TS counts
   //TODO: change freq for each machine
#define TSCOUNT_FREQ 3180000000

#define saveTimeStampCountInto(low, high) \
   asm volatile("RDTSC;                   \
                 movl %%eax, %0;          \
                 movl %%edx, %1;"         \
   /* outputs */ : "=m" (low), "=m" (high)\
   /* inputs  */ :                        \
   /* clobber */ : "%eax", "%edx"         \
                );

inline TSCount getTSCount();

//===================== Debug ==========================
int numProcrsCreated;


#endif	/* _VMS_H */

