VSs.DevelopConstructs History

Hide minor edits - Show changes to output - Cancel

July 05, 2012, at 07:09 PM by 24.130.186.152 -
Changed lines 87-114 from:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
to:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );

!!!Send-receive constructs

inline int32 *
VSs__create_taskID_of_size( int32 numInts, SlaveVP *animSlv );

void
VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID,
SlaveVP *animSlv);


inline int32 *
VSs__give_self_taskID( SlaveVP *animSlv );

void
VSs__send_of_type_to( void *msg, const int32 type, int32 *receiverID,
SlaveVP *senderSlv );

void
VSs__send_from_to( void *msg, int32 *senderID, int32 *receiverID, SlaveVP *senderSlv );

void *
VSs__receive_type_to( const int32 type, int32* receiverID, SlaveVP *receiverSlv );

void *
VSs__receive_from_to( int32 *senderID, int32 *receiverID, SlaveVP *receiverSlv );
July 05, 2012, at 05:57 PM by 24.130.186.152 -
Changed line 1 from:
See the VSs header file for the exact details of these constructs.
to:
!!VSs structures, types, and constructs
July 05, 2012, at 05:57 PM by 24.130.186.152 -
July 05, 2012, at 05:56 PM by 24.130.186.152 -
Changed line 30 from:
This creates a new slave virtual processor, and gives the code to execute. Which core the VP is animated by is indeterminate and may change.
to:
This creates a new slave virtual processor, and gives the code to execute. Which core the VP is animated by is indeterminate and may change. The TopLevelFnPtr specifies that the top level function receive a SlaveVP pointer as one of its arguments. This pointer is generated by the VSs runtime and passed in to the function. It points to the actual virtual processor that is animating that function call. This pointer is required in all other VSs calls, so it must be passed around.
Added line 44:
This creates a task, rather than a virtual processor. This difference is one of context and expected longevity. A task has no pre-existing stack context, and normally does not suspend. Rather, a task is seen as a self-contained unit of work that runs to completion. However, in order to increase the flexibility of VSs, to capture a wider variety of applications, VSs tasks are able to execute sends and receives, as well as a variety of other synchronization constructs seen below. The function executed as the behavior of a task must have the same signature as a VP top level function (and is passed into this task creator via the task type structure). The arguments to the task are passed inside a structure, that the task must cast to an application-defined structure. The arguments are copied inside the runtime, so the arguments structure can be reused to create many tasks, assigning new values for each one.
Changed line 48 from:
to:
This is mandatory, and must be executed at some point within the task code. Every path that ends task code must have this as the last statement. IE, "return" or simply encountering the last } must never be reached without executing this first.
Changed lines 52-53 from:
//=======================
to:
!!!Malloc and Free
Due to a "feature" of Linux's threads, VMS, and thus VSs is forced to implement its own malloc and free system. Direct calls to malloc and free must be replaced with VSs__malloc and VSs__free in order to prevent segfaults inside Linux's implementation.
Deleted lines 57-58:

//=======================
July 05, 2012, at 05:40 PM by 24.130.186.152 -
Added lines 23-24:
!!VSs constructs
This is used inside the "border crossing" function, when transition from normal C into VSs. It creates the first virtual processor that exists within the VSs program. This seed VP then creates task-stubs and possibly other VPs, by using the creation constructs (below).
Changed lines 28-30 from:
to:
!!!Creation constructs

This creates a new slave virtual processor, and gives the code to execute. Which core the VP is animated by is indeterminate and may change.
Changed lines 32-34 from:
VSs__create_slave_with( TopLevelFnPtr fnPtr, void *initData,
SlaveVP *creatingSlv );
to:
VSs__create_slave( TopLevelFnPtr fnPtr, void *initData,
SlaveVP *creatingSlv );

This also creates a slave VP, but pins it to a specific core.
Added line 40:
This is a required call that must be made from within the code given during creation of a slave VP. It can be called from anyplace, but will immediately stop execution of the VP's code and make the VP disappear. The slaveToDissipate must be the slave that is animating the code that makes this call (IE, the slave that was passed in to the top level function).
Added lines 44-50:
int32
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);


