changeset 24:2b161e1a50ee

1st working version -- as far as can tell due to SEH bugs
author Me
date Wed, 07 Jul 2010 13:15:54 -0700
parents aa634ef7cc35
children c556193f7211
files CoreLoop.c VMS.c VMS.h
diffstat 3 files changed, 203 insertions(+), 80 deletions(-) [+]
line diff
     1.1 --- a/CoreLoop.c	Wed Jun 30 13:11:06 2010 -0700
     1.2 +++ b/CoreLoop.c	Wed Jul 07 13:15:54 2010 -0700
     1.3 @@ -33,21 +33,12 @@
     1.4        //Designate a core by a 1 in bit-position corresponding to the core
     1.5     SetThreadAffinityMask(GetCurrentThread(),1 << coreLoopThdParams->coreNum);
     1.6  
     1.7 -      //Save the stack pointer and frame pointer of this coreLoop's thread
     1.8 -//   asm volatile("movl %%ebp, %0;  \
     1.9 -                 movl %%esp, %1; "\
    1.10 -   /* outputs */ : "=m" (coreLoopThdParams->framePtr), \
    1.11 -                   "=m" (coreLoopThdParams->stackPtr)  \
    1.12 -   /* inputs  */ : \
    1.13 -                );
    1.14     
    1.15        //Save addr of "end core loop" label - jump to it to shut down coreloop
    1.16        //To get label addr in non-gcc compiler, can trick it by making a call
    1.17        // to a fn that does asm that pulls the "return"
    1.18        // addr off the stack and stores it in a pointed-to location.
    1.19 -   coreLoopThdParams->endThdPt       = &&EndCoreLoop;
    1.20 -   _VMSMasterEnv->coreLoopShutDownPt = &&EndCoreLoop; //haven't decided yet
    1.21 -      //which way will do shutdown of core loops
    1.22 +   _VMSMasterEnv->coreLoopShutDownPt = &&EndCoreLoop;
    1.23     
    1.24        //Core loop has no values live upon CoreLoopStartPt except workQ
    1.25        // every value in the code is defined by a statement in core loop,
    1.26 @@ -65,7 +56,9 @@
    1.27     workQ  = _VMSWorkQ;
    1.28     currPr = (VirtProcr *) readCASQ( workQ );
    1.29  
    1.30 -   currPr->coreLoopStartPt = &&CoreLoopStartPt;  //just to be sure.(GCC spec)
    1.31 +//   printf("core %d loop procr addr: %d\n", coreLoopThdParams->coreNum, \
    1.32 +       (int)currPr ); fflush(stdin);
    1.33 +   currPr->coreLoopStartPt = &&CoreLoopStartPt;  //to be sure.(GCC specific)
    1.34     
    1.35     currPr->coreAnimatedBy  = coreLoopThdParams->coreNum;
    1.36  
    1.37 @@ -88,7 +81,6 @@
    1.38        //Explicitly loading into eax before changing frame-ptr fixed it
    1.39        //Also, it turns "(currPr->coreLoopFramePtr)" into a temporary on the
    1.40        // stack, so "movl %%ebp, %0" saves to the temp, NOT the data-struc!
    1.41 -//coreLoop
    1.42     asm volatile("movl %0, %%eax;      \
    1.43                   movl %%esp, (%%eax); \
    1.44                   movl %1, %%eax;      \
     2.1 --- a/VMS.c	Wed Jun 30 13:11:06 2010 -0700
     2.2 +++ b/VMS.c	Wed Jul 07 13:15:54 2010 -0700
     2.3 @@ -71,12 +71,34 @@
     2.4     masterEnv->schedSlots[0]->workIsDone          = FALSE;  //says don't touch
     2.5     masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr;
     2.6     masterEnv->masterVirtPr->schedSlot = masterEnv->schedSlots[0];
     2.7 +   masterEnv->stillRunning = FALSE;
     2.8     
     2.9        //First core loop to start up gets this, which will schedule seed Pr
    2.10        //TODO: debug: check address of masterVirtPr
    2.11     writeCASQ( masterEnv->masterVirtPr, workQ );
    2.12  
    2.13     numProcrsCreated = 1;
    2.14 +
    2.15 +   //========================================================================
    2.16 +   //                      Create the Threads
    2.17 +   int coreIdx;
    2.18 +
    2.19 +   //Make params given to the win threads that animate the core loops
    2.20 +   for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
    2.21 +    { coreLoopThdParams[coreIdx]          = malloc( sizeof(ThdParams) );
    2.22 +      coreLoopThdParams[coreIdx]->coreNum = coreIdx;
    2.23 +
    2.24 +         //make the core loop threads, born in suspended state
    2.25 +      coreLoopThdHandles[ coreIdx ] =
    2.26 +         CreateThread ( NULL, // Security attributes
    2.27 +                        0, // Stack size
    2.28 +                        coreLoop,
    2.29 +                        coreLoopThdParams[coreIdx],
    2.30 +                        CREATE_SUSPENDED,
    2.31 +                        &(coreLoopThdIds[coreIdx])
    2.32 +                       );
    2.33 +    }
    2.34 +
    2.35   }
    2.36  
    2.37  
    2.38 @@ -103,30 +125,44 @@
    2.39  
    2.40  /*Semantic layer calls this when it want the system to start running..
    2.41   *
    2.42 - *This creates the core loops, pins them to physical cores, gives them the
    2.43 - * pointer to the workQ, and starts them running.
    2.44 + *This starts the core loops running then waits for them to exit.
    2.45   */
    2.46  void
    2.47 -VMS__start()
    2.48 +VMS__start_the_work_then_wait_until_done()
    2.49   { int coreIdx;
    2.50 +      //Start the core loops running
    2.51 +//===========================================================================
    2.52 +   LARGE_INTEGER stPerfCount, endPerfCount, countFreq;
    2.53 +   unsigned long long count = 0, freq = 0;
    2.54 +   double runTime;
    2.55  
    2.56 -   //TODO: Save "orig" stack pointer and frame ptr -- restore in VMS__end()
    2.57 -   //Create the win threads that animate the core loops
    2.58 +   QueryPerformanceCounter( &stPerfCount );
    2.59 +
    2.60 +      //start them running
    2.61 +   for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
    2.62 +    {    //Create the threads
    2.63 +      ResumeThread( coreLoopThdHandles[coreIdx] ); //starts thread
    2.64 +    }
    2.65 +
    2.66 +      //wait for all to complete
    2.67     for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
    2.68      {
    2.69 -      coreLoopThdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) );
    2.70 -      coreLoopThdParams[coreIdx]->coreNum = coreIdx;
    2.71 +      WaitForSingleObject(coreLoopThdHandles[coreIdx], INFINITE);
    2.72 +    }
    2.73  
    2.74 -      coreLoopThdHandles[coreIdx] =
    2.75 -          CreateThread ( NULL, // Security attributes
    2.76 -                         0, // Stack size
    2.77 -                         coreLoop,
    2.78 -                         coreLoopThdParams[coreIdx],
    2.79 -                         CREATE_SUSPENDED,
    2.80 -                         &(coreLoopThdIds[coreIdx])
    2.81 -                        );
    2.82 -      ResumeThread( coreLoopThdHandles[coreIdx] ); //starts thread
    2.83 -    }
    2.84 +      //NOTE: do not clean up VMS env here -- semantic layer has to have
    2.85 +      // a chance to clean up its environment first, then do a call to free
    2.86 +      // the Master env and rest of VMS locations
    2.87 +
    2.88 +   QueryPerformanceCounter( &endPerfCount );
    2.89 +   count = endPerfCount.QuadPart - stPerfCount.QuadPart;
    2.90 +
    2.91 +   QueryPerformanceFrequency( &countFreq );
    2.92 +   freq = countFreq.QuadPart;
    2.93 +   runTime = (double)count / (double)freq;
    2.94 +
    2.95 +   printf("\n Time startup to shutdown: %f\n", runTime);
    2.96 +   fflush( stdin );
    2.97   }
    2.98  
    2.99  
   2.100 @@ -283,7 +319,7 @@
   2.101  /*This inserts the semantic-layer's request data into standard VMS carrier
   2.102   */
   2.103  inline void
   2.104 -VMS__send_sem_request( void *semReqData, VirtProcr *callingPr )
   2.105 +VMS__add_sem_request( void *semReqData, VirtProcr *callingPr )
   2.106   { VMSReqst *req;
   2.107  
   2.108     req = malloc( sizeof(VMSReqst) );
   2.109 @@ -295,20 +331,6 @@
   2.110   }
   2.111  
   2.112  
   2.113 -/*This creates a request of type "dissipate" -- which will cause the virt
   2.114 - * processor's state and owned locations to be freed
   2.115 - */
   2.116 -inline void
   2.117 -VMS__send_dissipate_request( VirtProcr *procrToDissipate )
   2.118 - { VMSReqst *req;
   2.119 -
   2.120 -   req = malloc( sizeof(VMSReqst) );
   2.121 -//   req->virtProcrFrom      = callingPr;
   2.122 -   req->reqType               = dissipate;
   2.123 -   req->nextReqst             = procrToDissipate->requests;
   2.124 -   procrToDissipate->requests = req;
   2.125 - }
   2.126 -
   2.127  
   2.128  //TODO: add a semantic-layer supplied "freer" for the semantic-data portion
   2.129  // of a request -- IE call with both a virt procr and a fn-ptr to request
   2.130 @@ -322,36 +344,63 @@
   2.131     free( req );
   2.132   }
   2.133  
   2.134 -/*This must be called by the request handler plugin -- it cannot be called
   2.135 - * from the semantic library "dissipate processor" function -- instead, the
   2.136 - * semantic layer has to generate a request for the plug-in to call this
   2.137 - * function.
   2.138 - *The reason is that this frees the virtual processor's stack -- which is
   2.139 - * still in use inside semantic library calls!
   2.140 - *
   2.141 - *This frees or recycles all the state owned by and comprising the animating
   2.142 - * virtual procr.  It frees any state that was malloc'd by the VMS system
   2.143 - * itself, and asks the VMS system to dis-own any VMS__malloc'd locations.
   2.144 - *If the dissipated processor is the sole (remaining) owner of VMS__malloc'd
   2.145 - * state, then that state gets freed (or sent to recycling) as a side-effect
   2.146 - * of dis-owning it.
   2.147 - */
   2.148 +
   2.149 +//TODO: add a semantic-layer supplied "freer" for the semantic-data portion
   2.150 +// of a request -- IE call with both a virt procr and a fn-ptr to request
   2.151 +// freer (also maybe put sem request freer as a field in virt procr?)
   2.152  void
   2.153 -VMS__free_procr_locs( VirtProcr *animatingPr )
   2.154 +VMS__free_request( VMSReqst *req )
   2.155 + { 
   2.156 +   free( req );
   2.157 + }
   2.158 +
   2.159 +VMSReqst *
   2.160 +VMS__take_top_request_from( VirtProcr *procrWithReq )
   2.161 + { VMSReqst *req;
   2.162 +
   2.163 +   req = procrWithReq->requests;
   2.164 +   if( req == NULL ) return req;
   2.165 +   
   2.166 +   procrWithReq->requests = procrWithReq->requests->nextReqst;
   2.167 +   return req;
   2.168 + }
   2.169 +
   2.170 +inline int
   2.171 +VMS__isSemanticReqst( VMSReqst *req )
   2.172   {
   2.173 -      //dis-own all locations owned by this processor, causing to be freed
   2.174 -      // any locations that it is (was) sole owner of
   2.175 -   //TODO: implement VMS__malloc system, including "give up ownership"
   2.176 +   return ( req->reqType == semantic );
   2.177 + }
   2.178  
   2.179 -   VMS__remove_and_free_top_request( animatingPr );
   2.180 -   free( animatingPr->startOfStack );
   2.181 -   
   2.182 -      //NOTE: animatingPr->semanticData should either have been allocated
   2.183 -      // with VMS__malloc, or else freed in the request handler plug-in.
   2.184 -      //NOTE: initialData was given to the processor, so should either have
   2.185 -      // been alloc'd with VMS__malloc, or freed by the level above animPr.
   2.186 -      //So, all that's left to free here is the VirtProcr struc itself
   2.187 -   free( animatingPr );
   2.188 +
   2.189 +inline void *
   2.190 +VMS__take_sem_reqst_from( VMSReqst *req )
   2.191 + {
   2.192 +   return req->semReqData;
   2.193 + }
   2.194 +
   2.195 +inline int
   2.196 +VMS__isDissipateReqst( VMSReqst *req )
   2.197 + {
   2.198 +   return ( req->reqType == dissipate );
   2.199 + }
   2.200 +
   2.201 +inline int
   2.202 +VMS__isCreateReqst( VMSReqst *req )
   2.203 + {
   2.204 +   return ( req->reqType == regCreated );
   2.205 + }
   2.206 +
   2.207 +void
   2.208 +VMS__send_register_new_procr_request(VirtProcr *newPr, VirtProcr *reqstingPr)
   2.209 + { VMSReqst *req;
   2.210 +
   2.211 +   req                  = malloc( sizeof(VMSReqst) );
   2.212 +   req->reqType         = regCreated;
   2.213 +   req->semReqData      = newPr;
   2.214 +   req->nextReqst       = reqstingPr->requests;
   2.215 +   reqstingPr->requests = req;
   2.216 +
   2.217 +   VMS__suspend_procr( reqstingPr );
   2.218   }
   2.219  
   2.220  
   2.221 @@ -384,6 +433,44 @@
   2.222   }
   2.223  
   2.224  
   2.225 +/*This must be called by the request handler plugin -- it cannot be called
   2.226 + * from the semantic library "dissipate processor" function -- instead, the
   2.227 + * semantic layer has to generate a request for the plug-in to call this
   2.228 + * function.
   2.229 + *The reason is that this frees the virtual processor's stack -- which is
   2.230 + * still in use inside semantic library calls!
   2.231 + *
   2.232 + *This frees or recycles all the state owned by and comprising the VMS
   2.233 + * portion of the animating virtual procr.  The request handler must first
   2.234 + * free any semantic data created for the processor that didn't use the
   2.235 + * VMS_malloc mechanism.  Then it calls this, which first asks the malloc
   2.236 + * system to disown any state that did use VMS_malloc, and then frees the
   2.237 + * statck and the processor-struct itself.
   2.238 + *If the dissipated processor is the sole (remaining) owner of VMS__malloc'd
   2.239 + * state, then that state gets freed (or sent to recycling) as a side-effect
   2.240 + * of dis-owning it.
   2.241 + */
   2.242 +void
   2.243 +VMS__free_procr_locs( VirtProcr *animatingPr )
   2.244 + {
   2.245 +      //dis-own all locations owned by this processor, causing to be freed
   2.246 +      // any locations that it is (was) sole owner of
   2.247 +   //TODO: implement VMS__malloc system, including "give up ownership"
   2.248 +
   2.249 +      //The dissipate request might still be attached, so remove and free it
   2.250 +   VMS__remove_and_free_top_request( animatingPr );
   2.251 +   free( animatingPr->startOfStack );
   2.252 +
   2.253 +      //NOTE: initialData was given to the processor, so should either have
   2.254 +      // been alloc'd with VMS__malloc, or freed by the level above animPr.
   2.255 +      //So, all that's left to free here is the stack and the VirtProcr struc
   2.256 +      // itself
   2.257 +   free( animatingPr->startOfStack );
   2.258 +   free( animatingPr );
   2.259 + }
   2.260 +
   2.261 +
   2.262 +
   2.263  /*This is the function run by the special "shut-down" processor
   2.264   * 
   2.265   *The _VMSMasterEnv is needed by this shut down function, so the "wait"
   2.266 @@ -422,11 +509,32 @@
   2.267        // get its request handled before all the cores have shutdown.
   2.268        //TODO: after all the threads stop, clean out the MasterEnv, the
   2.269        // SemanticEnv, and the workQ before returning.
   2.270 -   VMS__send_dissipate_request( animatingPr );
   2.271 -   VMS__suspend_procr( animatingPr );  //will never come back from this
   2.272 +   VMS__dissipate_procr( animatingPr );  //will never come back from this
   2.273   }
   2.274  
   2.275  
   2.276 +/*This has to free anything allocated during VMS_init, and any other alloc'd
   2.277 + * locations that might be left over.
   2.278 + */
   2.279 +void
   2.280 +VMS__shutdown()
   2.281 + { int i;
   2.282 + 
   2.283 +   free( _VMSWorkQ );
   2.284 +   free( _VMSMasterEnv->filledSlots );
   2.285 +   for( i = 0; i < NUM_SCHED_SLOTS; i++ )
   2.286 +    {
   2.287 +      free( _VMSMasterEnv->schedSlots[i] );
   2.288 +    }
   2.289 +
   2.290 +   free( _VMSMasterEnv->schedSlots);
   2.291 +   VMS__free_procr_locs( _VMSMasterEnv->masterVirtPr );
   2.292 +   
   2.293 +   free( _VMSMasterEnv );
   2.294 + }
   2.295 +
   2.296 +
   2.297 +//===========================================================================
   2.298  
   2.299  inline TSCount getTSCount()
   2.300   { unsigned int low, high;
     3.1 --- a/VMS.h	Wed Jun 30 13:11:06 2010 -0700
     3.2 +++ b/VMS.h	Wed Jul 07 13:15:54 2010 -0700
     3.3 @@ -29,7 +29,7 @@
     3.4  //#define thdAttrs NULL  //For PThreads
     3.5  
     3.6  typedef struct _SchedSlot  SchedSlot;
     3.7 -typedef struct _SlaveReqst VMSReqst;
     3.8 +typedef struct _VMSReqst VMSReqst;
     3.9  typedef struct _VirtProcr  VirtProcr;
    3.10  
    3.11  typedef VirtProcr * (*SlaveScheduler)  ( void * );        //semEnv
    3.12 @@ -59,18 +59,19 @@
    3.13   {
    3.14     semantic = 1,
    3.15     dissipate,
    3.16 +   regCreated,
    3.17     IO
    3.18   };
    3.19  
    3.20 -struct _SlaveReqst
    3.21 +struct _VMSReqst
    3.22   {
    3.23  //   VirtProcr   *virtProcrFrom;
    3.24 -   enum ReqstType  reqType;  //used for dissipate and in future for IO requests
    3.25 +   enum ReqstType  reqType;//used for dissipate and in future for IO requests
    3.26     void           *semReqData;
    3.27  
    3.28     VMSReqst *nextReqst;
    3.29   };
    3.30 -//SlaveReqst
    3.31 +//VMSReqst
    3.32  
    3.33  struct _VirtProcr
    3.34   { int         procrID;  //for debugging -- count up each time create
    3.35 @@ -142,7 +143,7 @@
    3.36  VMS__init();
    3.37  
    3.38  void
    3.39 -VMS__start();
    3.40 +VMS__start_the_work_then_wait_until_done();
    3.41  
    3.42  VirtProcr *
    3.43  VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData );
    3.44 @@ -150,15 +151,37 @@
    3.45  VirtProcr *
    3.46  VMS__create_the_shutdown_procr();
    3.47  
    3.48 +//==========================
    3.49  inline void
    3.50 -VMS__send_sem_request( void *semReqData, VirtProcr *callingPr );
    3.51 +VMS__add_sem_request( void *semReqData, VirtProcr *callingPr );
    3.52  
    3.53  void
    3.54 -VMS__send_dissipate_request( VirtProcr *procrToDissipate );
    3.55 +VMS__send_register_new_procr_request( VirtProcr *newPrToRegister,
    3.56 +                                      VirtProcr *reqstingPr );
    3.57 +
    3.58 +void
    3.59 +VMS__free_request( VMSReqst *req );
    3.60  
    3.61  void
    3.62  VMS__remove_and_free_top_request( VirtProcr *reqstingPr );
    3.63  
    3.64 +VMSReqst *
    3.65 +VMS__take_top_request_from( VirtProcr *reqstingPr );
    3.66 +
    3.67 +inline void *
    3.68 +VMS__take_sem_reqst_from( VMSReqst *req );
    3.69 +
    3.70 +inline int
    3.71 +VMS__isSemanticReqst( VMSReqst *req );
    3.72 +
    3.73 +inline int
    3.74 +VMS__isDissipateReqst( VMSReqst *req );
    3.75 +
    3.76 +inline int
    3.77 +VMS__isCreateReqst( VMSReqst *req );
    3.78 +
    3.79 +//==========================
    3.80 +
    3.81  void
    3.82  VMS__suspend_procr( VirtProcr *callingPr );
    3.83