changeset 120:d4c881c7f03a Inter-Master Requests

Added fn to send inter-master requests, and cleaned up code
author Me@portablequad
date Sat, 03 Sep 2011 20:41:51 -0700
parents ac11b50220bd
children 11740002decf
files CoreLoop.c MasterLoop.c VMS.c VMS.h inter_VMS_request_handlers.h
diffstat 5 files changed, 121 insertions(+), 55 deletions(-) [+]
line diff
     1.1 --- a/CoreLoop.c	Tue Aug 30 21:55:04 2011 -0700
     1.2 +++ b/CoreLoop.c	Sat Sep 03 20:41:51 2011 -0700
     1.3 @@ -91,8 +91,8 @@
     1.4     readyToAnimateQ  = _VMSMasterEnv->readyToAnimateQs[thisCoresIdx];
     1.5  
     1.6     #ifdef USE_WORK_STEALING
     1.7 -      //Alg for work-stealing designed to make common case fast.  Comment
     1.8 -      // in stealer code explains.
     1.9 +      //protect access to readyToAnimateQ -- other cores also want access!
    1.10 +      //Alg makes common case fast.  Comment in stealer code explains.
    1.11     gate.preGateProgress++;
    1.12     if( gate.gateClosed )
    1.13      {    //now, set coreloop's progress, so stealer can see that core loop
    1.14 @@ -103,7 +103,7 @@
    1.15  
    1.16     currPr = (VirtProcr *) readVMSQ( readyToAnimateQ );
    1.17  
    1.18 -      //Set the coreloop's progress, so stealer can see it has made it out
    1.19 +      //Set coreloop's progress, so stealer can see this has made it out
    1.20        // of the protected area
    1.21     gate.exitProgress = gate.preGateProgress;
    1.22     #else
    1.23 @@ -112,7 +112,8 @@
    1.24  
    1.25     if( currPr != NULL ) _VMSMasterEnv->numMasterInARow[thisCoresIdx] = 0;
    1.26     else
    1.27 -    {
    1.28 +    { //no more Slaves, get master lock and switch to master Pr
    1.29 +	
    1.30        //============================= MEASUREMENT STUFF =====================
    1.31        #ifdef MEAS__TIME_MASTER_LOCK
    1.32        int32 startStamp, endStamp;
    1.33 @@ -120,17 +121,17 @@
    1.34        #endif
    1.35        //=====================================================================
    1.36        int tries = 0; int gotLock = 0;
    1.37 -      while( currPr == NULL ) //if queue was empty, enter get masterLock loop
    1.38 -       {    //queue was empty, so get master lock
    1.39 +      while( currPr == NULL ) 
    1.40 +       {    //didn't get lock, so keep trying
    1.41  
    1.42           gotLock = __sync_bool_compare_and_swap(&(_VMSMasterEnv->masterLock),
    1.43                                                            UNLOCKED, LOCKED );
    1.44           if( gotLock )
    1.45 -          {    //run own MasterVP -- jmps to coreLoops startPt when done
    1.46 +          {    //run own MasterVP
    1.47              currPr = _VMSMasterEnv->masterVPs[thisCoresIdx];
    1.48              if( _VMSMasterEnv->numMasterInARow[thisCoresIdx] > 1000 )
    1.49               {       DEBUG( dbgB2BMaster,"Many back to back MasterVPs\n");
    1.50 -               pthread_yield();
    1.51 +               pthread_yield();   //this core has no slaves to schedule..
    1.52               }
    1.53              _VMSMasterEnv->numMasterInARow[thisCoresIdx] += 1;
    1.54              break;  //end while -- have a VP to animate now
    1.55 @@ -152,7 +153,7 @@
    1.56      }
    1.57  
    1.58     
    1.59 -   switchToVP(currPr); //The VPs return in here
    1.60 +   switchToVP(currPr); //The VPs all return back to here
    1.61     flushRegisters();
    1.62     }//CoreLoop      
    1.63   }
    1.64 @@ -160,7 +161,7 @@
    1.65  
    1.66  void *
    1.67  terminateCoreLoop(VirtProcr *currPr){
    1.68 -   //first free shutdown VP that jumped here -- it first restores the
    1.69 +   //first free the shutdown VP that jumped here -- it first restores the
    1.70     // coreloop's stack, so addr of currPr in stack frame is still correct
    1.71     VMS__dissipate_procr( currPr );
    1.72     pthread_exit( NULL );
     2.1 --- a/MasterLoop.c	Tue Aug 30 21:55:04 2011 -0700
     2.2 +++ b/MasterLoop.c	Sat Sep 03 20:41:51 2011 -0700
     2.3 @@ -49,9 +49,7 @@
     2.4   *So VMS__init just births the master virtual processor same way it births
     2.5   * all the others -- then does any extra setup needed and puts it into the
     2.6   * work queue.
     2.7 - *However means have to make masterEnv a global static volatile the same way
     2.8 - * did with readyToAnimateQ in core loop.  -- for performance, put the
     2.9 - * jump to the core loop directly in here, and have it directly jump back.
    2.10 + *However means have to make masterEnv a global static volatile.
    2.11   *
    2.12   *
    2.13   *Aug 18, 2010 -- Going to a separate MasterVP for each core, to see if this
    2.14 @@ -60,7 +58,7 @@
    2.15   *
    2.16   *So, this function is coupled to each of the MasterVPs, -- meaning this
    2.17   * function can't rely on a particular stack and frame -- each MasterVP that
    2.18 - * animates this function has a different one.
    2.19 + * animates this function has a different stack.
    2.20   *
    2.21   *At this point, the masterLoop does not write itself into the queue anymore,
    2.22   * instead, the coreLoop acquires the masterLock when it has nothing to
    2.23 @@ -96,24 +94,17 @@
    2.24        //So, setup values about stack ptr, jmp pt and all that
    2.25     //masterPr->nextInstrPt = &&masterLoopStartPt;
    2.26  
    2.27 -
    2.28 -      //Note, got rid of writing the stack and frame ptr up here, because
    2.29 -      // only one
    2.30 -      // core can ever animate a given MasterVP, so don't need to communicate
    2.31 -      // new frame and stack ptr to the MasterVP storage before a second
    2.32 -      // version of that MasterVP can get animated on a different core.
    2.33 -      //Also got rid of the busy-wait.
    2.34 -
    2.35 -   
    2.36 -   //masterLoopStartPt:
    2.37 -   //The animating materVP suspends at end of this loop, then later resumes and
    2.38 -   // comes back here 
    2.39 -   while(1){
    2.40 +      //Sept 2011
    2.41 +      //Old code jumped directly to this point, but doesn't work on x64
    2.42 +	  // So, just make this an endless loop, and do assembly function at end
    2.43 +	  // that saves its own return addr, then jumps to core_loop.
    2.44 +   while(1)
    2.45 +   {
    2.46         
    2.47     //============================= MEASUREMENT STUFF ========================
    2.48     #ifdef MEAS__TIME_MASTER
    2.49        //Total Master time includes one coreloop time -- just assume the core
    2.50 -      // loop time is same for Master as for AppVPs, even though it may be
    2.51 +      // loop time is same for Master as is for AppVPs, even though it may be
    2.52        // smaller due to higher predictability of the fixed jmp.
    2.53     saveLowTimeStampCountInto( masterPr->startMasterTSCLow );
    2.54     #endif
    2.55 @@ -122,7 +113,7 @@
    2.56     masterEnv        = (MasterEnv*)_VMSMasterEnv;
    2.57     
    2.58        //GCC may optimize so doesn't always re-define from frame-storage
    2.59 -   masterPr         = (VirtProcr*)volatileMasterPr; //on stack, to be sure after jmp
    2.60 +   masterPr         = (VirtProcr*)volatileMasterPr; //on stack, reload after jmp
    2.61     thisCoresIdx     = masterPr->coreAnimatedBy;
    2.62     readyToAnimateQ  = masterEnv->readyToAnimateQs[thisCoresIdx];
    2.63     schedSlots       = masterEnv->allSchedSlots[thisCoresIdx];
    2.64 @@ -132,15 +123,15 @@
    2.65     semanticEnv      = masterEnv->semanticEnv;
    2.66  
    2.67        //First, check for requests from other MasterVPs, and handle them
    2.68 -   if( masterEnv->requestsWaitingFor[thisCoresIdx] )
    2.69 -    { masterReqQ = masterEnv->masterReqQs[thisCoresIdx];
    2.70 -	  while( currReq = readVMSQ(masterReqQ) )
    2.71 -       { handleMasterReq( currReq, semanticEnv, masterPr );
    2.72 -       }	   
    2.73 -	}
    2.74 +   if( currReq = masterEnv->interMasterRequestsFor[thisCoresIdx] )
    2.75 +    { do
    2.76 +       { handleInterMasterReq( currReq, semanticEnv, masterPr );
    2.77 +       }
    2.78 +      while( currReq = currReq->nextReqst );
    2.79 +    }
    2.80        //Now, take care of the SlaveVPs
    2.81 -	  //Go through the slots -- if Slave there newly suspended, handle its request
    2.82 -	  // then, either way, ask assigner to fill each slot
    2.83 +      //Go through the slots -- if Slave there newly suspended, handle its request
    2.84 +      // then, either way, ask assigner to fill each slot
    2.85     numSlotsFilled = 0;
    2.86     for( slotIdx = 0; slotIdx < NUM_SCHED_SLOTS; slotIdx++)
    2.87      {
    2.88 @@ -208,14 +199,15 @@
    2.89   * master_loop, others are handed off to the plugin.
    2.90   */
    2.91  void inline
    2.92 -handleMasterReq( MasterReq *currReq, void *_semEnv, VirtProcr *masterPr )
    2.93 - {
    2.94 -   switch( currReq->reqType )
    2.95 -    { case interVMSReq:
    2.96 -            handleInterVMSReq(     (InterVMSCoreReq *)currReq, masterPr);
    2.97 +handleInterMasterReq( InterMasterReqst *currReq, void *_semEnv,
    2.98 +                                                    VirtProcr *masterPr )
    2.99 + { switch( currReq->reqType )
   2.100 +    { case destVMSCore:
   2.101 +            handleInterVMSCoreReq( (InterVMSCoreReqst *)currReq, masterPr);
   2.102           break;
   2.103 -      case interPluginReq:
   2.104 -	       (*interPluginReqHdlr)(  (InterPluginReq  *)currReq, _semEnv );
   2.105 +      case destPlugin:
   2.106 +	       (*interPluginReqHdlr)( ((InterPluginReqst  *)currReq)->pluginReq,
   2.107 +                                                                _semEnv );
   2.108           break;
   2.109        default:
   2.110           break;
   2.111 @@ -223,15 +215,16 @@
   2.112   }
   2.113  
   2.114  void inline
   2.115 -handleInterVMSReq( InterVMSCoreReq *currReq, VirtProcr *masterPr )
   2.116 +handleInterVMSReq( InterVMSCoreReqst *currReq, VirtProcr *masterPr )
   2.117   { 
   2.118     switch( currReq->reqType )
   2.119      {
   2.120 -      case transfer_free:        handleTransferFree( currReq, masterPr );
   2.121 +      case transfer_free_ptr:    handleTransferFree( currReq, masterPr );
   2.122           break;
   2.123      }
   2.124   }
   2.125   
   2.126 + 
   2.127  
   2.128  /*Work Stealing Alg -- racy one
   2.129   *This algorithm has a race condition -- the coreloops are accessing their
     3.1 --- a/VMS.c	Tue Aug 30 21:55:04 2011 -0700
     3.2 +++ b/VMS.c	Sat Sep 03 20:41:51 2011 -0700
     3.3 @@ -497,6 +497,19 @@
     3.4     VMS__suspend_procr( callingPr );
     3.5   }
     3.6  
     3.7 +void inline
     3.8 +VMS__send_inter_plugin_req( void *reqData, int32 targetMaster, 
     3.9 +                                            VirtProcr *requestingMaster )
    3.10 + { _VMSMasterEnv->interMasterRequestsFor[targetMaster] = 
    3.11 +                                            (InterMasterReqst *) reqData;
    3.12 + }
    3.13 +
    3.14 +void inline
    3.15 +VMS__send_inter_VMSCore_req( InterVMSCoreReqst *reqData,
    3.16 +                        int32 targetMaster, VirtProcr *requestingMaster )
    3.17 + { _VMSMasterEnv->interMasterRequestsFor[targetMaster] = 
    3.18 +                                            (InterMasterReqst *) reqData;
    3.19 + }
    3.20  
    3.21  /*
    3.22   */
     4.1 --- a/VMS.h	Tue Aug 30 21:55:04 2011 -0700
     4.2 +++ b/VMS.h	Sat Sep 03 20:41:51 2011 -0700
     4.3 @@ -113,7 +113,7 @@
     4.4  
     4.5  typedef struct _SchedSlot     SchedSlot;
     4.6  typedef struct _VMSReqst      VMSReqst;
     4.7 -typedef struct _VirtProcr     VirtProcr;
     4.8 +typedef struct _InterMasterReqst InterMasterReqst;
     4.9  typedef struct _IntervalProbe IntervalProbe;
    4.10  typedef struct _GateStruc     GateStruc;
    4.11  
    4.12 @@ -128,9 +128,12 @@
    4.13  //============= Requests ===========
    4.14  //
    4.15  
    4.16 -enum VMSReqstType   //avoid starting enums at 0, for debug reasons
    4.17 - {
    4.18 -   semantic = 1,
    4.19 +//VMS Request is the carrier for Slave to Master requests
    4.20 +// it has an embedded sub-type request that is pulled out
    4.21 +// inside the plugin's request handler
    4.22 +enum VMSReqstType   //For Slave->Master requests
    4.23 + { 
    4.24 +   semantic = 1,    //avoid starting enums at 0, for debug reasons
    4.25     createReq,
    4.26     dissipate,
    4.27     VMSSemantic      //goes with VMSSemReqst below
    4.28 @@ -145,6 +148,9 @@
    4.29   };
    4.30  //VMSReqst
    4.31  
    4.32 +//This is a sub-type of Slave->Master requests.
    4.33 +// It's for Slaves to invoke built-in VMS-core functions that have language-like
    4.34 +// behavior.
    4.35  enum VMSSemReqstType   //These are equivalent to semantic requests, but for
    4.36   {                     // VMS's services available directly to app, like OS
    4.37     createProbe = 1,    // and probe services -- like a VMS-wide built-in lang
    4.38 @@ -157,7 +163,53 @@
    4.39     VirtProcr           *requestingPr;
    4.40     char                *nameStr;  //for create probe
    4.41   }
    4.42 - VMSSemReq;
    4.43 +VMSSemReq;
    4.44 +
    4.45 +//These are for Master to Master requests
    4.46 +// They get re-cast to the appropriate sub-type of request
    4.47 +enum InterMasterReqstType    //For Master->Master
    4.48 + {
    4.49 +   destVMSCore = 1,          //avoid starting enums at 0, for debug reasons
    4.50 +   destPlugin
    4.51 + };
    4.52 +
    4.53 +struct _InterMasterReqst //Doing a trick to save space & time -- allocate
    4.54 + {  // space for a sub-type then cast first as InterMaster then as sub-type
    4.55 +   enum InterMasterReqstType  reqType;
    4.56 +   InterMasterReqst *nextReqst;
    4.57 + };
    4.58 +//InterMasterReqst  (defined above in typedef block)
    4.59 +
    4.60 +
    4.61 +//These are a sub-type of InterMaster requests.  The inter-master req gets
    4.62 +// re-cast to be of this type, after checking
    4.63 +//This ones for requests between internals of VMS-core.. such as malloc
    4.64 +enum InterVMSCoreReqType   
    4.65 + {
    4.66 +   transfer_free_ptr = 1     //avoid starting enums at 0, for debug reasons
    4.67 + };
    4.68 +
    4.69 +typedef struct  //Doing a trick to save space & time -- allocate space
    4.70 + {              // for this, cast first as InterMaster then as this
    4.71 +   enum InterMasterReqstType  reqType;  //duplicate InterMasterReqst at top
    4.72 +   InterMasterReqst *nextReqst;
    4.73 +   
    4.74 +   enum InterVMSCoreReqType  secondReqType;
    4.75 +   void                     *freePtr;  //pile up fields, add as needed
    4.76 + }
    4.77 +InterVMSCoreReqst;
    4.78 +
    4.79 +
    4.80 +//This is for requests between plugins on different cores
    4.81 +// Here, after casting, the pluginReq is extracted and handed to plugin
    4.82 +typedef struct  //Doing a trick to save space & time -- allocate space
    4.83 + {              // for this, cast first as InterMaster then as this
    4.84 +   enum InterMasterReqstType  reqType;  //copy InterMasterReqst at top
    4.85 +   InterMasterReqst          *nextReqst;
    4.86 +   
    4.87 +   void                      *pluginReq; //plugin will cast to approp type
    4.88 + }
    4.89 +InterPluginReqst;
    4.90  
    4.91  
    4.92  //====================  Core data structures  ===================
    4.93 @@ -209,9 +261,8 @@
    4.94  //VirtProcr
    4.95  
    4.96  
    4.97 -/*WARNING: re-arranging this data structure could cause VP-switching
    4.98 - *         assembly code to fail -- hard-codes offsets of fields
    4.99 - *         (because -O3 messes with things otherwise)
   4.100 +/*Master Env is the only global variable -- has entry points for any other
   4.101 + * data needed.  
   4.102   */
   4.103  typedef struct
   4.104   {
   4.105 @@ -368,6 +419,14 @@
   4.106  inline void
   4.107  VMS__send_VMSSem_request( void *semReqData, VirtProcr *callingPr );
   4.108  
   4.109 +
   4.110 +void inline
   4.111 +VMS__send_inter_plugin_req( void *reqData, int32 targetMaster, 
   4.112 +                                            VirtProcr *requestingMaster );
   4.113 +void inline
   4.114 +VMS__send_inter_VMSCore_req( InterVMSCoreReqst *reqData, int32 targetMaster,
   4.115 +                                           VirtProcr *requestingMaster );
   4.116 +
   4.117  VMSReqst *
   4.118  VMS__take_next_request_out_of( VirtProcr *procrWithReq );
   4.119  
     5.1 --- a/inter_VMS_request_handlers.h	Tue Aug 30 21:55:04 2011 -0700
     5.2 +++ b/inter_VMS_request_handlers.h	Sat Sep 03 20:41:51 2011 -0700
     5.3 @@ -16,7 +16,7 @@
     5.4   */
     5.5  
     5.6  inline void
     5.7 -handleMakeMutex(  VPThdSemReq *semReq, VPThdSemEnv *semEnv);
     5.8 +handleTransferFree( MasterReq *masterReq, VirtProcr *masterPr );
     5.9  
    5.10  
    5.11  #endif	/* _MASTER_REQ_H */