void
VSs__end_task( SlaveVP *animSlv );
Changed lines 58-62 from:
//=======================
int32
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);
to:
//=======================


!!!Concurrency Constructs
These affect the virtual processor that is currently animating a task. They are all used to synchronize the use of shared variables that is not controlled by the IN, OUT, and INOUT method. These allow more flexibility in the pattern of communication among tasks and virtual processors that are not animating tasks.

VSs__start_fn_singleton and VSs__end_fn_singleton are used when many tasks or virtual processors need a section of code to be executed by the time they start, but it must only be executed by one of them. This construct allows the first to get that point in the code to be the one to execute it, and all the others just skip that section of code. Without this singleton construct, a barrier would have to be used to be sure all the tasks and/or virtual processors had reached this point, or else some custom use of locks. However, in practice, the coder often wishes to group executions by some code-specific thing, and creates an ID for each group:
Deleted lines 65-73:
VSs__end_task( SlaveVP *animSlv );



!!!Concurrency Constructs
These affect the virtual processor that is currently animating a task. They are all used to synchronize the use of shared variables that is not controlled by the IN, OUT, and INOUT method. These allow more flexibility in the pattern of communication among tasks and virtual processors that are not animating tasks.

VSs__start_fn_singleton and VSs__end_fn_singleton are used when many tasks or virtual processors need a section of code to be executed by the time they start, but it must only be executed by one of them. This construct allows the first to get that point in the code to be the one to execute it, and all the others just skip that section of code. Without this singleton construct, a barrier would have to be used to be sure all the tasks and/or virtual processors had reached this point, or else some custom use of locks. However, in practice, the coder often wishes to group executions by some code-specific thing, and creates an ID for each group:
void
Changed line 88 from:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
to:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
July 05, 2012, at 05:28 PM by 24.130.186.152 -
Added line 72:
This executes a function atomically (PtrToAtomicFn was mentioned above):
Added line 77:
VSs__start_transaction and VSs__end_transaction are classic nested transactions. However, the implementation is not speculative, so it doesn't have all the performance advantages of a transactional memory implementation. Rather, it is provided in order to express dependencies among sections of code that access shared variables. They increase the variety of dependencies that can be expressed:
Changed line 82 from:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
to:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
July 05, 2012, at 05:22 PM by 24.130.186.152 -
Added line 58:
VSs__start_fn_singleton and VSs__end_fn_singleton are used when many tasks or virtual processors need a section of code to be executed by the time they start, but it must only be executed by one of them. This construct allows the first to get that point in the code to be the one to execute it, and all the others just skip that section of code. Without this singleton construct, a barrier would have to be used to be sure all the tasks and/or virtual processors had reached this point, or else some custom use of locks. However, in practice, the coder often wishes to group executions by some code-specific thing, and creates an ID for each group:
Added line 65:
VSs__start_data_singleton and VSs__end_data_singleton are also placed in-line in the code, except they protect a particular data structure rather than a section of code. The address of the data should only have the protected code executed on it once. In use, the address of a target data structure is given to the singleton construct, and then the protected code is only executed on that address one time:
Changed line 80 from:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
to:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
July 05, 2012, at 05:10 PM by 24.130.186.152 -
Changed lines 12-38 from:
typedef struct
{
VSsTaskFnPtr fn;
int32 numTotalArgs;//the number of inputs to function
int32 numCtldArgs;//how many of those inputs have dependencies
int32 *argTypes;
//says IN, OUT, INOUT, or not involved in dependencies, for each argument (is an array)
int32 *argSizes;
//size of the data structure of each argument.. used for detecting overlap (is an array)
int32 sizeOfArgs; //used when copying the array of arguments, says the size
, in bytes, of the structure passed to VSs__submit_task() (below)
}
VSsTaskType;


void
VSs__create_seed_slave_and_do_work( TopLevelFnPtr fn, void *initData );


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

SlaveVP *
VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
SlaveVP *creatingSlv, int32 coreToAssignOnto);

