# HG changeset patch # User Me # Date 1284200703 25200 # Node ID e123acb162f05306170f2b8e39ef51bbda8acb47 Initial add of MeasVMS semantic layer Works, but has weird suspend-time histogram -- will try moving hist updates out of coreloop & out of master and into the app diff -r 000000000000 -r e123acb162f0 MeasVMS.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MeasVMS.h Sat Sep 11 03:25:03 2010 -0700 @@ -0,0 +1,138 @@ +/* + * Copyright 2009 OpenSourceStewardshipFoundation.org + * Licensed under GNU General Public License version 2 + * + * Author: seanhalle@yahoo.com + * + */ + +#ifndef _MeasVMS_H +#define _MeasVMS_H + +#include "VMS/Queue_impl/PrivateQueue.h" +#include "VMS/Hash_impl/PrivateHash.h" +#include "VMS/Histogram/Histogram.h" +#include "VMS/VMS.h" + +/*This header defines everything specific to the MeasVMS semantic plug-in + */ +typedef struct _MeasVMSSemReq MeasVMSSemReq; + + +/*Semantic layer-specific data sent inside a request from lib called in app + * to request handler called in MasterLoop + */ +enum MeasVMSReqType + { + 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 + }; + +struct _MeasVMSSemReq + { enum MeasVMSReqType reqType; + VirtProcr *sendPr; + VirtProcr *receivePr; + int32 msgType; + void *msg; + MeasVMSSemReq *nextReqInHashEntry; + } +/* MeasVMSSemReq */; + +typedef struct + { + PrivQueueStruc **readyVPQs; + int numVirtPr; + int numTimesCalled; + int firstOfTwo; + int nextCoreToGetNewPr; + + Histogram **addrOfSuspHist; + Histogram **addrOfMasterHist; + } +MeasVMSSemEnv; + + +typedef struct + { + Histogram **suspHistAddr; + Histogram **masterHistAddr; + } +PairOfHistAddresses; + +//=========================================================================== + +void +MeasVMS__create_seed_procr_and_do_work( VirtProcrFnPtr fn, void *initData ); + +//======================= + +void +MeasVMS__init(); + +void +MeasVMS__cleanup_after_shutdown(); + +//======================= + +inline VirtProcr * +MeasVMS__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, + VirtProcr *creatingPr ); + +void +MeasVMS__dissipate_procr( VirtProcr *procrToDissipate ); + +//======================= +void * +MeasVMS__malloc_size_to( int numBytes, VirtProcr *ownerPr ); + +void +MeasVMS__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, + VirtProcr *newOwnerPr ); + +void +MeasVMS__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ); + +void +MeasVMS__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ); + +void +MeasVMS__transfer_ownership_to_outside( void *dataToTransferOwnershipOf ); + + + +//======================= +void +MeasVMS__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, + VirtProcr *receivePr); + +void +MeasVMS__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr); + +void * +MeasVMS__receive_type_to( const int type, VirtProcr *receivePr ); + +void * +MeasVMS__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ); + + +//======================= + +void +MeasVMS__free_semantic_request( MeasVMSSemReq *semReq ); + + +//========================= Internal use only ============================= +void +MeasVMS__Request_Handler( VirtProcr *requestingPr, void *_semEnv ); + +VirtProcr * +MeasVMS__schedule_virt_procr( void *_semEnv, int coreNum ); + + +#endif /* _MeasVMS_H */ + diff -r 000000000000 -r e123acb162f0 MeasVMS_PluginFns.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MeasVMS_PluginFns.c Sat Sep 11 03:25:03 2010 -0700 @@ -0,0 +1,92 @@ +/* + * Copyright 2010 OpenSourceStewardshipFoundation + * + * Licensed under BSD + */ + +#include +#include +#include + +#include "VMS/Queue_impl/PrivateQueue.h" +#include "MeasVMS.h" + + +/*Sept 5, 2010: only measuring core loop for now -- to do this, have + * an AppVP that has a loop that suspends itself then measures the time + * from suspend to resume and updates a histogram, then suspends again. + * + *This request handler just queues up the same processor twice in a row -- + * the first will suspend, the second will resume and capture the time + * spent in the core loop between -- then it will suspend again, and there + * will be no more AppVPs in the queue, so the MasterVP will be animated + * by the core loop, and this request handler will be called again and + * do the same thing. + * + *It keeps a count of how many times it does this, and shutsdown when enough. + */ +void +MeasVMS__Request_Handler( VirtProcr *requestingPr, void *_semEnv ) + { MeasVMSSemEnv *semEnv; + + semEnv = (MeasVMSSemEnv *)_semEnv; + + //Cheating normal request handler behavior here -- putting two of the + // exact same virt procr into ready-queue at same time. Also breaking + // abstraction inside that virt procr by accessing the VP vars inside + // the application code. + + //NOTE: there are no requests attached to the AppVPs.. just do a fixed + // thing each time called, don't process any requests. + writePrivQ(requestingPr, semEnv->readyVPQs[requestingPr->coreAnimatedBy]); + writePrivQ(requestingPr, semEnv->readyVPQs[requestingPr->coreAnimatedBy]); + + semEnv->numTimesCalled += 1; + if( semEnv->numTimesCalled >= MEAS__NUM_TIMES_TO_RUN ) + { + #ifdef MEAS__TIME_STAMP_SUSP + *(semEnv->addrOfSuspHist) = _VMSMasterEnv->measSuspHist; + #endif + #ifdef MEAS__TIME_MASTER + *(semEnv->addrOfMasterHist) = _VMSMasterEnv->measMasterHist; + #endif + VMS__handle_shutdown_reqst( requestingPr ); + } + + } + +//=========================================================================== + + +/*For MeasVMS, thing s are a bit of a pain + */ +VirtProcr * +MeasVMS__schedule_virt_procr( void *_semEnv, int coreNum ) + { VirtProcr *schedPr; + MeasVMSSemEnv *semEnv; + + semEnv = (MeasVMSSemEnv *)_semEnv; + + schedPr = readPrivQ( semEnv->readyVPQs[coreNum] ); + + //Note, using a non-blocking queue -- it returns NULL if queue empty + if( schedPr == NULL ) return NULL; + + if( semEnv->firstOfTwo == TRUE ) + { + semEnv->firstOfTwo = FALSE; + schedPr->schedSlot->workIsDone = FALSE; //slot from second assign + schedPr->schedSlot->needsProcrAssigned = TRUE; + } + else + { + semEnv->firstOfTwo = TRUE; + //================================================================== + if( schedPr->schedSlot == NULL ) return schedPr; //seed pr first time + //================================================================== + schedPr->schedSlot->workIsDone = TRUE; //slot from first assign + } + + return schedPr; + } + diff -r 000000000000 -r e123acb162f0 MeasVMS_lib.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MeasVMS_lib.c Sat Sep 11 03:25:03 2010 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright 2010 OpenSourceStewardshipFoundation + * + * Licensed under BSD + */ + +#include +#include +#include + +#include "VMS/VMS.h" +#include "MeasVMS.h" +#include "VMS/Queue_impl/PrivateQueue.h" +#include "VMS/Hash_impl/PrivateHash.h" + + +//========================================================================== + +void +MeasVMS__init(); + +void +MeasVMS__init_Seq(); + +void +MeasVMS__init_Helper(); + + +//=========================================================================== + +/*This is the "border crossing" function -- the thing that crosses from the + * outside world, into the VMS_HW world. It initializes and starts up the + * VMS system, then creates one processor from the specified function and + * puts it into the readyQ. From that point, that one function is resp. + * for creating all the other processors, that then create others, and so + * forth. + *When all the processors, including the seed, have dissipated, then this + * function returns. The results will have been written by side-effect via + * pointers read from, or written into initData. + * + *NOTE: no Threads should exist in the outside program that might touch + * any of the data reachable from initData passed in to here + */ +void +MeasVMS__create_seed_procr_and_do_work( VirtProcrFnPtr fnPtr, void *initData ) + { MeasVMSSemEnv *semEnv; + VirtProcr *seedPr; + + #ifdef SEQUENTIAL + MeasVMS__init_Seq(); //debug sequential exe + #else + MeasVMS__init(); //normal multi-thd + #endif + + semEnv = _VMSMasterEnv->semanticEnv; + + //MeasVMS starts with one processor, which is put into initial environ, + // and which then calls create() to create more, thereby expanding work + seedPr = VMS__create_procr( fnPtr, initData ); + + seedPr->coreAnimatedBy = semEnv->nextCoreToGetNewPr++; + + writePrivQ( seedPr, semEnv->readyVPQs[seedPr->coreAnimatedBy] ); + semEnv->numVirtPr = 1; + + //============================= MEASUREMENT STUFF ======================== + PairOfHistAddresses *histCarrier = (PairOfHistAddresses *)initData; + + semEnv->addrOfSuspHist = histCarrier->suspHistAddr; + semEnv->addrOfMasterHist = histCarrier->masterHistAddr; + //======================================================================== + + + #ifdef SEQUENTIAL + VMS__start_the_work_then_wait_until_done_Seq(); //debug sequential exe + #else + VMS__start_the_work_then_wait_until_done(); //normal multi-thd + #endif + + MeasVMS__cleanup_after_shutdown(); + } + + +//=========================================================================== + +/*Initializes all the data-structures for a MeasVMS system -- but doesn't + * start it running yet! + * + * + *This sets up the semantic layer over the VMS system + * + *First, calls VMS_Setup, then creates own environment, making it ready + * for creating the seed processor and then starting the work. + */ +void +MeasVMS__init() + { + VMS__init(); + //masterEnv, a global var, now is partially set up by init_VMS + + MeasVMS__init_Helper(); + } + +void +MeasVMS__init_Seq() + { + VMS__init_Seq(); + //masterEnv, a global var, now is partially set up by init_VMS + + MeasVMS__init_Helper(); + } + +void +MeasVMS__init_Helper() + { MeasVMSSemEnv *semEnv; + PrivQueueStruc **readyVPQs; + int coreIdx; + + //Hook up the semantic layer's plug-ins to the Master virt procr + _VMSMasterEnv->requestHandler = &MeasVMS__Request_Handler; + _VMSMasterEnv->slaveScheduler = &MeasVMS__schedule_virt_procr; + + //create the semantic layer's environment (all its data) and add to + // the master environment + semEnv = malloc( sizeof( MeasVMSSemEnv ) ); + _VMSMasterEnv->semanticEnv = semEnv; + + //create the ready queue, hash tables used for pairing send to receive + // and so forth + //TODO: add hash tables for pairing sends with receives, and + // initialize the data ownership system + readyVPQs = malloc( NUM_CORES * sizeof(PrivQueueStruc *) ); + + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) + { + readyVPQs[ coreIdx ] = makePrivQ(); + } + + semEnv->numTimesCalled = 0; + semEnv->firstOfTwo = FALSE; + + semEnv->readyVPQs = readyVPQs; + } + + +/*Frees any memory allocated by MeasVMS__init() then calls VMS__shutdown + */ +void +MeasVMS__cleanup_after_shutdown() + { MeasVMSSemEnv *semanticEnv; + int coreIdx; + + semanticEnv = _VMSMasterEnv->semanticEnv; + + + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) + { + free( semanticEnv->readyVPQs[coreIdx]->startOfData ); + free( semanticEnv->readyVPQs[coreIdx] ); + } + free( semanticEnv->readyVPQs ); + + free( _VMSMasterEnv->semanticEnv ); + VMS__cleanup_after_shutdown(); + } + + +//=========================================================================== +