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

#ifndef _VMS_H
#define	_VMS_H

#include "VMS_primitive_data_types.h"
#include "Queue_impl/BlockingQueue.h"
#include <windows.h>
#include <winbase.h>

//This value is the number of hardware threads in the shared memory
// machine -- make double that number scheduling slots, plus extra for master
#define NUM_CORES      4
#define NUM_SCHED_SLOTS  9

#define SUCCESS 0

//#define thdAttrs NULL  //For PThreads

typedef struct _SchedSlot  SchedSlot;
typedef struct _SlaveReqst SlaveReqst;
typedef struct _VirtProcr  VirtProcr;

typedef bool8 (*SlaveScheduler)  ( SchedSlot *, void * );
typedef void  (*RequestHandler)  ( SlaveReqst * );
typedef void  (*VirtProcrFnPtr)  ( void *, VirtProcr * );
typedef void  VirtProcrFn( void *, VirtProcr * );


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


struct _SchedSlot
 {
   int         workIsDone;
   int         needsProcrAssigned;
   VirtProcr  *procrAssignedToSlot;
 };
//SchedSlot
 

struct _SlaveReqst
 {
   VirtProcr   *slaveFrom;
   int          reqType;   //for future when have I/O and OS services
   void        *semReqData;

   SlaveReqst  *nextRequest;
 };
//SlaveReqst

struct _VirtProcr
 { int         procrID;  //for debugging -- count up each time create
   int         coreAnimatedBy;
   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;
   SlaveReqst *requests;

   void       *semanticData;
 };
//VirtProcr



typedef struct
 {
   SlaveScheduler   slaveScheduler;
   RequestHandler   requestHandler;
   
   SchedSlot **schedSlots;
   SchedSlot **filledSlots;
   int         numFilled;
   
   int         stillRunning;
   
   VirtProcr  *masterVirtPr;
   void       *semanticEnv;
   void       *OSEventStruc;    //for future, when add I/O to BLIS

   void       *coreLoopShutDownPt; //addr to jump to to shut down a coreLoop
 }
MasterEnv;


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

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


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


HANDLE      coreLoopThdHandles[ NUM_CORES ];  //windows handle to thread
ThdParams   *coreLoopThdParams[ NUM_CORES ];
DWORD           coreLoopThdIds[ NUM_CORES ];

   //TODO: Debug: figure out if need to be volatile or not
volatile MasterEnv      *_VMSMasterEnv;

   //workQ is global, static, and volatile so that core loop has its location
   // hard coded, and reloads every time through the loop -- that way don't
   // need to save any regs used by core loop (will see if this really works)
volatile CASQueueStruc  *_VMSWorkQ;

//==========================
void
VMS__init();

void
VMS__start();

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

inline void
VMS__send_sem_request( void *semReqData, VirtProcr *callingPr );

void
VMS__suspend_processor( VirtProcr *callingPr );

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

typedef unsigned long long TSCount;

#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();

int numProcrsCreated;

#endif	/* _VMS_H */