void
VSs__dissipate_slave( SlaveVP *slaveToDissipate );
to:
typedef struct
{
VSsTaskFnPtr fn;
int32 numTotalArgs;//the number of inputs to function
int32 numCtldArgs;//how many of those inputs have dependencies
int32 *argTypes; //says IN, OUT, INOUT, or not involved in dependencies, for each argument (is an array)
int32 *argSizes; //size of the data structure of each argument.. used for detecting overlap
(is an array)
int32 sizeOfArgs; //
used when copying the array of arguments, says the size, in bytes, of the structure passed to VSs__submit_task() (below)
}
VSsTaskType;

void
VSs__create_seed_slave_and_do_work( TopLevelFnPtr fn
, void *initData );


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

SlaveVP *
VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr,
void *initData,
SlaveVP *creatingSlv, int32 coreToAssignOnto);

void
VSs__dissipate_slave( SlaveVP *slaveToDissipate );
Changed lines 46-69 from:
int32
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);


void
VSs__end_task( SlaveVP *animSlv );



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

void
VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv );

void
VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv );

void
VSs__animate_short_fn_in_isolation(
PtrToAtomicFn ptrToFnToExecInMaster,
to:
int32
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);


void
VSs__end_task( SlaveVP *animSlv );



!!!
Concurrency Constructs
These affect the virtual processor that is currently animating a task. They are all used to synchronize the use of shared variables that is not controlled by the IN, OUT, and INOUT method. These allow more flexibility in the pattern of communication among tasks and virtual processors that are not animating tasks.

void
VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv );

void
VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv );

void
VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
Changed lines 74-78 from:
void
VSs__start_transaction( int32 transactionID, SlaveVP *animSlv );

void
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
to:
void
VSs__start_transaction( int32 transactionID, SlaveVP *animSlv );

void
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
July 05, 2012, at 05:05 PM by 24.130.186.152 -
Deleted line 0:
Changed lines 6-184 from:
typedef void (*PtrToAtomicFn ) ( void * ); //executed atomically in master

#define IN 1
#define OUT 2
#define INOUT 2

#define READER 1
#define WRITER 2

typedef struct
{
VSsTaskFnPtr fn;
int32 numTotalArgs;//the number of inputs to function
int32 numCtldArgs;//how many of args have dependencies
int32 *argTypes; //says reader, writer, or non-ctld
int32 *argSizes; //for detecting overlap
int32 sizeOfArgs; //for memcpy of args struct
}
VSsTaskType;


typedef struct
{
bool32 hasEnabledNonFinishedWriter;
int32 numEnabledNonDoneReaders;
PrivQueueStruc *waitersQ;
}
VSsPointerEntry;

typedef struct
{
void **args; //ctld args must come first, as ptrs
VSsTaskType *taskType;
int32 numBlockingProp;
SlaveVP *slaveAssignedTo;
VSsPointerEntry **ptrEntries;
}
VSsTaskStub;

typedef struct
{
VSsTaskStub *taskStub;
int32 argNum;
int32 isReader;
}
VSsTaskStubCarrier;


typedef struct
{
int32 type;
VSsTaskStub *taskStub;
}
VSsWaiterCarrier;

/*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;
}
VSsTrans;

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

enum VSsReqType
{
submit_task = 1,
end_task,
create_slave,
create_slave_w_aff,
dissipate_slave,
//===============================
malloc_req,
free_req,
singleton_fn_start,
singleton_fn_end,
singleton_data_start,
singleton_data_end,
atomic,
trans_start,
trans_end
};

struct _VSsSemReq
{ enum VSsReqType reqType;
SlaveVP *callingSlv;
VSsTaskType *taskType;
void *args;
VSsTaskStub *taskStub;

TopLevelFnPtr fnPtr;
void *initData;
int32 coreToAssignOnto;

int32 sizeToMalloc;
void *ptrToFree;

int32 singletonID;
VSsSingleton **singletonPtrAddr;

PtrToAtomicFn fnToExecInMaster;
void *dataForFn;

int32 transID;
}
/* VSsSemReq */;


