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

#ifndef _VPThread_H
#define	_VPThread_H

#include "VMS/VMS.h"
#include "VMS/Queue_impl/PrivateQueue.h"
#include "VMS/DynArray/DynArray.h"


/*This header defines everything specific to the VPThread semantic plug-in
 */


//===========================================================================
#define INIT_NUM_MUTEX 10000
#define INIT_NUM_COND  10000

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

//===========================================================================
typedef struct _VPThreadSemReq   VPThdSemReq;
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 MasterLoop
 */
enum VPThreadReqType
 {
   make_mutex = 1,
   mutex_lock,
   mutex_unlock,
   make_cond,
   cond_wait,
   cond_signal,
   make_procr,
   malloc_req,
   free_req,
   singleton_start,
   singleton_end,
   atomic,
   trans_start,
   trans_end
 };

struct _VPThreadSemReq
 { enum VPThreadReqType reqType;
   VirtProcr           *requestingPr;
   int32                mutexIdx;
   int32                condIdx;

   void                *initData;
   VirtProcrFnPtr       fnPtr;
   int32                coreToScheduleOnto;

   int32                sizeToMalloc;
   void                *ptrToFree;

   int32              singletonID;
   void              *endJumpPt;

   PtrToAtomicFn      fnToExecInMaster;
   void              *dataForFn;

   int32              transID;
 }
/* VPThreadSemReq */;


typedef struct
 {
   VirtProcr      *VPCurrentlyExecuting;
   PrivQueueStruc *waitingVPQ;
 }
VPThdTrans;

typedef struct
 {
   int32           hasBeenStarted;
   int32           hasFinished;
   void           *endInstrAddr;
   PrivQueueStruc *waitQ;
 }
VPThdSingleton;

typedef struct
 {
   int32           mutexIdx;
   VirtProcr      *holderOfLock;
   PrivQueueStruc *waitingQueue;
 }
VPThdMutex;


typedef struct
 {
   int32           condIdx;
   PrivQueueStruc *waitingQueue;
   VPThdMutex       *partnerMutex;
 }
VPThdCond;

typedef struct _TransListElem TransListElem;
struct _TransListElem
 {
   int32          transID;
   TransListElem *nextTrans;
 };
//TransListElem

typedef struct
 {
   int32          highestTransEntered;
   TransListElem *lastTransEntered;
 }
VPThdSemData;


typedef struct
 {
      //Standard stuff will be in most every semantic env
   PrivQueueStruc  **readyVPQs;
   int32             numVirtPr;
   int32             nextCoreToGetNewPr;
   int32             primitiveStartTime;

      //Specific to this semantic layer
   VPThdMutex      **mutexDynArray;
   PrivDynArrayInfo *mutexDynArrayInfo;

   VPThdCond       **condDynArray;
   PrivDynArrayInfo *condDynArrayInfo;

   void             *applicationGlobals;

                       //fix limit on num with dynArray
   VPThdSingleton    singletons[NUM_STRUCS_IN_SEM_ENV];
   void             *singletonEndInstrAddr;

   VPThdTrans        transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
 }
VPThdSemEnv;


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

inline void
VPThread__create_seed_procr_and_do_work( VirtProcrFnPtr fn, void *initData );

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

inline VirtProcr *
VPThread__create_thread( VirtProcrFnPtr fnPtr, void *initData,
                          VirtProcr *creatingPr );

inline VirtProcr *
VPThread__create_thread_with_affinity( VirtProcrFnPtr fnPtr, void *initData,
                          VirtProcr *creatingPr,  int32  coreToScheduleOnto );

inline void
VPThread__dissipate_thread( VirtProcr *procrToDissipate );

//=======================
inline void
VPThread__set_globals_to( void *globals );

inline void *
VPThread__give_globals();

//=======================
inline int32
VPThread__make_mutex( VirtProcr *animPr );

inline void
VPThread__mutex_lock( int32 mutexIdx, VirtProcr *acquiringPr );
                                                    
inline void
VPThread__mutex_unlock( int32 mutexIdx, VirtProcr *releasingPr );


//=======================
inline int32
VPThread__make_cond( int32 ownedMutexIdx, VirtProcr *animPr);

inline void
VPThread__cond_wait( int32 condIdx, VirtProcr *waitingPr);

inline void *
VPThread__cond_signal( int32 condIdx, VirtProcr *signallingPr );


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

void
VPThread__end_singleton( int32 singletonID, VirtProcr *animPr );

inline void
VPThread__start_singleton( int32 singletonID, VirtProcr *animPr );

void
VPThread__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
                                         void *data, VirtProcr *animPr );

void
VPThread__start_transaction( int32 transactionID, VirtProcr *animPr );

void
VPThread__end_transaction( int32 transactionID, VirtProcr *animPr );



//=========================  Internal use only  =============================
inline void
VPThread__Request_Handler( VirtProcr *requestingPr, void *_semEnv );

inline VirtProcr *
VPThread__schedule_virt_procr( void *_semEnv, int coreNum );

//=======================
inline void
VPThread__free_semantic_request( VPThdSemReq *semReq );

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

void
VPThread__init();

void
VPThread__cleanup_after_shutdown();

#endif	/* _VPThread_H */

