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

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

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

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;
 }
ThdParams;

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


struct _VirtProcr
 {
   void       *stackPtr;
   void       *framePtr;
   void       *nextInstrPt;
   void       *coreLoopStartPt;  //allows proto-runtime to be linked later

   void       *initialData;

   SchedSlot  *schedSlot;
   SlaveReqst *requests;

   void       *semanticData;
 };


//When optimize make a separate flat array in here for each flag in SchedSlot
//So that polling done flags is fast..  not sure even worth it, though..
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
 }
MasterEnv;



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

   SlaveReqst  *nextRequest;
 };


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


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


HANDLE      coreLoopThds[ NUM_CORES ];  //windows handle to thread
ThdParams     *thdParams[ NUM_CORES ];
DWORD             thdIds[ NUM_CORES ];

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 QueueStruc    *_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 );


#endif	/* _VMS_H */

