VMS/VMS_Implementations/VMS_impls/VMS__MC_shared_impl

view VMS__startup_and_shutdown.c @ 248:da08f9717024

Moved VMS_defs__turn_on_and_off.h outside of VMS repo, into project repo
author Sean Halle <seanhalle@yahoo.com>
date Sat, 21 Jul 2012 15:20:40 -0700
parents 227cd4d33d94
children 2341dd049035
line source
1 /*
2 * Copyright 2010 OpenSourceStewardshipFoundation
3 *
4 * Licensed under BSD
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <malloc.h>
11 #include <inttypes.h>
12 #include <sys/time.h>
13 #include <pthread.h>
15 #include "VMS.h"
18 #define thdAttrs NULL
21 /* MEANING OF WL PI SS int
22 * These indicate which places the function is safe to use. They stand for:
23 * WL: Wrapper Library
24 * PI: Plugin
25 * SS: Startup and Shutdown
26 * int: internal to the VMS implementation
27 */
30 //===========================================================================
31 AnimSlot **
32 create_anim_slots( int32 coreSlotsAreOn );
34 void
35 create_masterEnv();
37 void
38 create_the_coreCtlr_OS_threads();
40 MallocProlog *
41 create_free_list();
43 void
44 endOSThreadFn( void *initData, SlaveVP *animatingSlv );
47 //===========================================================================
49 /*Setup has two phases:
50 * 1) Semantic layer first calls init_VMS, which creates masterEnv, and puts
51 * the master Slv into the work-queue, ready for first "call"
52 * 2) Semantic layer then does its own init, which creates the seed virt
53 * slave inside the semantic layer, ready to assign it when
54 * asked by the first run of the animationMaster.
55 *
56 *This part is bit weird because VMS really wants to be "always there", and
57 * have applications attach and detach.. for now, this VMS is part of
58 * the app, so the VMS system starts up as part of running the app.
59 *
60 *The semantic layer is isolated from the VMS internals by making the
61 * semantic layer do setup to a state that it's ready with its
62 * initial Slvs, ready to assign them to slots when the animationMaster
63 * asks. Without this pattern, the semantic layer's setup would
64 * have to modify slots directly to assign the initial virt-procrs, and put
65 * them into the readyToAnimateQ itself, breaking the isolation completely.
66 *
67 *
68 *The semantic layer creates the initial Slv(s), and adds its
69 * own environment to masterEnv, and fills in the pointers to
70 * the requestHandler and slaveAssigner plug-in functions
71 */
73 /*This allocates VMS data structures, populates the master VMSProc,
74 * and master environment, and returns the master environment to the semantic
75 * layer.
76 */
77 void
78 VMS_SS__init()
79 {
80 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
81 create_masterEnv();
82 printf( "\n\n Running in SEQUENTIAL mode \n\n" );
83 #else
84 create_masterEnv();
85 DEBUG__printf1(TRUE,"Offset of lock in masterEnv: %d ", (int32)offsetof(MasterEnv,masterLock) );
86 create_the_coreCtlr_OS_threads();
87 #endif
88 }
91 /*TODO: finish implementing
92 *This function returns information about the version of VMS, the language
93 * the program is being run in, its version, and information on the
94 * hardware.
95 */
96 /*
97 char *
98 VMS_App__give_environment_string()
99 {
100 //--------------------------
101 fprintf(output, "#\n# >> Build information <<\n");
102 fprintf(output, "# GCC VERSION: %d.%d.%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__);
103 fprintf(output, "# Build Date: %s %s\n", __DATE__, __TIME__);
105 fprintf(output, "#\n# >> Hardware information <<\n");
106 fprintf(output, "# Hardware Architecture: ");
107 #ifdef __x86_64
108 fprintf(output, "x86_64");
109 #endif //__x86_64
110 #ifdef __i386
111 fprintf(output, "x86");
112 #endif //__i386
113 fprintf(output, "\n");
114 fprintf(output, "# Number of Cores: %d\n", NUM_CORES);
115 //--------------------------
117 //VMS Plugins
118 fprintf(output, "#\n# >> VMS Plugins <<\n");
119 fprintf(output, "# Language : ");
120 fprintf(output, _LANG_NAME_);
121 fprintf(output, "\n");
122 //Meta info gets set by calls from the language during its init,
123 // and info registered by calls from inside the application
124 fprintf(output, "# Assigner: %s\n", _VMSMasterEnv->metaInfo->assignerInfo);
126 //--------------------------
127 //Application
128 fprintf(output, "#\n# >> Application <<\n");
129 fprintf(output, "# Name: %s\n", _VMSMasterEnv->metaInfo->appInfo);
130 fprintf(output, "# Data Set:\n%s\n",_VMSMasterEnv->metaInfo->inputSet);
132 //--------------------------
133 }
134 */
136 /*This structure holds all the information VMS needs to manage a program. VMS
137 * stores information about what percent of CPU time the program is getting, what
138 * language it uses, the request handlers to call for its slaves, and so on.
139 */
140 /*
141 typedef struct
142 { void *semEnv;
143 RequestHdlrFnPtr requestHandler;
144 SlaveAssignerFnPtr slaveAssigner;
145 int32 numSlavesLive;
146 void *resultToReturn;
148 TopLevelFnPtr seedFnPtr;
149 void *dataForSeed;
150 bool32 executionIsComplete;
151 pthread_mutex_t doneLock;
152 pthread_cond_t doneCond;
153 }
154 VMSProcess;
155 */
158 /*
159 void
160 VMS_App__start_VMS_running()
161 {
162 create_masterEnv();
164 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
165 //Nothing else to create for sequential mode
166 #else
167 create_the_coreCtlr_OS_threads();
168 #endif
169 }
170 */
172 /*A pointer to the startup-function for the language is given as the last
173 * argument to the call. Use this to initialize a program in the language.
174 * This creates a data structure that encapsulates the bookkeeping info
175 * VMS uses to track and schedule a program run.
176 */
177 /*
178 VMSProcess *
179 VMS_App__spawn_program_on_data_in_Lang( TopLevelFnPtr prog_seed_fn, void *data,
180 LangInitFnPtr langInitFnPtr )
181 { VMSProcess *newProcess;
182 newProcess = malloc( sizeof(VMSProcess) );
183 newProcess->doneLock = PTHREAD_MUTEX_INITIALIZER;
184 newProcess->doneCond = PTHREAD_COND_INITIALIZER;
185 newProcess->executionIsComplete = FALSE;
186 newProcess->numSlavesLive = 0;
188 newProcess->dataForSeed = data;
189 newProcess->seedFnPtr = prog_seed_fn;
191 //The language's spawn-process function fills in the plugin function-ptrs in
192 // the VMSProcess struct, gives the struct to VMS, which then makes and
193 // queues the seed SlaveVP, which starts processors made from the code being
194 // animated.
196 (*langInitFnPtr)( newProcess );
198 return newProcess;
199 }
200 */
202 /*When all SlaveVPs owned by the program-run associated to the process have
203 * dissipated, then return from this call. There is no language to cleanup,
204 * and VMS does not shutdown.. but the process bookkeeping structure,
205 * which is used by VMS to track and schedule the program, is freed.
206 *The VMSProcess structure is kept until this call collects the results from it,
207 * then freed. If the process is not done yet when VMS gets this
208 * call, then this call waits.. the challenge here is that this call comes from
209 * a live OS thread that's outside VMS.. so, inside here, it waits on a
210 * condition.. then it's a VMS thread that signals this to wake up..
211 *First checks whether the process is done, if yes, calls the clean-up fn then
212 * returns the result extracted from the VMSProcess struct.
213 *If process not done yet, then performs a wait (in a loop to be sure the
214 * wakeup is not spurious, which can happen). VMS registers the wait, and upon
215 * the process ending (last SlaveVP owned by it dissipates), then VMS signals
216 * this to wakeup. This then calls the cleanup fn and returns the result.
217 */
218 /*
219 void *
220 VMS_App__give_results_when_done_for( VMSProcess *process )
221 { void *result;
223 pthread_mutex_lock( process->doneLock );
224 while( !(process->executionIsComplete) )
225 {
226 pthread_cond_wait( process->doneCond,
227 process->doneLock );
228 }
229 pthread_mutex_unlock( process->doneLock );
231 result = process->resultToReturn;
233 VMS_int__cleanup_process_after_done( process );
234 free( process ); //was malloc'd above, so free it here
236 return result;
237 }
238 */
240 /*Turns off the VMS system, and frees all data associated with it. Does this
241 * by creating shutdown SlaveVPs and inserting them into animation slots.
242 * Will probably have to wake up sleeping cores as part of this -- the fn that
243 * inserts the new SlaveVPs should handle the wakeup..
244 */
245 /*
246 void
247 VMS_SS__shutdown(); //already defined -- look at it
249 void
250 VMS_App__shutdown()
251 {
252 for( cores )
253 { slave = VMS_int__create_new_SlaveVP( endOSThreadFn, NULL );
254 VMS_int__insert_slave_onto_core( SlaveVP *slave, coreNum );
255 }
256 }
257 */
259 /* VMS_App__start_VMS_running();
261 VMSProcess matrixMultProcess;
263 matrixMultProcess =
264 VMS_App__spawn_program_on_data_in_Lang( &prog_seed_fn, data, Vthread_lang );
266 resMatrix = VMS_App__give_results_when_done_for( matrixMultProcess );
268 VMS_App__shutdown();
269 */
271 void
272 create_masterEnv()
273 { MasterEnv *masterEnv;
274 VMSQueueStruc **readyToAnimateQs;
275 int coreIdx;
276 SlaveVP **masterVPs;
277 AnimSlot ***allAnimSlots; //ptr to array of ptrs
280 //Make the master env, which holds everything else
281 _VMSMasterEnv = malloc( sizeof(MasterEnv) );
283 //Very first thing put into the master env is the free-list, seeded
284 // with a massive initial chunk of memory.
285 //After this, all other mallocs are VMS__malloc.
286 _VMSMasterEnv->freeLists = VMS_ext__create_free_list();
289 //===================== Only VMS__malloc after this ====================
290 masterEnv = (MasterEnv*)_VMSMasterEnv;
292 //Make a readyToAnimateQ for each core controller
293 readyToAnimateQs = VMS_int__malloc( NUM_CORES * sizeof(VMSQueueStruc *) );
294 masterVPs = VMS_int__malloc( NUM_CORES * sizeof(SlaveVP *) );
296 //One array for each core, several in array, core's masterVP scheds all
297 allAnimSlots = VMS_int__malloc( NUM_CORES * sizeof(AnimSlot *) );
299 _VMSMasterEnv->numSlavesAlive = 0; //used to detect shut-down condition
301 _VMSMasterEnv->numSlavesCreated = 0; //used by create slave to set ID
302 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
303 {
304 readyToAnimateQs[ coreIdx ] = makeVMSQ();
306 //Q: should give masterVP core-specific info as its init data?
307 masterVPs[ coreIdx ] = VMS_int__create_slaveVP( (TopLevelFnPtr)&animationMaster, (void*)masterEnv );
308 masterVPs[ coreIdx ]->coreAnimatedBy = coreIdx;
309 masterVPs[ coreIdx ]->typeOfVP = Master;
310 allAnimSlots[ coreIdx ] = create_anim_slots( coreIdx ); //makes for one core
311 }
312 _VMSMasterEnv->masterVPs = masterVPs;
313 _VMSMasterEnv->masterLock = UNLOCKED;
314 _VMSMasterEnv->seed1 = rand()%1000; // init random number generator
315 _VMSMasterEnv->seed2 = rand()%1000; // init random number generator
316 _VMSMasterEnv->allAnimSlots = allAnimSlots;
317 _VMSMasterEnv->measHistsInfo = NULL;
319 //============================= MEASUREMENT STUFF ========================
321 MEAS__Make_Meas_Hists_for_Susp_Meas;
322 MEAS__Make_Meas_Hists_for_Master_Meas;
323 MEAS__Make_Meas_Hists_for_Master_Lock_Meas;
324 MEAS__Make_Meas_Hists_for_Malloc_Meas;
325 MEAS__Make_Meas_Hists_for_Plugin_Meas;
326 MEAS__Make_Meas_Hists_for_Language;
328 PROBES__Create_Probe_Bookkeeping_Vars;
330 HOLISTIC__Setup_Perf_Counters;
332 //========================================================================
333 }
335 AnimSlot **
336 create_anim_slots( int32 coreSlotsAreOn )
337 { AnimSlot **animSlots;
338 int i;
340 animSlots = VMS_int__malloc( NUM_ANIM_SLOTS * sizeof(AnimSlot *) );
342 for( i = 0; i < NUM_ANIM_SLOTS; i++ )
343 {
344 animSlots[i] = VMS_int__malloc( sizeof(AnimSlot) );
346 //Set state to mean "handling requests done, slot needs filling"
347 animSlots[i]->workIsDone = FALSE;
348 animSlots[i]->needsSlaveAssigned = TRUE;
349 animSlots[i]->slotIdx = i; //quick retrieval of slot pos
350 animSlots[i]->coreSlotIsOn = coreSlotsAreOn;
351 }
352 return animSlots;
353 }
356 void
357 freeAnimSlots( AnimSlot **animSlots )
358 { int i;
359 for( i = 0; i < NUM_ANIM_SLOTS; i++ )
360 {
361 VMS_int__free( animSlots[i] );
362 }
363 VMS_int__free( animSlots );
364 }
367 void
368 create_the_coreCtlr_OS_threads()
369 {
370 //========================================================================
371 // Create the Threads
372 int coreIdx, retCode;
374 //Need the threads to be created suspended, and wait for a signal
375 // before proceeding -- gives time after creating to initialize other
376 // stuff before the coreCtlrs set off.
377 _VMSMasterEnv->setupComplete = 0;
379 //initialize the cond used to make the new threads wait and sync up
380 //must do this before *creating* the threads..
381 pthread_mutex_init( &suspendLock, NULL );
382 pthread_cond_init( &suspendCond, NULL );
384 //Make the threads that animate the core controllers
385 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
386 { coreCtlrThdParams[coreIdx] = VMS_int__malloc( sizeof(ThdParams) );
387 coreCtlrThdParams[coreIdx]->coreNum = coreIdx;
389 retCode =
390 pthread_create( &(coreCtlrThdHandles[coreIdx]),
391 thdAttrs,
392 &coreController,
393 (void *)(coreCtlrThdParams[coreIdx]) );
394 if(retCode){printf("ERROR creating thread: %d\n", retCode); exit(1);}
395 }
396 }
400 void
401 VMS_SS__register_request_handler( RequestHandler requestHandler )
402 { _VMSMasterEnv->requestHandler = requestHandler;
403 }
406 void
407 VMS_SS__register_anim_assigner( SlaveAssigner animAssigner )
408 { _VMSMasterEnv->slaveAssigner = animAssigner;
409 }
411 VMS_SS__register_semantic_env( void *semanticEnv )
412 { _VMSMasterEnv->semanticEnv = semanticEnv;
413 }
416 /*This is what causes the VMS system to initialize.. then waits for it to
417 * exit.
418 *
419 *Wrapper lib layer calls this when it wants the system to start running..
420 */
421 void
422 VMS_SS__start_the_work_then_wait_until_done()
423 {
424 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
425 /*Only difference between version with an OS thread pinned to each core and
426 * the sequential version of VMS is VMS__init_Seq, this, and coreCtlr_Seq.
427 */
428 //Instead of un-suspending threads, just call the one and only
429 // core ctlr (sequential version), in the main thread.
430 coreCtlr_Seq( NULL );
431 flushRegisters();
432 #else
433 int coreIdx;
434 //Start the core controllers running
436 //tell the core controller threads that setup is complete
437 //get lock, to lock out any threads still starting up -- they'll see
438 // that setupComplete is true before entering while loop, and so never
439 // wait on the condition
440 pthread_mutex_lock( &suspendLock );
441 _VMSMasterEnv->setupComplete = 1;
442 pthread_mutex_unlock( &suspendLock );
443 pthread_cond_broadcast( &suspendCond );
446 //wait for all to complete
447 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ )
448 {
449 pthread_join( coreCtlrThdHandles[coreIdx], NULL );
450 }
452 //NOTE: do not clean up VMS env here -- semantic layer has to have
453 // a chance to clean up its environment first, then do a call to free
454 // the Master env and rest of VMS locations
455 #endif
456 }
459 SlaveVP* VMS_SS__create_shutdown_slave(){
460 SlaveVP* shutdownVP;
462 shutdownVP = VMS_int__create_slaveVP( &endOSThreadFn, NULL );
463 shutdownVP->typeOfVP = Shutdown;
465 return shutdownVP;
466 }
468 //TODO: look at architecting cleanest separation between request handler
469 // and animation master, for dissipate, create, shutdown, and other non-semantic
470 // requests. Issue is chain: one removes requests from AppSlv, one dispatches
471 // on type of request, and one handles each type.. but some types require
472 // action from both request handler and animation master -- maybe just give the
473 // request handler calls like: VMS__handle_X_request_type
476 /*This is called by the semantic layer's request handler when it decides its
477 * time to shut down the VMS system. Calling this causes the core controller OS
478 * threads to exit, which unblocks the entry-point function that started up
479 * VMS, and allows it to grab the result and return to the original single-
480 * threaded application.
481 *
482 *The _VMSMasterEnv is needed by this shut down function, so the create-seed-
483 * and-wait function has to free a bunch of stuff after it detects the
484 * threads have all died: the masterEnv, the thread-related locations,
485 * masterVP any AppSlvs that might still be allocated and sitting in the
486 * semantic environment, or have been orphaned in the _VMSWorkQ.
487 *
488 *NOTE: the semantic plug-in is expected to use VMS__malloc to get all the
489 * locations it needs, and give ownership to masterVP. Then, they will be
490 * automatically freed.
491 *
492 *In here,create one core-loop shut-down processor for each core controller and put
493 * them all directly into the readyToAnimateQ.
494 *Note, this function can ONLY be called after the semantic environment no
495 * longer cares if AppSlvs get animated after the point this is called. In
496 * other words, this can be used as an abort, or else it should only be
497 * called when all AppSlvs have finished dissipate requests -- only at that
498 * point is it sure that all results have completed.
499 */
500 void
501 VMS_SS__shutdown()
502 { int32 coreIdx;
503 SlaveVP *shutDownSlv;
504 AnimSlot **animSlots;
505 //create the shutdown processors, one for each core controller -- put them
506 // directly into the Q -- each core will die when gets one
507 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
508 { //Note, this is running in the master
509 shutDownSlv = VMS_SS__create_shutdown_slave();
510 //last slave has dissipated, so no more in slots, so write
511 // shut down slave into first animulng slot.
512 animSlots = _VMSMasterEnv->allAnimSlots[ coreIdx ];
513 animSlots[0]->slaveAssignedToSlot = shutDownSlv;
514 animSlots[0]->needsSlaveAssigned = FALSE;
515 shutDownSlv->coreAnimatedBy = coreIdx;
516 shutDownSlv->animSlotAssignedTo = animSlots[ 0 ];
517 }
518 }
521 /*Am trying to be cute, avoiding IF statement in coreCtlr that checks for
522 * a special shutdown slaveVP. Ended up with extra-complex shutdown sequence.
523 *This function has the sole purpose of setting the stack and framePtr
524 * to the coreCtlr's stack and framePtr.. it does that then jumps to the
525 * core ctlr's shutdown point -- might be able to just call Pthread_exit
526 * from here, but am going back to the pthread's stack and setting everything
527 * up just as if it never jumped out, before calling pthread_exit.
528 *The end-point of core ctlr will free the stack and so forth of the
529 * processor that animates this function, (this fn is transfering the
530 * animator of the AppSlv that is in turn animating this function over
531 * to core controller function -- note that this slices out a level of virtual
532 * processors).
533 */
534 void
535 endOSThreadFn( void *initData, SlaveVP *animatingSlv )
536 {
537 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
538 asmTerminateCoreCtlrSeq(animatingSlv);
539 #else
540 asmTerminateCoreCtlr(animatingSlv);
541 #endif
542 }
545 /*This is called from the startup & shutdown
546 */
547 void
548 VMS_SS__cleanup_at_end_of_shutdown()
549 {
550 //Before getting rid of everything, print out any measurements made
551 if( _VMSMasterEnv->measHistsInfo != NULL )
552 { forAllInDynArrayDo( _VMSMasterEnv->measHistsInfo, (DynArrayFnPtr)&printHist );
553 forAllInDynArrayDo( _VMSMasterEnv->measHistsInfo, (DynArrayFnPtr)&saveHistToFile);
554 forAllInDynArrayDo( _VMSMasterEnv->measHistsInfo, (DynArrayFnPtr)&freeHist );
555 }
557 MEAS__Print_Hists_for_Susp_Meas;
558 MEAS__Print_Hists_for_Master_Meas;
559 MEAS__Print_Hists_for_Master_Lock_Meas;
560 MEAS__Print_Hists_for_Malloc_Meas;
561 MEAS__Print_Hists_for_Plugin_Meas;
564 //All the environment data has been allocated with VMS__malloc, so just
565 // free its internal big-chunk and all inside it disappear.
566 /*
567 readyToAnimateQs = _VMSMasterEnv->readyToAnimateQs;
568 masterVPs = _VMSMasterEnv->masterVPs;
569 allAnimSlots = _VMSMasterEnv->allAnimSlots;
571 for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
572 {
573 freeVMSQ( readyToAnimateQs[ coreIdx ] );
574 //master Slvs were created external to VMS, so use external free
575 VMS_int__dissipate_slaveVP( masterVPs[ coreIdx ] );
577 freeAnimSlots( allAnimSlots[ coreIdx ] );
578 }
580 VMS_int__free( _VMSMasterEnv->readyToAnimateQs );
581 VMS_int__free( _VMSMasterEnv->masterVPs );
582 VMS_int__free( _VMSMasterEnv->allAnimSlots );
584 //============================= MEASUREMENT STUFF ========================
585 #ifdef PROBES__TURN_ON_STATS_PROBES
586 freeDynArrayDeep( _VMSMasterEnv->dynIntervalProbesInfo, &VMS_WL__free_probe);
587 #endif
588 //========================================================================
589 */
590 //These are the only two that use system free
591 VMS_ext__free_free_list( _VMSMasterEnv->freeLists );
592 free( (void *)_VMSMasterEnv );
593 }
596 //================================