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

#ifndef _Vthread_H
#define	_Vthread_H

#define _LANG_NAME_ "Vthread"

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


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


//===========================================================================
   //turn on the counter measurements of language overhead -- comment to turn off
#define MEAS__TURN_ON_LANG_MEAS
#include "Vthread__Measurement.h"

#define INIT_NUM_MUTEX 10000
#define INIT_NUM_COND  10000

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

//===========================================================================
typedef struct _VthreadSemReq   VthdSemReq;
typedef void  (*PtrToAtomicFn )   ( void * ); //executed atomically in master
//===========================================================================


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

/*Semantic layer-specific data sent inside a request from lib called in app
 * to request handler called in MasterLoop
 */
enum VthreadReqType
 {
   make_mutex = 1,
   mutex_lock,
   mutex_unlock,
   make_cond,
   cond_wait,
   cond_signal,
   make_slaveVP,
   malloc_req,
   free_req,
   singleton_fn_start,
   singleton_fn_end,
   singleton_data_start,
   singleton_data_end,
   atomic,
   trans_start,
   trans_end
 };

struct _VthreadSemReq
 { enum VthreadReqType reqType;
   SlaveVP           *requestingSlv;
   int32                mutexIdx;
   int32                condIdx;

   void                *initData;
   TopLevelFnPtr       fnPtr;
   int32                coreToScheduleOnto;

   size_t                sizeToMalloc;
   void                *ptrToFree;

   int32              singletonID;
   VthdSingleton     *singleton;

   PtrToAtomicFn      fnToExecInMaster;
   void              *dataForFn;

   int32              transID;
 }
/* VthreadSemReq */;


typedef struct
 {
   SlaveVP      *SlvCurrentlyExecuting;
   PrivQueueStruc *waitingSlvQ;
 }
VthdTrans;


typedef struct
 {
   int32           mutexIdx;
   SlaveVP      *holderOfLock;
   PrivQueueStruc *waitingQueue;
 }
VthdMutex;


typedef struct
 {
   int32           condIdx;
   PrivQueueStruc *waitingQueue;
   VthdMutex       *partnerMutex;
 }
VthdCond;

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

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


typedef struct
 {
      //Standard stuff will be in most every semantic env
   PrivQueueStruc  **readySlvQs;
   int32             nextCoreToGetNewSlv;
   int32             primitiveStartTime;

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

   VthdCond        **condDynArray;
   PrivDynArrayInfo *condDynArrayInfo;

   void             *applicationGlobals;

                       //fix limit on num with dynArray
   VthdSingleton    fnSingletons[NUM_STRUCS_IN_SEM_ENV];

   VthdTrans        transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
 }
VthdSemEnv;

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

void
Vthread__init();

void
Vthread__init_Seq();

void
Vthread__init_Helper();


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

inline void
Vthread__create_seed_slaveVP_and_do_work( TopLevelFnPtr fn, void *initData );

inline SlaveVP *
Vthread__create_slaveVP_helper( TopLevelFnPtr fnPtr, void *initData,
                          VthdSemEnv *semEnv,    int32 coreToScheduleOnto );

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

inline SlaveVP *
Vthread__create_thread( TopLevelFnPtr fnPtr, void *initData,
                          SlaveVP *creatingSlv );

inline SlaveVP *
Vthread__create_thread_with_affinity( TopLevelFnPtr fnPtr, void *initData,
                          SlaveVP *creatingSlv,  int32  coreToScheduleOnto );

inline void
Vthread__dissipate_thread( SlaveVP *procrToDissipate );

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

inline void *
Vthread__give_globals();

//=======================
inline int32
Vthread__make_mutex( SlaveVP *animSlv );

inline void
Vthread__mutex_lock( int32 mutexIdx, SlaveVP *acquiringSlv );
                                                    
inline void
Vthread__mutex_unlock( int32 mutexIdx, SlaveVP *releasingSlv );


//=======================
inline int32
Vthread__make_cond( int32 ownedMutexIdx, SlaveVP *animSlv);

inline void
Vthread__cond_wait( int32 condIdx, SlaveVP *waitingSlv);

inline void *
Vthread__cond_signal( int32 condIdx, SlaveVP *signallingSlv );


//=======================
void
Vthread__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
Vthread__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
Vthread__start_data_singleton( VthdSingleton *singelton, SlaveVP *animSlv );

void
Vthread__end_data_singleton( VthdSingleton *singleton, SlaveVP *animSlv );

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

void
Vthread__start_transaction( int32 transactionID, SlaveVP *animSlv );

void
Vthread__end_transaction( int32 transactionID, SlaveVP *animSlv );



//=========================  Internal use only  =============================
inline void
Vthread__Request_Handler( SlaveVP *requestingSlv, void *_semEnv );

inline SlaveVP *
Vthread__schedule_slaveVP( void *_semEnv, int coreNum );

//=======================
inline void
Vthread__free_semantic_request( VthdSemReq *semReq );

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

void *
Vthread__malloc( size_t sizeToMalloc, SlaveVP *animSlv );

void
Vthread__init();

void
Vthread__cleanup_after_shutdown();

void inline
resume_slaveVP( SlaveVP *procr, VthdSemEnv *semEnv );

#endif	/* _Vthread_H */