typedef struct
{
PrivQueueStruc **readyVPQs;
PrivQueueStruc *taskReadyQ; //Q: shared or local?
HashTable *argPtrHashTbl;
int32 numSlaveVP;
int32 nextCoreToGetNewSlv;
int32 primitiveStartTime;

//fix limit on num with dynArray
VSsSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV];
VSsTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV];

bool32 *coreIsDone;
int32 numCoresDone;

#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* idleSlv[NUM_CORES][NUM_ANIM_SLOTS];
int shutdownInitiated;
}
VSsSemEnv;


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

typedef struct
{
int32 highestTransEntered;
TransListElem *lastTransEntered;
bool32 needsTaskAssigned;
VSsTaskStub *taskStub;
}
VSsSemData;

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

void
VSs__create_seed_slave_and_do_work( TopLevelFnPtr fn, void *initData );
to:
PtrToAtomicFn is the type for functions that are executed via the VSs__animate_short_fn_in_isolation construct (below)

IN, OUT, and INOUT are used to specify the way a task uses each of its shared variables


VSsTaskType is the structure that holds information about a VSs task. One of these must be created and filled in for each kind of task created within a VSs (StarSs) program. It says how many arguments the task needs passed to it, how many of those are shared variables involved in dependencies with other tasks, the type of each, the size of each, and the size of the structure passed to the VSs__submit_task. Here is the full structure, with detailed comments on each entry:
typedef struct
{
VSsTaskFnPtr fn;
int32 numTotalArgs;//the number of inputs to function
int32 numCtldArgs;//how many of those inputs have dependencies
int32 *argTypes; //says IN, OUT, INOUT, or not involved in dependencies, for each argument (is an array)
int32 *argSizes; //size of the data structure of each argument.. used for detecting overlap (is an array)
int32 sizeOfArgs; //used when copying the array of arguments, says the size, in bytes, of the structure passed to VSs__submit_task() (below)
}
VSsTaskType;


void
VSs__create_seed_slave_and_do_work( TopLevelFnPtr fn, void *initData );


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

SlaveVP *
VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
SlaveVP *creatingSlv, int32 coreToAssignOnto);

void
VSs__dissipate_slave( SlaveVP *slaveToDissipate );

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

void *
VSs__malloc( int32 numBytes, SlaveVP *callingSlave )

VSs__free( void *ptrToFree, SlaveVP *callingSlave )

//=======================
Changed lines 48-49 from:
VSs__giveMinWorkUnitCycles( float32 percentOverhead );
to:
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);
Changed lines 52-64 from:
VSs__start_primitive();

int32
VSs__end_primitive_and_give_cycles();

int32
VSs__giveIdealNumWorkUnits();

int32
VSs__give_number_of_cores_to_schedule_onto();

//=======================
to:
VSs__end_task( SlaveVP *animSlv );



//======================= Concurrency Stuff ======================
Changed lines 58-59 from:
VSs__init();
to:
VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );
Changed lines 61-72 from:
VSs__cleanup_after_shutdown();

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

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

SlaveVP *
VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
SlaveVP *creatingSlv, int32 coreToAssignOnto
);
to:
VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );
Changed lines 64-76 from:
VSs__dissipate_slave( SlaveVP *slaveToDissipate );

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

VSs__malloc( numBytes, callingSlave )

VSs__free(ptrToFree, callingSlave )

//=======================
int32
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);
to:
VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv );
Changed lines 67-71 from:
VSs__end_task( SlaveVP *animSlv );



//======================= Concurrency Stuff ======================
to:
VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv );
Changed lines 70-71 from:
VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );
to:
VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
void *data
, SlaveVP *animSlv );
Changed lines 74-75 from:
VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );
to:
VSs__start_transaction( int32 transactionID, SlaveVP *animSlv );
Changed lines 77-90 from:
VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv );

void
VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv );

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

void
VSs__start_transaction( int32 transactionID, SlaveVP *animSlv );

void

VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
to:
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );
July 05, 2012, at 04:44 PM by 24.130.186.152 -
Added lines 1-259:

See the VSs header file for the exact details of these constructs.

!!!Types and structs

