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

#ifndef _VOMP_H
#define	_VOMP_H

#include "Queue_impl/PrivateQueue.h"
#include "Hash_impl/PrivateHash.h"
#include "VMS_impl/VMS.h"
#include "dependency.h"


//===========================================================================
#define NUM_STRUCS_IN_SEM_ENV 1000

   //This is hardware dependent -- it's the number of cycles of scheduling
   // overhead -- if a work unit is fewer than this, it is better being
   // combined sequentially with other work
   //This value depends on both VMS overhead and VOMP's plugin.  At some point
   // it will be derived by perf-counter measurements during init of VOMP
#define MIN_WORK_UNIT_CYCLES 20000

//===========================================================================
/*This header defines everything specific to the VOMP semantic plug-in
 */
typedef struct _VOMPSemReq   VOMPSemReq;
typedef void  (*PtrToAtomicFn )   ( void * ); //executed atomically in master
//===========================================================================

/*Semantic layer-specific data sent inside a request from lib called in app
 * to request handler called in AnimationMaster
 */

typedef struct
 {
   SlaveVP      *VPCurrentlyExecuting;
   PrivQueueStruc *waitingVPQ;
 }
VOMPTrans;

/*WARNING: assembly hard-codes position of endInstrAddr as first field
 */
typedef struct
 {
   void           *endInstrAddr;
   int32           hasBeenStarted;
   int32           hasFinished;
   PrivQueueStruc *waitQ;
 }
VOMPSingleton;

enum VOMPReqType
 {
   send_type = 1,
   send_from_to,
   receive_any,    //order and grouping matter -- send before receive
   receive_type,   // and receive_any first of the receives -- Handlers
   receive_from_to,// rely upon this ordering of enum
   transfer_to,
   transfer_out,
   malloc_req,
   free_req,
   singleton_fn_start,
   singleton_fn_end,
   singleton_data_start,
   singleton_data_end,
   atomic,
   trans_start,
   trans_end
 };

struct _VOMPSemReq
 { enum VOMPReqType    reqType;
   SlaveVP         *sendPr;
   SlaveVP         *receivePr;
   int32              msgType;
   void              *msg;
   VOMPSemReq         *nextReqInHashEntry;

   void              *initData;
   TopLevelFnPtr     fnPtr;
   int32              coreToAssignOnto;

   int32              sizeToMalloc;
   void              *ptrToFree;

   int32              singletonID;
   VOMPSingleton     **singletonPtrAddr;

   PtrToAtomicFn      fnToExecInMaster;
   void              *dataForFn;

   int32              transID;
 }
/* VOMPSemReq */;


typedef struct
 {
   PrivQueueStruc **readyVPQs;
   HashTable       *commHashTbl;
   int32            numSlaveVP;
   int32            nextCoreToGetNewPr;
   int32            primitiveStartTime;

                       //fix limit on num with dynArray
   VOMPSingleton     fnSingletons[NUM_STRUCS_IN_SEM_ENV];
   VOMPTrans         transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
   
   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   ListOfArrays* unitList;
   ListOfArrays* ctlDependenciesList;
   ListOfArrays* commDependenciesList;
   NtoN** ntonGroups;
   PrivDynArrayInfo* ntonGroupsInfo;
   ListOfArrays* dynDependenciesList;
   Unit last_in_slot[NUM_CORES * NUM_ANIM_SLOTS];
   ListOfArrays* hwArcs;
   #endif

   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
   ListOfArrays* counterList[NUM_CORES];
   #endif
   SlaveVP* idlePr[NUM_CORES][NUM_ANIM_SLOTS];
   int shutdownInitiated;
 }
VOMPSemEnv;


typedef struct _TransListElem TransListElem;
struct _TransListElem
 {
   int32          transID;
   TransListElem *nextTrans;
 };
//TransListElem
 
typedef struct
 {
   int32          highestTransEntered;
   TransListElem *lastTransEntered;
 }
VOMPSemData;
 
//===========================================================================

void
VOMP__create_seed_procr_and_do_work( TopLevelFnPtr fn, void *initData );

int32
VOMP__giveMinWorkUnitCycles( float32 percentOverhead );

void
VOMP__start_primitive();

int32
VOMP__end_primitive_and_give_cycles();

int32
VOMP__giveIdealNumWorkUnits();

int32
VOMP__give_number_of_cores_to_schedule_onto();

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

void
VOMP__init();

void
VOMP__cleanup_after_shutdown();

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

  SlaveVP *
VOMP__create_procr_with( TopLevelFnPtr fnPtr, void *initData,
                          SlaveVP *creatingSlv );

  SlaveVP *
VOMP__create_procr_with_affinity( TopLevelFnPtr fnPtr,    void *initData,
                            SlaveVP *creatingPr, int32 coreToAssignOnto);

void
VOMP__dissipate_procr( SlaveVP *procrToDissipate );

//=======================
void *
VOMP__malloc_to( int numBytes, SlaveVP *ownerSlv );

void
VOMP__free( void *ptrToFree, SlaveVP *owningSlv );

void
VOMP__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerPr,
                                                    SlaveVP *newOwnerSlv );
                                                    
void
VOMP__add_ownership_by_to( SlaveVP *newOwnerPr, void *data );

void
VOMP__remove_ownership_by_from( SlaveVP *loserPr, void *dataLosing );

void
VOMP__transfer_ownership_to_outside( void *dataToTransferOwnershipOf );



//=======================
void
VOMP__send_of_type_to( SlaveVP *sendPr, void *msg, const int type,
                        SlaveVP *receivePr);

void
VOMP__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr);

void *
VOMP__receive_type_to( const int type, SlaveVP *receiveSlv );

void *
VOMP__receive_from_to( SlaveVP *sendPr, SlaveVP *receiveSlv );


//======================= Concurrency Stuff ======================
void
VOMP__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
VOMP__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
VOMP__start_data_singleton( VOMPSingleton **singeltonAddr, SlaveVP *animSlv );

void
VOMP__end_data_singleton( VOMPSingleton **singletonAddr, SlaveVP *animSlv );

void
VOMP__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
                                    void *data, SlaveVP *animSlv );

void
VOMP__start_transaction( int32 transactionID, SlaveVP *animSlv );

void
VOMP__end_transaction( int32 transactionID, SlaveVP *animSlv );


//=========================  Internal use only  =============================
void
VOMP__Request_Handler( SlaveVP *requestingPr, void *_semEnv );

SlaveVP *
VOMP__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot );

SlaveVP*
VOMP__create_procr_helper( TopLevelFnPtr fnPtr, void *initData,
                          VOMPSemEnv *semEnv,    int32 coreToAssignOnto );

//=====================  Measurement of Lang Overheads  =====================
#include "VOMP_Measurement.h"

//===========================================================================
#endif	/* _VOMP_H */