VSsTaskFnPtr is the type for variables that hold a pointer to a function that encodes the behavior of a task. Such functions have a fixed signature.
typedef void (*PtrToAtomicFn ) ( void * ); //executed atomically in master

#define IN 1
#define OUT 2
#define INOUT 2

#define READER 1
#define WRITER 2

typedef struct
{
VSsTaskFnPtr fn;
int32 numTotalArgs;//the number of inputs to function
int32 numCtldArgs;//how many of args have dependencies
int32 *argTypes; //says reader, writer, or non-ctld
int32 *argSizes; //for detecting overlap
int32 sizeOfArgs; //for memcpy of args struct
}
VSsTaskType;


typedef struct
{
bool32 hasEnabledNonFinishedWriter;
int32 numEnabledNonDoneReaders;
PrivQueueStruc *waitersQ;
}
VSsPointerEntry;

typedef struct
{
void **args; //ctld args must come first, as ptrs
VSsTaskType *taskType;
int32 numBlockingProp;
SlaveVP *slaveAssignedTo;
VSsPointerEntry **ptrEntries;
}
VSsTaskStub;

typedef struct
{
VSsTaskStub *taskStub;
int32 argNum;
int32 isReader;
}
VSsTaskStubCarrier;


typedef struct
{
int32 type;
VSsTaskStub *taskStub;
}
VSsWaiterCarrier;

/*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;
}
VSsTrans;

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

enum VSsReqType
{
submit_task = 1,
end_task,
create_slave,
create_slave_w_aff,
dissipate_slave,
//===============================
malloc_req,
free_req,
singleton_fn_start,
singleton_fn_end,
singleton_data_start,
singleton_data_end,
atomic,
trans_start,
trans_end
};

struct _VSsSemReq
{ enum VSsReqType reqType;
SlaveVP *callingSlv;
VSsTaskType *taskType;
void *args;
VSsTaskStub *taskStub;

TopLevelFnPtr fnPtr;
void *initData;
int32 coreToAssignOnto;

int32 sizeToMalloc;
void *ptrToFree;

int32 singletonID;
VSsSingleton **singletonPtrAddr;

PtrToAtomicFn fnToExecInMaster;
void *dataForFn;

int32 transID;
}
/* VSsSemReq */;


typedef struct
{
PrivQueueStruc **readyVPQs;
PrivQueueStruc *taskReadyQ; //Q: shared or local?
HashTable *argPtrHashTbl;
int32 numSlaveVP;
int32 nextCoreToGetNewSlv;
int32 primitiveStartTime;

//fix limit on num with dynArray
VSsSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV];
VSsTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV];

bool32 *coreIsDone;
int32 numCoresDone;

#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* idleSlv[NUM_CORES][NUM_ANIM_SLOTS];
int shutdownInitiated;
}
VSsSemEnv;


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

typedef struct
{
int32 highestTransEntered;
TransListElem *lastTransEntered;
bool32 needsTaskAssigned;
VSsTaskStub *taskStub;
}
VSsSemData;

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

void
VSs__create_seed_slave_and_do_work( TopLevelFnPtr fn, void *initData );

int32
VSs__giveMinWorkUnitCycles( float32 percentOverhead );

void
VSs__start_primitive();

int32
VSs__end_primitive_and_give_cycles();

int32
VSs__giveIdealNumWorkUnits();

int32
VSs__give_number_of_cores_to_schedule_onto();

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

void
VSs__init();

void
VSs__cleanup_after_shutdown();

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

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

SlaveVP *
VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
SlaveVP *creatingSlv, int32 coreToAssignOnto);

void
VSs__dissipate_slave( SlaveVP *slaveToDissipate );

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

VSs__malloc( numBytes, callingSlave )

VSs__free(ptrToFree, callingSlave )

//=======================
int32
VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv);


void
VSs__end_task( SlaveVP *animSlv );



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

void
VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );

void
VSs__start_data_singleton( VSsSingleton **singeltonAddr, SlaveVP *animSlv );

void
VSs__end_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv );

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

void
VSs__start_transaction( int32 transactionID, SlaveVP *animSlv );

void
VSs__end_transaction( int32 transactionID, SlaveVP *animSlv );