changeset 0:67a3a05a39c0

Initial add -- copied code, just junk still
author Some Random Person <seanhalle@yahoo.com>
date Wed, 23 May 2012 13:17:07 -0700
parents
children 5ed4d833506e
files .hgeol .hgignore Measurement/VSs_Counter_Recording.c Measurement/VSs_Counter_Recording.h Measurement/VSs_Measurement.h Measurement/dependency.c Measurement/dependency.h VSs.c VSs.h VSs_PluginFns.c VSs_Request_Handlers.c VSs_Request_Handlers.h VSs_singleton_asm.s __brch__default
diffstat 14 files changed, 2481 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgeol	Wed May 23 13:17:07 2012 -0700
     1.3 @@ -0,0 +1,12 @@
     1.4 +
     1.5 +[patterns]
     1.6 +**.py = native
     1.7 +**.txt = native
     1.8 +**.c = native
     1.9 +**.h = native
    1.10 +**.cpp = native
    1.11 +**.java = native
    1.12 +**.sh = native
    1.13 +**.pl = native
    1.14 +**.jpg = bin
    1.15 +**.gif = bin
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/.hgignore	Wed May 23 13:17:07 2012 -0700
     2.3 @@ -0,0 +1,3 @@
     2.4 +syntax: glob
     2.5 +
     2.6 +*.o
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Measurement/VSs_Counter_Recording.c	Wed May 23 13:17:07 2012 -0700
     3.3 @@ -0,0 +1,121 @@
     3.4 +/*
     3.5 + * 
     3.6 + * author: Nina Engelhardt
     3.7 + */
     3.8 +
     3.9 +#include "VOMP_Counter_Recording.h"
    3.10 +#include "VMS_impl/VMS.h"
    3.11 +#include "VOMP.h"
    3.12 +
    3.13 +#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
    3.14 +
    3.15 +void VOMP__init_counter_data_structs(){
    3.16 +    VOMPSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv;
    3.17 +    int i;
    3.18 +    for(i=0;i<NUM_CORES;i++){
    3.19 +        semanticEnv->counterList[i] = makeListOfArrays(sizeof(CounterEvent), 128);
    3.20 +    }
    3.21 +}
    3.22 +
    3.23 +void addToListOfArraysCounterEvent(CounterEvent value, ListOfArrays* list){
    3.24 +    int offset_in_fragment = list->next_free_index % list->num_entries_per_fragment; 
    3.25 +    if(offset_in_fragment == 0){ 
    3.26 +        void* newBlock = malloc(list->entry_size * list->num_entries_per_fragment); 
    3.27 +        addToDynArray(newBlock,list->dim1info); 
    3.28 +    } 
    3.29 +    CounterEvent* typedFragment = (CounterEvent*) ((list->dim1)[list->dim1info->numInArray -1]); 
    3.30 +    typedFragment[offset_in_fragment] = value; 
    3.31 +    list->next_free_index++; 
    3.32 +}
    3.33 +
    3.34 +void VOMP__counter_handler(int evt_type, int vpid, int task, SlaveVP* pr, uint64 cycles, uint64 instrs)
    3.35 +{
    3.36 +    
    3.37 +    if (pr->typeOfVP == Master || pr->typeOfVP == Shutdown)
    3.38 +     { //Only save values for application work, done in a SlaveVP
    3.39 +        return;
    3.40 +     }
    3.41 +
    3.42 +    VOMPSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv;
    3.43 +            
    3.44 +    CounterEvent e;
    3.45 +    e.event_type = evt_type;
    3.46 +    e.vp = vpid;
    3.47 +    e.task = task;
    3.48 +    
    3.49 +    e.cycles = cycles;
    3.50 +    e.instrs = instrs;
    3.51 +    
    3.52 +    if(pr){
    3.53 +        e.coreID = pr->coreAnimatedBy;
    3.54 +        e.slot = pr->animSlotAssignedTo;
    3.55 +    } else {
    3.56 +        e.coreID = -1;
    3.57 +        e.slot = NULL;
    3.58 +    }
    3.59 +    
    3.60 +    int corenum;
    3.61 +    
    3.62 +    if(pr) corenum = pr->coreAnimatedBy; else return; 
    3.63 +  
    3.64 +    if(evt_type==Work_start || evt_type==Work_end || evt_type==AppResponderInvocation_start){
    3.65 +        addToListOfArrays_ext(CounterEvent,e,semanticEnv->counterList[corenum]);
    3.66 +    } else {
    3.67 +        addToListOfArraysCounterEvent(e,semanticEnv->counterList[corenum]);
    3.68 +    }
    3.69 +}
    3.70 +
    3.71 +void set_counter_file(FILE* f){
    3.72 +    counterfile = f;
    3.73 +}
    3.74 +
    3.75 +void print_counter_events_to_file(void* _e){
    3.76 +     CounterEvent* e = (CounterEvent*) _e;
    3.77 +     fprintf(counterfile, "event, ");
    3.78 +     switch(e->event_type){
    3.79 +         case AppResponderInvocation_start:
    3.80 +             fprintf(counterfile, "AppResponderInvocation_start");
    3.81 +             break;
    3.82 +         case AppResponder_start:
    3.83 +             fprintf(counterfile, "AppResponder_start");
    3.84 +             break;
    3.85 +         case AppResponder_end:
    3.86 +             fprintf(counterfile, "AppResponder_end");
    3.87 +             break;
    3.88 +         case AssignerInvocation_start:
    3.89 +             fprintf(counterfile, "AssignerInvocation_start");
    3.90 +             break;
    3.91 +         case NextAssigner_start:
    3.92 +             fprintf(counterfile, "NextAssigner_start");
    3.93 +             break;
    3.94 +         case Assigner_start:
    3.95 +             fprintf(counterfile, "Assigner_start");
    3.96 +             break;
    3.97 +         case Assigner_end:
    3.98 +             fprintf(counterfile, "Assigner_end");
    3.99 +             break;
   3.100 +         case Work_end:
   3.101 +             fprintf(counterfile, "Work_end");
   3.102 +             break;
   3.103 +         case Work_start:
   3.104 +             fprintf(counterfile, "Work_start");
   3.105 +             break;
   3.106 +         case HwResponderInvocation_start:
   3.107 +             fprintf(counterfile, "HwResponderInvocation_start");
   3.108 +             break;
   3.109 +         case Timestamp_start:
   3.110 +             fprintf(counterfile, "Timestamp_start");
   3.111 +             break;
   3.112 +         case Timestamp_end:
   3.113 +             fprintf(counterfile, "Timestamp_end");
   3.114 +             break;
   3.115 +         default:
   3.116 +             fprintf(counterfile, "unknown event");
   3.117 +     }
   3.118 +     fprintf(counterfile,", %d, %d, %llu, %llu",e->vp,e->task,e->cycles,e->instrs);
   3.119 +     if(e->coreID >=0)
   3.120 +         fprintf(counterfile,", %d",e->coreID);
   3.121 +     fprintf(counterfile,"\n");
   3.122 +     fflush(counterfile);
   3.123 +}
   3.124 +#endif
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/Measurement/VSs_Counter_Recording.h	Wed May 23 13:17:07 2012 -0700
     4.3 @@ -0,0 +1,33 @@
     4.4 +/* 
     4.5 + * File:   VOMP_Counter_Recording.h
     4.6 + * Author: nengel
     4.7 + *
     4.8 + * Created on January 11, 2012, 3:03 PM
     4.9 + */
    4.10 +
    4.11 +#ifndef VOMP_COUNTER_RECORDING_H
    4.12 +#define	VOMP_COUNTER_RECORDING_H
    4.13 +
    4.14 +#include "VMS_impl/VMS.h"
    4.15 +
    4.16 +typedef struct {
    4.17 +   int event_type;
    4.18 +   int coreID;
    4.19 +   AnimSlot* slot;
    4.20 +   int vp;
    4.21 +   int task;
    4.22 +   uint64 cycles;
    4.23 +   uint64 instrs;
    4.24 +} CounterEvent;
    4.25 +
    4.26 +FILE* counterfile;
    4.27 +
    4.28 +void VOMP__init_counter_data_structs();
    4.29 +
    4.30 +void VOMP__counter_handler(int evt_type, int vpid, int task, SlaveVP* pr, uint64 cycles, uint64 instrs);
    4.31 +
    4.32 +void set_counter_file(FILE* f);
    4.33 +
    4.34 +void print_counter_events_to_file(void* _e);
    4.35 +#endif	/* VOMP_COUNTER_RECORDING_H */
    4.36 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/Measurement/VSs_Measurement.h	Wed May 23 13:17:07 2012 -0700
     5.3 @@ -0,0 +1,87 @@
     5.4 +/*
     5.5 + *  Copyright 2009 OpenSourceStewardshipFoundation.org
     5.6 + *  Licensed under GNU General Public License version 2
     5.7 + *
     5.8 + * Author: seanhalle@yahoo.com
     5.9 + *
    5.10 + */
    5.11 +
    5.12 +#ifndef _VOMP_MEAS_H
    5.13 +#define	_VOMP_MEAS_H
    5.14 +
    5.15 +
    5.16 +#ifdef MEAS__TURN_ON_LANG_MEAS
    5.17 +
    5.18 +   #ifdef MEAS__Make_Meas_Hists_for_Language
    5.19 +   #undef MEAS__Make_Meas_Hists_for_Language
    5.20 +   #endif
    5.21 +
    5.22 +
    5.23 +//===================  Language-specific Measurement Stuff ===================
    5.24 +//
    5.25 +//
    5.26 +   #define SendFromToHistIdx      1 //note: starts at 1
    5.27 +   #define SendOfTypeHistIdx      2
    5.28 +   #define ReceiveFromToHistIdx   3
    5.29 +   #define ReceiveOfTypeHistIdx   4
    5.30 +
    5.31 +   #define MEAS__Make_Meas_Hists_for_Language \
    5.32 +      _VMSMasterEnv->measHistsInfo = \
    5.33 +                 makePrivDynArrayOfSize( (void***)&(_VMSMasterEnv->measHists), 200); \
    5.34 +       makeAMeasHist( SendFromToHistIdx,   "SendFromTo",    50, 0, 100 ) \
    5.35 +       makeAMeasHist( SendOfTypeHistIdx,   "SendOfType",    50, 0, 100 ) \
    5.36 +       makeAMeasHist( ReceiveFromToHistIdx,"ReceiveFromTo", 50, 0, 100 ) \
    5.37 +       makeAMeasHist( ReceiveOfTypeHistIdx,"ReceiveOfType", 50, 0, 100 )
    5.38 +
    5.39 +   #define Meas_startSendFromTo \
    5.40 +       int32 startStamp, endStamp; \
    5.41 +       saveLowTimeStampCountInto( startStamp ); \
    5.42 +
    5.43 +   #define Meas_endSendFromTo \
    5.44 +       saveLowTimeStampCountInto( endStamp ); \
    5.45 +       addIntervalToHist( startStamp, endStamp, \
    5.46 +                                _VMSMasterEnv->measHists[ SendFromToHistIdx ] );
    5.47 +
    5.48 +   #define Meas_startSendOfType \
    5.49 +       int32 startStamp, endStamp; \
    5.50 +       saveLowTimeStampCountInto( startStamp ); \
    5.51 +
    5.52 +   #define Meas_endSendOfType \
    5.53 +       saveLowTimeStampCountInto( endStamp ); \
    5.54 +       addIntervalToHist( startStamp, endStamp, \
    5.55 +                                _VMSMasterEnv->measHists[ SendOfTypeHistIdx ] );
    5.56 +
    5.57 +   #define Meas_startReceiveFromTo \
    5.58 +       int32 startStamp, endStamp; \
    5.59 +       saveLowTimeStampCountInto( startStamp ); \
    5.60 +
    5.61 +   #define Meas_endReceiveFromTo \
    5.62 +       saveLowTimeStampCountInto( endStamp ); \
    5.63 +       addIntervalToHist( startStamp, endStamp, \
    5.64 +                                _VMSMasterEnv->measHists[ ReceiveFromToHistIdx ] );
    5.65 +
    5.66 +   #define Meas_startReceiveOfType \
    5.67 +       int32 startStamp, endStamp; \
    5.68 +       saveLowTimeStampCountInto( startStamp ); \
    5.69 +
    5.70 +   #define Meas_endReceiveOfType \
    5.71 +       saveLowTimeStampCountInto( endStamp ); \
    5.72 +       addIntervalToHist( startStamp, endStamp, \
    5.73 +                                _VMSMasterEnv->measHists[ReceiveOfTypeHistIdx ] );
    5.74 +
    5.75 +#else //===================== turned off ==========================
    5.76 +
    5.77 +   #define MEAS__Make_Meas_Hists_for_Language
    5.78 +   #define Meas_startSendFromTo
    5.79 +   #define Meas_endSendFromTo
    5.80 +   #define Meas_startSendOfType
    5.81 +   #define Meas_endSendOfType
    5.82 +   #define Meas_startReceiveFromTo
    5.83 +   #define Meas_endReceiveFromTo
    5.84 +   #define Meas_startReceiveOfType
    5.85 +   #define Meas_endReceiveOfType
    5.86 +
    5.87 +#endif  /* MEAS__TURN_ON_LANG_MEAS */
    5.88 +
    5.89 +#endif	/*  */
    5.90 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/Measurement/dependency.c	Wed May 23 13:17:07 2012 -0700
     6.3 @@ -0,0 +1,78 @@
     6.4 +#include "dependency.h"
     6.5 +#include "VMS_impl/VMS.h"
     6.6 +
     6.7 +Dependency* new_dependency(int from_vp, int from_task, int to_vp, int to_task){
     6.8 +    Dependency* newDep = (Dependency*) VMS_int__malloc(sizeof(Dependency));
     6.9 +    if (newDep!=NULL){
    6.10 +        newDep->from_vp = from_vp;
    6.11 +        newDep->from_task = from_task;
    6.12 +        newDep->to_vp = to_vp;
    6.13 +        newDep->to_task = to_task;
    6.14 +    }
    6.15 +    return newDep;
    6.16 +}
    6.17 +
    6.18 +NtoN* new_NtoN(int id){
    6.19 +    NtoN* newn = (NtoN*) VMS_int__malloc(sizeof(NtoN));
    6.20 +    newn->id = id;
    6.21 +    newn->senders = makeListOfArrays(sizeof(Unit), 64);
    6.22 +    newn->receivers = makeListOfArrays(sizeof(Unit), 64);
    6.23 +    return newn;
    6.24 +}
    6.25 +
    6.26 +int set_dependency_file(FILE* file){
    6.27 +    dependency_file = file;
    6.28 +}
    6.29 +
    6.30 +void print_ctl_dependency_to_file(void* _dep){
    6.31 +    Dependency* dep = (Dependency*) _dep;
    6.32 +    if(!dep) return;
    6.33 +    fprintf(dependency_file,"ctlDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task);
    6.34 +}
    6.35 +
    6.36 +void print_comm_dependency_to_file(void* _dep){
    6.37 +    Dependency* dep = (Dependency*) _dep;
    6.38 +    if(!dep) return;
    6.39 +    fprintf(dependency_file,"commDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task);
    6.40 +}
    6.41 +
    6.42 +void print_dyn_dependency_to_file(void* _dep){
    6.43 +    Dependency* dep = (Dependency*) _dep;
    6.44 +    if(!dep) return;
    6.45 +    fprintf(dependency_file,"dynDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task);
    6.46 +}
    6.47 +
    6.48 +void print_hw_dependency_to_file(void* _dep){
    6.49 +    Dependency* dep = (Dependency*) _dep;
    6.50 +    if(!dep) return;
    6.51 +    fprintf(dependency_file,"hwDep,%d,%d,%d,%d\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task);
    6.52 +}
    6.53 +
    6.54 +void print_dependency_to_file(void* _dep){
    6.55 +    Dependency* dep = (Dependency*) _dep;
    6.56 +    if(!dep) return;
    6.57 +    fprintf(dependency_file,"VP_%d_%d -> VP_%d_%d;\n",dep->from_vp,dep->from_task,dep->to_vp,dep->to_task);
    6.58 +}
    6.59 +
    6.60 +void print_unit_to_file(void* _unit){
    6.61 +    Unit* unit = (Unit*) _unit;
    6.62 +    if(!unit) return;
    6.63 +    fprintf(dependency_file,"unit,%d,%d\n",unit->vp,unit->task);
    6.64 +}
    6.65 +
    6.66 +void print_nton_set_helper(void* _u){
    6.67 +    Unit* u = (Unit*) _u;
    6.68 +    if(!u) return;
    6.69 +    fprintf(dependency_file,",%d,%d",u->vp,u->task);
    6.70 +}
    6.71 +
    6.72 +void print_nton_to_file(void* _nton){
    6.73 +    NtoN* nton = (NtoN*) _nton;
    6.74 +    if(!nton) return;
    6.75 +    //assert(nton->senders->next_free_index==nton->receivers->next_free_index);
    6.76 +    int numInSet = nton->senders->next_free_index;
    6.77 +    fprintf(dependency_file,"NtoN,%d",numInSet);
    6.78 +    forAllInListOfArraysDo(nton->senders,&print_nton_set_helper);
    6.79 +    forAllInListOfArraysDo(nton->receivers,&print_nton_set_helper);
    6.80 +    fprintf(dependency_file,"\n");
    6.81 +}
    6.82 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/Measurement/dependency.h	Wed May 23 13:17:07 2012 -0700
     7.3 @@ -0,0 +1,56 @@
     7.4 +/* 
     7.5 + * File:   dependency.h
     7.6 + * Author: Nina Engelhardt
     7.7 + *
     7.8 + * Created on 29. August 2011, 17:41
     7.9 + */
    7.10 +
    7.11 +#ifndef  _DEPENDENCY_H
    7.12 +#define	_DEPENDENCY_H
    7.13 +
    7.14 +
    7.15 +#include <stdio.h>
    7.16 +#include "ListOfArrays/ListOfArrays.h"
    7.17 +
    7.18 +typedef struct {
    7.19 +    int vp;
    7.20 +    int task;
    7.21 +} Unit;
    7.22 +
    7.23 +typedef struct {
    7.24 +    int from_vp;
    7.25 +    int from_task;
    7.26 +    int to_vp;
    7.27 +    int to_task;
    7.28 +} Dependency; 
    7.29 +
    7.30 +typedef struct {
    7.31 +    int32 id;
    7.32 +    ListOfArrays* senders;
    7.33 +    ListOfArrays* receivers;
    7.34 +} NtoN;
    7.35 +
    7.36 +FILE* dependency_file;
    7.37 +
    7.38 +Dependency* new_dependency(int from_vp, int from_task, int to_vp, int to_task);
    7.39 +
    7.40 +NtoN* new_NtoN(int id);
    7.41 +
    7.42 +int set_dependency_file(FILE* file);
    7.43 +
    7.44 +void print_ctl_dependency_to_file(void* _dep);
    7.45 +
    7.46 +void print_comm_dependency_to_file(void* _dep);
    7.47 +
    7.48 +void print_dyn_dependency_to_file(void* _dep);
    7.49 +
    7.50 +void print_hw_dependency_to_file(void* _dep);
    7.51 +
    7.52 +void print_dependency_to_file(void* dep);
    7.53 +
    7.54 +void print_unit_to_file(void* unit);
    7.55 +
    7.56 +void print_nton_to_file(void* _nton);
    7.57 +
    7.58 +#endif	/* DEPENDENCY_H */
    7.59 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/VSs.c	Wed May 23 13:17:07 2012 -0700
     8.3 @@ -0,0 +1,772 @@
     8.4 +/*
     8.5 + * Copyright 2010  OpenSourceCodeStewardshipFoundation
     8.6 + *
     8.7 + * Licensed under BSD
     8.8 + */
     8.9 +
    8.10 +#include <stdio.h>
    8.11 +#include <stdlib.h>
    8.12 +#include <malloc.h>
    8.13 +
    8.14 +#include "Queue_impl/PrivateQueue.h"
    8.15 +#include "Hash_impl/PrivateHash.h"
    8.16 +
    8.17 +#include "VOMP.h"
    8.18 +#include "VOMP_Counter_Recording.h"
    8.19 +
    8.20 +//==========================================================================
    8.21 +
    8.22 +void
    8.23 +VOMP__init();
    8.24 +
    8.25 +void
    8.26 +VOMP__init_Helper();
    8.27 +//==========================================================================
    8.28 +
    8.29 +
    8.30 +
    8.31 +//===========================================================================
    8.32 +
    8.33 +
    8.34 +/*These are the library functions *called in the application*
    8.35 + * 
    8.36 + *There's a pattern for the outside sequential code to interact with the
    8.37 + * VMS_HW code.
    8.38 + *The VMS_HW system is inside a boundary..  every VOMP system is in its
    8.39 + * own directory that contains the functions for each of the processor types.
    8.40 + * One of the processor types is the "seed" processor that starts the
    8.41 + * cascade of creating all the processors that do the work.
    8.42 + *So, in the directory is a file called "EntryPoint.c" that contains the
    8.43 + * function, named appropriately to the work performed, that the outside
    8.44 + * sequential code calls.  This function follows a pattern:
    8.45 + *1) it calls VOMP__init()
    8.46 + *2) it creates the initial data for the seed processor, which is passed
    8.47 + *    in to the function
    8.48 + *3) it creates the seed VOMP processor, with the data to start it with.
    8.49 + *4) it calls startVOMPThenWaitUntilWorkDone
    8.50 + *5) it gets the returnValue from the transfer struc and returns that
    8.51 + *    from the function
    8.52 + *
    8.53 + *For now, a new VOMP system has to be created via VOMP__init every
    8.54 + * time an entry point function is called -- later, might add letting the
    8.55 + * VOMP system be created once, and let all the entry points just reuse
    8.56 + * it -- want to be as simple as possible now, and see by using what makes
    8.57 + * sense for later..
    8.58 + */
    8.59 +
    8.60 +
    8.61 +
    8.62 +//===========================================================================
    8.63 +
    8.64 +/*This is the "border crossing" function -- the thing that crosses from the
    8.65 + * outside world, into the VMS_HW world.  It initializes and starts up the
    8.66 + * VMS system, then creates one processor from the specified function and
    8.67 + * puts it into the readyQ.  From that point, that one function is resp.
    8.68 + * for creating all the other processors, that then create others, and so
    8.69 + * forth.
    8.70 + *When all the processors, including the seed, have dissipated, then this
    8.71 + * function returns.  The results will have been written by side-effect via
    8.72 + * pointers read from, or written into initData.
    8.73 + *
    8.74 + *NOTE: no Threads should exist in the outside program that might touch
    8.75 + * any of the data reachable from initData passed in to here
    8.76 + */
    8.77 +void
    8.78 +VOMP__create_seed_procr_and_do_work( TopLevelFnPtr fnPtr, void *initData )
    8.79 + { VOMPSemEnv *semEnv;
    8.80 +   SlaveVP *seedPr;
    8.81 +
    8.82 +   VOMP__init();      //normal multi-thd
    8.83 +   
    8.84 +   semEnv = _VMSMasterEnv->semanticEnv;
    8.85 +
    8.86 +      //VOMP starts with one processor, which is put into initial environ,
    8.87 +      // and which then calls create() to create more, thereby expanding work
    8.88 +   seedPr = VOMP__create_procr_helper( fnPtr, initData,
    8.89 +                                      semEnv, semEnv->nextCoreToGetNewPr++ );
    8.90 +
    8.91 +   resume_slaveVP( seedPr, semEnv );
    8.92 +   
    8.93 +   VMS_SS__start_the_work_then_wait_until_done();      //normal multi-thd
    8.94 +
    8.95 +   VOMP__cleanup_after_shutdown();
    8.96 + }
    8.97 +
    8.98 +
    8.99 +int32
   8.100 +VOMP__giveMinWorkUnitCycles( float32 percentOverhead )
   8.101 + {
   8.102 +   return MIN_WORK_UNIT_CYCLES;
   8.103 + }
   8.104 +
   8.105 +int32
   8.106 +VOMP__giveIdealNumWorkUnits()
   8.107 + {
   8.108 +   return NUM_ANIM_SLOTS * NUM_CORES;
   8.109 + }
   8.110 +
   8.111 +int32
   8.112 +VOMP__give_number_of_cores_to_schedule_onto()
   8.113 + {
   8.114 +   return NUM_CORES;
   8.115 + }
   8.116 +
   8.117 +/*For now, use TSC -- later, make these two macros with assembly that first
   8.118 + * saves jump point, and second jumps back several times to get reliable time
   8.119 + */
   8.120 +void
   8.121 +VOMP__start_primitive()
   8.122 + { saveLowTimeStampCountInto( ((VOMPSemEnv *)(_VMSMasterEnv->semanticEnv))->
   8.123 +                              primitiveStartTime );
   8.124 + }
   8.125 +
   8.126 +/*Just quick and dirty for now -- make reliable later
   8.127 + * will want this to jump back several times -- to be sure cache is warm
   8.128 + * because don't want comm time included in calc-time measurement -- and
   8.129 + * also to throw out any "weird" values due to OS interrupt or TSC rollover
   8.130 + */
   8.131 +int32
   8.132 +VOMP__end_primitive_and_give_cycles()
   8.133 + { int32 endTime, startTime;
   8.134 +   //TODO: fix by repeating time-measurement
   8.135 +   saveLowTimeStampCountInto( endTime );
   8.136 +   startTime =((VOMPSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime;
   8.137 +   return (endTime - startTime);
   8.138 + }
   8.139 +
   8.140 +//===========================================================================
   8.141 +
   8.142 +/*Initializes all the data-structures for a VOMP system -- but doesn't
   8.143 + * start it running yet!
   8.144 + *
   8.145 + *This runs in the main thread -- before VMS starts up
   8.146 + * 
   8.147 + *This sets up the semantic layer over the VMS system
   8.148 + *
   8.149 + *First, calls VMS_Setup, then creates own environment, making it ready
   8.150 + * for creating the seed processor and then starting the work.
   8.151 + */
   8.152 +void
   8.153 +VOMP__init()
   8.154 + {
   8.155 +   VMS_SS__init();
   8.156 +      //masterEnv, a global var, now is partially set up by init_VMS
   8.157 +      // after this, have VMS_int__malloc and VMS_int__free available
   8.158 +
   8.159 +   VOMP__init_Helper();
   8.160 + }
   8.161 +
   8.162 +
   8.163 +void idle_fn(void* data, SlaveVP *animatingSlv){
   8.164 +    while(1){
   8.165 +        VMS_int__suspend_slaveVP_and_send_req(animatingSlv);
   8.166 +    }
   8.167 +}
   8.168 +
   8.169 +void
   8.170 +VOMP__init_Helper()
   8.171 + { VOMPSemEnv       *semanticEnv;
   8.172 +   PrivQueueStruc **readyVPQs;
   8.173 +   int              coreIdx, i, j;
   8.174 + 
   8.175 +      //Hook up the semantic layer's plug-ins to the Master virt procr
   8.176 +   _VMSMasterEnv->requestHandler = &VOMP__Request_Handler;
   8.177 +   _VMSMasterEnv->slaveAssigner  = &VOMP__assign_slaveVP_to_slot;
   8.178 +   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
   8.179 +   _VMSMasterEnv->counterHandler = &VOMP__counter_handler;
   8.180 +   #endif
   8.181 +
   8.182 +      //create the semantic layer's environment (all its data) and add to
   8.183 +      // the master environment
   8.184 +   semanticEnv = VMS_int__malloc( sizeof( VOMPSemEnv ) );
   8.185 +   _VMSMasterEnv->semanticEnv = semanticEnv;
   8.186 +   
   8.187 +   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
   8.188 +   VOMP__init_counter_data_structs();
   8.189 +   #endif
   8.190 +   semanticEnv->shutdownInitiated = FALSE;
   8.191 +   for(i=0;i<NUM_CORES;++i){
   8.192 +       for(j=0;j<NUM_ANIM_SLOTS;++j){
   8.193 +           semanticEnv->idlePr[i][j] = VMS_int__create_slaveVP(&idle_fn,NULL);
   8.194 +           semanticEnv->idlePr[i][j]->coreAnimatedBy = i;
   8.195 +       }
   8.196 +   }
   8.197 +
   8.198 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   8.199 +   semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128);
   8.200 +   semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128);
   8.201 +   semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128);
   8.202 +   semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128);
   8.203 +   semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8);
   8.204 +   
   8.205 +   semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128);
   8.206 +   memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit)));
   8.207 +   #endif
   8.208 +
   8.209 +      //create the ready queue, hash tables used for pairing send to receive
   8.210 +      // and so forth
   8.211 +      //TODO: add hash tables for pairing sends with receives, and
   8.212 +      // initialize the data ownership system
   8.213 +   readyVPQs = VMS_int__malloc( NUM_CORES * sizeof(PrivQueueStruc *) );
   8.214 +
   8.215 +   for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
   8.216 +    {
   8.217 +      readyVPQs[ coreIdx ] = makeVMSQ();
   8.218 +    }
   8.219 +   
   8.220 +   semanticEnv->readyVPQs = readyVPQs;
   8.221 +   
   8.222 +   semanticEnv->nextCoreToGetNewPr = 0;
   8.223 +   semanticEnv->numSlaveVP = 0;
   8.224 +   
   8.225 +   semanticEnv->commHashTbl  = makeHashTable( 1<<16, &VMS_int__free );//start big
   8.226 +
   8.227 +   //TODO: bug -- turn these arrays into dyn arrays to eliminate limit
   8.228 +   //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( );
   8.229 +   //semanticEnv->transactionStrucs = makeDynArrayInfo( );
   8.230 +   for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ )
   8.231 +    {
   8.232 +      semanticEnv->fnSingletons[i].endInstrAddr      = NULL;
   8.233 +      semanticEnv->fnSingletons[i].hasBeenStarted    = FALSE;
   8.234 +      semanticEnv->fnSingletons[i].hasFinished       = FALSE;
   8.235 +      semanticEnv->fnSingletons[i].waitQ             = makeVMSQ();
   8.236 +      semanticEnv->transactionStrucs[i].waitingVPQ   = makeVMSQ();
   8.237 +    }
   8.238 + }
   8.239 +
   8.240 +
   8.241 +/*Frees any memory allocated by VOMP__init() then calls VMS_int__shutdown
   8.242 + */
   8.243 +void
   8.244 +VOMP__cleanup_after_shutdown()
   8.245 + { VOMPSemEnv *semanticEnv;
   8.246 +   
   8.247 +   semanticEnv = _VMSMasterEnv->semanticEnv;
   8.248 +
   8.249 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   8.250 +   //UCC
   8.251 +   FILE* output;
   8.252 +   int n;
   8.253 +   char filename[255];    
   8.254 +    for(n=0;n<255;n++)
   8.255 +    {
   8.256 +        sprintf(filename, "./counters/UCC.%d",n);
   8.257 +        output = fopen(filename,"r");
   8.258 +        if(output)
   8.259 +        {
   8.260 +            fclose(output);
   8.261 +        }else{
   8.262 +            break;
   8.263 +        }
   8.264 +    }
   8.265 +   if(n<255){
   8.266 +    printf("Saving UCC to File: %s ...\n", filename);
   8.267 +    output = fopen(filename,"w+");
   8.268 +    if(output!=NULL){
   8.269 +        set_dependency_file(output);
   8.270 +        //fprintf(output,"digraph Dependencies {\n");
   8.271 +        //set_dot_file(output);
   8.272 +        //FIXME:  first line still depends on counters being enabled, replace w/ unit struct!
   8.273 +        //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info );
   8.274 +        forAllInListOfArraysDo(semanticEnv->unitList, &print_unit_to_file);
   8.275 +        forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file );
   8.276 +        forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file );
   8.277 +        forAllInDynArrayDo(semanticEnv->ntonGroupsInfo,&print_nton_to_file);
   8.278 +        //fprintf(output,"}\n");
   8.279 +        fflush(output);
   8.280 +
   8.281 +    } else
   8.282 +        printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n");
   8.283 +   } else {
   8.284 +       printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n");
   8.285 +   }
   8.286 +   //Loop Graph
   8.287 +   for(n=0;n<255;n++)
   8.288 +    {
   8.289 +        sprintf(filename, "./counters/LoopGraph.%d",n);
   8.290 +        output = fopen(filename,"r");
   8.291 +        if(output)
   8.292 +        {
   8.293 +            fclose(output);
   8.294 +        }else{
   8.295 +            break;
   8.296 +        }
   8.297 +    }
   8.298 +   if(n<255){
   8.299 +    printf("Saving LoopGraph to File: %s ...\n", filename);
   8.300 +    output = fopen(filename,"w+");
   8.301 +    if(output!=NULL){
   8.302 +        set_dependency_file(output);
   8.303 +        //fprintf(output,"digraph Dependencies {\n");
   8.304 +        //set_dot_file(output);
   8.305 +        //FIXME:  first line still depends on counters being enabled, replace w/ unit struct!
   8.306 +        //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info );
   8.307 +        forAllInListOfArraysDo( semanticEnv->unitList, &print_unit_to_file );
   8.308 +        forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file );
   8.309 +        forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file );
   8.310 +        forAllInListOfArraysDo( semanticEnv->dynDependenciesList, &print_dyn_dependency_to_file );
   8.311 +        forAllInListOfArraysDo( semanticEnv->hwArcs, &print_hw_dependency_to_file );
   8.312 +        //fprintf(output,"}\n");
   8.313 +        fflush(output);
   8.314 +
   8.315 +    } else
   8.316 +        printf("Opening LoopGraph file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n");
   8.317 +   } else {
   8.318 +       printf("Could not open LoopGraph file, please clean \"counters\" folder. (Must contain less than 255 files.)\n");
   8.319 +   }
   8.320 +   
   8.321 +   
   8.322 +   freeListOfArrays(semanticEnv->unitList);
   8.323 +   freeListOfArrays(semanticEnv->commDependenciesList);
   8.324 +   freeListOfArrays(semanticEnv->ctlDependenciesList);
   8.325 +   freeListOfArrays(semanticEnv->dynDependenciesList);
   8.326 +   
   8.327 +   #endif
   8.328 +#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS    
   8.329 +    for(n=0;n<255;n++)
   8.330 +    {
   8.331 +        sprintf(filename, "./counters/Counters.%d.csv",n);
   8.332 +        output = fopen(filename,"r");
   8.333 +        if(output)
   8.334 +        {
   8.335 +            fclose(output);
   8.336 +        }else{
   8.337 +            break;
   8.338 +        }
   8.339 +    }
   8.340 +    if(n<255){
   8.341 +    printf("Saving Counter measurements to File: %s ...\n", filename);
   8.342 +    output = fopen(filename,"w+");
   8.343 +    if(output!=NULL){
   8.344 +        set_counter_file(output);
   8.345 +        int i;
   8.346 +        for(i=0;i<NUM_CORES;i++){
   8.347 +            forAllInListOfArraysDo( semanticEnv->counterList[i], &print_counter_events_to_file );
   8.348 +            fflush(output);
   8.349 +        }
   8.350 +
   8.351 +    } else
   8.352 +        printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n");
   8.353 +   } else {
   8.354 +       printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n");
   8.355 +   }
   8.356 +    
   8.357 +#endif
   8.358 +/* It's all allocated inside VMS's big chunk -- that's about to be freed, so
   8.359 + *  nothing to do here
   8.360 +   
   8.361 +
   8.362 +   for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ )
   8.363 +    {
   8.364 +      VMS_int__free( semanticEnv->readyVPQs[coreIdx]->startOfData );
   8.365 +      VMS_int__free( semanticEnv->readyVPQs[coreIdx] );
   8.366 +    }
   8.367 +   VMS_int__free( semanticEnv->readyVPQs );
   8.368 +   
   8.369 +   freeHashTable( semanticEnv->commHashTbl );
   8.370 +   VMS_int__free( _VMSMasterEnv->semanticEnv );
   8.371 + */
   8.372 +   VMS_SS__cleanup_at_end_of_shutdown();
   8.373 + }
   8.374 +
   8.375 +
   8.376 +//===========================================================================
   8.377 +
   8.378 +/*
   8.379 + */
   8.380 +  SlaveVP *
   8.381 +VOMP__create_procr_with( TopLevelFnPtr fnPtr,   void *initData,
   8.382 +                        SlaveVP *creatingPr )
   8.383 + { VOMPSemReq reqData;
   8.384 +
   8.385 +      //the semantic request data is on the stack and disappears when this
   8.386 +      // call returns -- it's guaranteed to remain in the VP's stack for as
   8.387 +      // long as the VP is suspended.
   8.388 +   reqData.reqType            = 0; //know type because in a VMS create req
   8.389 +   reqData.coreToAssignOnto = -1; //means round-robin assign
   8.390 +   reqData.fnPtr              = fnPtr;
   8.391 +   reqData.initData           = initData;
   8.392 +   reqData.sendPr             = creatingPr;
   8.393 +
   8.394 +   VMS_WL__send_create_slaveVP_req( &reqData, creatingPr );
   8.395 +
   8.396 +   return creatingPr->dataRetFromReq;
   8.397 + }
   8.398 +
   8.399 +  SlaveVP *
   8.400 +VOMP__create_procr_with_affinity( TopLevelFnPtr fnPtr, void *initData,
   8.401 +                        SlaveVP *creatingPr,  int32  coreToAssignOnto )
   8.402 + { VOMPSemReq  reqData;
   8.403 +
   8.404 +      //the semantic request data is on the stack and disappears when this
   8.405 +      // call returns -- it's guaranteed to remain in the VP's stack for as
   8.406 +      // long as the VP is suspended.
   8.407 +   reqData.reqType            = 0; //know type because in a VMS create req
   8.408 +   reqData.coreToAssignOnto = coreToAssignOnto;
   8.409 +   reqData.fnPtr              = fnPtr;
   8.410 +   reqData.initData           = initData;
   8.411 +   reqData.sendPr             = creatingPr;
   8.412 +
   8.413 +   VMS_WL__send_create_slaveVP_req( &reqData, creatingPr );
   8.414 +
   8.415 +   return creatingPr->dataRetFromReq;
   8.416 + }
   8.417 +
   8.418 +
   8.419 +  void
   8.420 +VOMP__dissipate_procr( SlaveVP *procrToDissipate )
   8.421 + {
   8.422 +   VMS_WL__send_dissipate_req( procrToDissipate );
   8.423 + }
   8.424 +
   8.425 +
   8.426 +//===========================================================================
   8.427 +
   8.428 +void *
   8.429 +VOMP__malloc_to( int32 sizeToMalloc, SlaveVP *owningPr )
   8.430 + { VOMPSemReq reqData;
   8.431 +
   8.432 +   reqData.reqType      = malloc_req;
   8.433 +   reqData.sendPr       = owningPr;
   8.434 +   reqData.sizeToMalloc = sizeToMalloc;
   8.435 +
   8.436 +   VMS_WL__send_sem_request( &reqData, owningPr );
   8.437 +
   8.438 +   return owningPr->dataRetFromReq;
   8.439 + }
   8.440 +
   8.441 +
   8.442 +/*Sends request to Master, which does the work of freeing
   8.443 + */
   8.444 +void
   8.445 +VOMP__free( void *ptrToFree, SlaveVP *owningPr )
   8.446 + { VOMPSemReq reqData;
   8.447 +
   8.448 +   reqData.reqType      = free_req;
   8.449 +   reqData.sendPr       = owningPr;
   8.450 +   reqData.ptrToFree    = ptrToFree;
   8.451 +
   8.452 +   VMS_WL__send_sem_request( &reqData, owningPr );
   8.453 + }
   8.454 +
   8.455 +
   8.456 +void
   8.457 +VOMP__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerSlv,
   8.458 +                                                  SlaveVP *newOwnerPr )
   8.459 + {
   8.460 +   //TODO: put in the ownership system that automatically frees when no
   8.461 +   // owners of data left -- will need keeper for keeping data around when
   8.462 +   // future created processors might need it but don't exist yet
   8.463 + }
   8.464 +
   8.465 +
   8.466 +void
   8.467 +VOMP__add_ownership_by_to( SlaveVP *newOwnerSlv, void *data )
   8.468 + {
   8.469 +
   8.470 + }
   8.471 +
   8.472 +
   8.473 +void
   8.474 +VOMP__remove_ownership_by_from( SlaveVP *loserSlv, void *dataLosing )
   8.475 + {
   8.476 +
   8.477 + }
   8.478 +
   8.479 +
   8.480 +/*Causes the VOMP system to remove internal ownership, so data won't be
   8.481 + * freed when VOMP shuts down, and will persist in the external program.
   8.482 + *
   8.483 + *Must be called from the processor that currently owns the data.
   8.484 + *
   8.485 + *IMPL: Transferring ownership touches two different virtual processor's
   8.486 + * state -- which means it has to be done carefully -- the VMS rules for
   8.487 + * semantic layers say that a work-unit is only allowed to touch the
   8.488 + * virtual processor it is part of, and that only a single work-unit per
   8.489 + * virtual processor be assigned to a slave at a time.  So, this has to
   8.490 + * modify the virtual processor that owns the work-unit that called this
   8.491 + * function, then create a request to have the other processor modified.
   8.492 + *However, in this case, the TO processor is the outside, and transfers
   8.493 + * are only allowed to be called by the giver-upper, so can mark caller of
   8.494 + * this function as no longer owner, and return -- done.
   8.495 + */
   8.496 +void
   8.497 +VOMP__transfer_ownership_to_outside( void *data )
   8.498 + {
   8.499 +   //TODO: removeAllOwnersFrom( data );
   8.500 + }
   8.501 +
   8.502 +
   8.503 +//===========================================================================
   8.504 +
   8.505 +void
   8.506 +VOMP__send_of_type_to( SlaveVP *sendPr, void *msg, const int type,
   8.507 +                        SlaveVP *receivePr)
   8.508 + { VOMPSemReq  reqData;
   8.509 +
   8.510 +   reqData.receivePr = receivePr;
   8.511 +   reqData.sendPr    = sendPr;
   8.512 +   reqData.reqType   = send_type;
   8.513 +   reqData.msgType   = type;
   8.514 +   reqData.msg       = msg;
   8.515 +   reqData.nextReqInHashEntry = NULL;
   8.516 +
   8.517 +      //On ownership -- remove inside the send and let ownership sit in limbo
   8.518 +      // as a potential in an entry in the hash table, when this receive msg
   8.519 +      // gets paired to a send, the ownership gets added to the receivePr --
   8.520 +      // the next work-unit in the receivePr's trace will have ownership.
   8.521 +   VMS_WL__send_sem_request( &reqData, sendPr );
   8.522 +
   8.523 +      //When come back from suspend, no longer own data reachable from msg
   8.524 +      //TODO: release ownership here
   8.525 + }
   8.526 +
   8.527 +void
   8.528 +VOMP__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr )
   8.529 + { VOMPSemReq  reqData;
   8.530 +
   8.531 +      //hash on the receiver, 'cause always know it, but sometimes want to
   8.532 +      // receive from anonymous sender
   8.533 +
   8.534 +   reqData.receivePr = receivePr;
   8.535 +   reqData.sendPr    = sendPr;
   8.536 +   reqData.reqType   = send_from_to;
   8.537 +   reqData.msg       = msg;
   8.538 +   reqData.nextReqInHashEntry = NULL;
   8.539 +
   8.540 +   VMS_WL__send_sem_request( &reqData, sendPr );
   8.541 + }
   8.542 +
   8.543 +
   8.544 +//===========================================================================
   8.545 +
   8.546 +void *
   8.547 +VOMP__receive_any_to( SlaveVP *receivePr )
   8.548 + {
   8.549 +
   8.550 + }
   8.551 +
   8.552 +void *
   8.553 +VOMP__receive_type_to( const int type, SlaveVP *receivePr )
   8.554 + {       DEBUG__printf1(dbgRqstHdlr,"WL: receive type to: %d", receivePr->slaveID);
   8.555 +   VOMPSemReq  reqData;
   8.556 +
   8.557 +   reqData.receivePr = receivePr;
   8.558 +   reqData.reqType   = receive_type;
   8.559 +   reqData.msgType   = type;
   8.560 +   reqData.nextReqInHashEntry = NULL;
   8.561 +
   8.562 +   VMS_WL__send_sem_request( &reqData, receivePr );
   8.563 +   
   8.564 +   return receivePr->dataRetFromReq;
   8.565 + }
   8.566 +
   8.567 +
   8.568 +
   8.569 +/*Call this at point receiving virt pr wants in-coming data.
   8.570 + * 
   8.571 + *The reason receivePr must call this is that it modifies the receivPr
   8.572 + * loc structure directly -- and the VMS rules state a virtual processor
   8.573 + * loc structure can only be modified by itself.
   8.574 + */
   8.575 +void *
   8.576 +VOMP__receive_from_to( SlaveVP *sendPr, SlaveVP *receivePr )
   8.577 + {       DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", sendPr->slaveID, receivePr->slaveID);
   8.578 +   VOMPSemReq  reqData;
   8.579 +
   8.580 +      //hash on the receiver, 'cause always know it, but sometimes want to
   8.581 +      // receive from anonymous sender
   8.582 +
   8.583 +   reqData.receivePr = receivePr;
   8.584 +   reqData.sendPr    = sendPr;
   8.585 +   reqData.reqType   = receive_from_to;
   8.586 +   reqData.nextReqInHashEntry = NULL;
   8.587 +
   8.588 +   VMS_WL__send_sem_request( &reqData, receivePr );
   8.589 +
   8.590 +   return receivePr->dataRetFromReq;
   8.591 + }
   8.592 +
   8.593 +
   8.594 +//===========================================================================
   8.595 +//
   8.596 +/*A function singleton is a function whose body executes exactly once, on a
   8.597 + * single core, no matter how many times the fuction is called and no
   8.598 + * matter how many cores or the timing of cores calling it.
   8.599 + *
   8.600 + *A data singleton is a ticket attached to data.  That ticket can be used
   8.601 + * to get the data through the function exactly once, no matter how many
   8.602 + * times the data is given to the function, and no matter the timing of
   8.603 + * trying to get the data through from different cores.
   8.604 + */
   8.605 +
   8.606 +/*asm function declarations*/
   8.607 +void asm_save_ret_to_singleton(VOMPSingleton *singletonPtrAddr);
   8.608 +void asm_write_ret_from_singleton(VOMPSingleton *singletonPtrAddr);
   8.609 +
   8.610 +/*Fn singleton uses ID as index into array of singleton structs held in the
   8.611 + * semantic environment.
   8.612 + */
   8.613 +void
   8.614 +VOMP__start_fn_singleton( int32 singletonID,   SlaveVP *animPr )
   8.615 + {
   8.616 +   VOMPSemReq  reqData;
   8.617 +
   8.618 +      //
   8.619 +   reqData.reqType     = singleton_fn_start;
   8.620 +   reqData.singletonID = singletonID;
   8.621 +
   8.622 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.623 +   if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton
   8.624 +    {
   8.625 +       VOMPSemEnv *semEnv = VMS_int__give_sem_env_for( animPr );
   8.626 +       asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID]));
   8.627 +    }
   8.628 + }
   8.629 +
   8.630 +/*Data singleton hands addr of loc holding a pointer to a singleton struct.
   8.631 + * The start_data_singleton makes the structure and puts its addr into the
   8.632 + * location.
   8.633 + */
   8.634 +void
   8.635 +VOMP__start_data_singleton( VOMPSingleton **singletonAddr,  SlaveVP *animPr )
   8.636 + {
   8.637 +   VOMPSemReq  reqData;
   8.638 +
   8.639 +   if( *singletonAddr && (*singletonAddr)->hasFinished )
   8.640 +       goto JmpToEndSingleton;
   8.641 +   
   8.642 +   reqData.reqType          = singleton_data_start;
   8.643 +   reqData.singletonPtrAddr = singletonAddr;
   8.644 +
   8.645 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.646 +   if( animPr->dataRetFromReq ) //either 0 or end singleton's return addr
   8.647 +    {    //Assembly code changes the return addr on the stack to the one
   8.648 +         // saved into the singleton by the end-singleton-fn
   8.649 +         //The return addr is at 0x4(%%ebp)
   8.650 +        JmpToEndSingleton:
   8.651 +          asm_write_ret_from_singleton(*singletonAddr);
   8.652 +    }
   8.653 +   //now, simply return
   8.654 +   //will exit either from the start singleton call or the end-singleton call
   8.655 + }
   8.656 +
   8.657 +/*Uses ID as index into array of flags.  If flag already set, resumes from
   8.658 + * end-label.  Else, sets flag and resumes normally.
   8.659 + *
   8.660 + *Note, this call cannot be inlined because the instr addr at the label
   8.661 + * inside is shared by all invocations of a given singleton ID.
   8.662 + */
   8.663 +void
   8.664 +VOMP__end_fn_singleton( int32 singletonID, SlaveVP *animPr )
   8.665 + {
   8.666 +   VOMPSemReq  reqData;
   8.667 +
   8.668 +      //don't need this addr until after at least one singleton has reached
   8.669 +      // this function
   8.670 +   VOMPSemEnv *semEnv = VMS_int__give_sem_env_for( animPr );
   8.671 +   asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID]));
   8.672 +
   8.673 +   reqData.reqType     = singleton_fn_end;
   8.674 +   reqData.singletonID = singletonID;
   8.675 +
   8.676 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.677 +
   8.678 +EndSingletonInstrAddr:
   8.679 +   return;
   8.680 + }
   8.681 +
   8.682 +void
   8.683 +VOMP__end_data_singleton(  VOMPSingleton **singletonPtrAddr, SlaveVP *animPr )
   8.684 + {
   8.685 +   VOMPSemReq  reqData;
   8.686 +
   8.687 +      //don't need this addr until after singleton struct has reached
   8.688 +      // this function for first time
   8.689 +      //do assembly that saves the return addr of this fn call into the
   8.690 +      // data singleton -- that data-singleton can only be given to exactly
   8.691 +      // one instance in the code of this function.  However, can use this
   8.692 +      // function in different places for different data-singletons.
   8.693 +//   (*(singletonAddr))->endInstrAddr =  &&EndDataSingletonInstrAddr;
   8.694 +
   8.695 +
   8.696 +   asm_save_ret_to_singleton(*singletonPtrAddr);
   8.697 +
   8.698 +   reqData.reqType          = singleton_data_end;
   8.699 +   reqData.singletonPtrAddr = singletonPtrAddr;
   8.700 +
   8.701 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.702 + }
   8.703 +
   8.704 +/*This executes the function in the masterVP, so it executes in isolation
   8.705 + * from any other copies -- only one copy of the function can ever execute
   8.706 + * at a time.
   8.707 + *
   8.708 + *It suspends to the master, and the request handler takes the function
   8.709 + * pointer out of the request and calls it, then resumes the VP.
   8.710 + *Only very short functions should be called this way -- for longer-running
   8.711 + * isolation, use transaction-start and transaction-end, which run the code
   8.712 + * between as work-code.
   8.713 + */
   8.714 +void
   8.715 +VOMP__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
   8.716 +                                    void *data, SlaveVP *animPr )
   8.717 + {
   8.718 +   VOMPSemReq  reqData;
   8.719 +
   8.720 +      //
   8.721 +   reqData.reqType          = atomic;
   8.722 +   reqData.fnToExecInMaster = ptrToFnToExecInMaster;
   8.723 +   reqData.dataForFn        = data;
   8.724 +
   8.725 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.726 + }
   8.727 +
   8.728 +
   8.729 +/*This suspends to the master.
   8.730 + *First, it looks at the VP's data, to see the highest transactionID that VP
   8.731 + * already has entered.  If the current ID is not larger, it throws an
   8.732 + * exception stating a bug in the code.  Otherwise it puts the current ID
   8.733 + * there, and adds the ID to a linked list of IDs entered -- the list is
   8.734 + * used to check that exits are properly ordered.
   8.735 + *Next it is uses transactionID as index into an array of transaction
   8.736 + * structures.
   8.737 + *If the "VP_currently_executing" field is non-null, then put requesting VP
   8.738 + * into queue in the struct.  (At some point a holder will request
   8.739 + * end-transaction, which will take this VP from the queue and resume it.)
   8.740 + *If NULL, then write requesting into the field and resume.
   8.741 + */
   8.742 +void
   8.743 +VOMP__start_transaction( int32 transactionID, SlaveVP *animPr )
   8.744 + {
   8.745 +   VOMPSemReq  reqData;
   8.746 +
   8.747 +      //
   8.748 +   reqData.sendPr      = animPr;
   8.749 +   reqData.reqType     = trans_start;
   8.750 +   reqData.transID     = transactionID;
   8.751 +
   8.752 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.753 + }
   8.754 +
   8.755 +/*This suspends to the master, then uses transactionID as index into an
   8.756 + * array of transaction structures.
   8.757 + *It looks at VP_currently_executing to be sure it's same as requesting VP.
   8.758 + * If different, throws an exception, stating there's a bug in the code.
   8.759 + *Next it looks at the queue in the structure.
   8.760 + *If it's empty, it sets VP_currently_executing field to NULL and resumes.
   8.761 + *If something in, gets it, sets VP_currently_executing to that VP, then
   8.762 + * resumes both.
   8.763 + */
   8.764 +void
   8.765 +VOMP__end_transaction( int32 transactionID, SlaveVP *animPr )
   8.766 + {
   8.767 +   VOMPSemReq  reqData;
   8.768 +
   8.769 +      //
   8.770 +   reqData.sendPr      = animPr;
   8.771 +   reqData.reqType     = trans_end;
   8.772 +   reqData.transID     = transactionID;
   8.773 +
   8.774 +   VMS_WL__send_sem_request( &reqData, animPr );
   8.775 + }
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/VSs.h	Wed May 23 13:17:07 2012 -0700
     9.3 @@ -0,0 +1,268 @@
     9.4 +/*
     9.5 + *  Copyright 2009 OpenSourceStewardshipFoundation.org
     9.6 + *  Licensed under GNU General Public License version 2
     9.7 + *
     9.8 + * Author: seanhalle@yahoo.com
     9.9 + *
    9.10 + */
    9.11 +
    9.12 +#ifndef _VOMP_H
    9.13 +#define	_VOMP_H
    9.14 +
    9.15 +#include "Queue_impl/PrivateQueue.h"
    9.16 +#include "Hash_impl/PrivateHash.h"
    9.17 +#include "VMS_impl/VMS.h"
    9.18 +#include "dependency.h"
    9.19 +
    9.20 +
    9.21 +//===========================================================================
    9.22 +#define NUM_STRUCS_IN_SEM_ENV 1000
    9.23 +
    9.24 +   //This is hardware dependent -- it's the number of cycles of scheduling
    9.25 +   // overhead -- if a work unit is fewer than this, it is better being
    9.26 +   // combined sequentially with other work
    9.27 +   //This value depends on both VMS overhead and VOMP's plugin.  At some point
    9.28 +   // it will be derived by perf-counter measurements during init of VOMP
    9.29 +#define MIN_WORK_UNIT_CYCLES 20000
    9.30 +
    9.31 +//===========================================================================
    9.32 +/*This header defines everything specific to the VOMP semantic plug-in
    9.33 + */
    9.34 +typedef struct _VOMPSemReq   VOMPSemReq;
    9.35 +typedef void  (*PtrToAtomicFn )   ( void * ); //executed atomically in master
    9.36 +//===========================================================================
    9.37 +
    9.38 +/*Semantic layer-specific data sent inside a request from lib called in app
    9.39 + * to request handler called in AnimationMaster
    9.40 + */
    9.41 +
    9.42 +typedef struct
    9.43 + {
    9.44 +   SlaveVP      *VPCurrentlyExecuting;
    9.45 +   PrivQueueStruc *waitingVPQ;
    9.46 + }
    9.47 +VOMPTrans;
    9.48 +
    9.49 +/*WARNING: assembly hard-codes position of endInstrAddr as first field
    9.50 + */
    9.51 +typedef struct
    9.52 + {
    9.53 +   void           *endInstrAddr;
    9.54 +   int32           hasBeenStarted;
    9.55 +   int32           hasFinished;
    9.56 +   PrivQueueStruc *waitQ;
    9.57 + }
    9.58 +VOMPSingleton;
    9.59 +
    9.60 +enum VOMPReqType
    9.61 + {
    9.62 +   send_type = 1,
    9.63 +   send_from_to,
    9.64 +   receive_any,    //order and grouping matter -- send before receive
    9.65 +   receive_type,   // and receive_any first of the receives -- Handlers
    9.66 +   receive_from_to,// rely upon this ordering of enum
    9.67 +   transfer_to,
    9.68 +   transfer_out,
    9.69 +   malloc_req,
    9.70 +   free_req,
    9.71 +   singleton_fn_start,
    9.72 +   singleton_fn_end,
    9.73 +   singleton_data_start,
    9.74 +   singleton_data_end,
    9.75 +   atomic,
    9.76 +   trans_start,
    9.77 +   trans_end
    9.78 + };
    9.79 +
    9.80 +struct _VOMPSemReq
    9.81 + { enum VOMPReqType    reqType;
    9.82 +   SlaveVP         *sendPr;
    9.83 +   SlaveVP         *receivePr;
    9.84 +   int32              msgType;
    9.85 +   void              *msg;
    9.86 +   VOMPSemReq         *nextReqInHashEntry;
    9.87 +
    9.88 +   void              *initData;
    9.89 +   TopLevelFnPtr     fnPtr;
    9.90 +   int32              coreToAssignOnto;
    9.91 +
    9.92 +   int32              sizeToMalloc;
    9.93 +   void              *ptrToFree;
    9.94 +
    9.95 +   int32              singletonID;
    9.96 +   VOMPSingleton     **singletonPtrAddr;
    9.97 +
    9.98 +   PtrToAtomicFn      fnToExecInMaster;
    9.99 +   void              *dataForFn;
   9.100 +
   9.101 +   int32              transID;
   9.102 + }
   9.103 +/* VOMPSemReq */;
   9.104 +
   9.105 +
   9.106 +typedef struct
   9.107 + {
   9.108 +   PrivQueueStruc **readyVPQs;
   9.109 +   HashTable       *commHashTbl;
   9.110 +   int32            numSlaveVP;
   9.111 +   int32            nextCoreToGetNewPr;
   9.112 +   int32            primitiveStartTime;
   9.113 +
   9.114 +                       //fix limit on num with dynArray
   9.115 +   VOMPSingleton     fnSingletons[NUM_STRUCS_IN_SEM_ENV];
   9.116 +   VOMPTrans         transactionStrucs[NUM_STRUCS_IN_SEM_ENV];
   9.117 +   
   9.118 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   9.119 +   ListOfArrays* unitList;
   9.120 +   ListOfArrays* ctlDependenciesList;
   9.121 +   ListOfArrays* commDependenciesList;
   9.122 +   NtoN** ntonGroups;
   9.123 +   PrivDynArrayInfo* ntonGroupsInfo;
   9.124 +   ListOfArrays* dynDependenciesList;
   9.125 +   Unit last_in_slot[NUM_CORES * NUM_ANIM_SLOTS];
   9.126 +   ListOfArrays* hwArcs;
   9.127 +   #endif
   9.128 +
   9.129 +   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
   9.130 +   ListOfArrays* counterList[NUM_CORES];
   9.131 +   #endif
   9.132 +   SlaveVP* idlePr[NUM_CORES][NUM_ANIM_SLOTS];
   9.133 +   int shutdownInitiated;
   9.134 + }
   9.135 +VOMPSemEnv;
   9.136 +
   9.137 +
   9.138 +typedef struct _TransListElem TransListElem;
   9.139 +struct _TransListElem
   9.140 + {
   9.141 +   int32          transID;
   9.142 +   TransListElem *nextTrans;
   9.143 + };
   9.144 +//TransListElem
   9.145 + 
   9.146 +typedef struct
   9.147 + {
   9.148 +   int32          highestTransEntered;
   9.149 +   TransListElem *lastTransEntered;
   9.150 + }
   9.151 +VOMPSemData;
   9.152 + 
   9.153 +//===========================================================================
   9.154 +
   9.155 +void
   9.156 +VOMP__create_seed_procr_and_do_work( TopLevelFnPtr fn, void *initData );
   9.157 +
   9.158 +int32
   9.159 +VOMP__giveMinWorkUnitCycles( float32 percentOverhead );
   9.160 +
   9.161 +void
   9.162 +VOMP__start_primitive();
   9.163 +
   9.164 +int32
   9.165 +VOMP__end_primitive_and_give_cycles();
   9.166 +
   9.167 +int32
   9.168 +VOMP__giveIdealNumWorkUnits();
   9.169 +
   9.170 +int32
   9.171 +VOMP__give_number_of_cores_to_schedule_onto();
   9.172 +
   9.173 +//=======================
   9.174 +
   9.175 +void
   9.176 +VOMP__init();
   9.177 +
   9.178 +void
   9.179 +VOMP__cleanup_after_shutdown();
   9.180 +
   9.181 +//=======================
   9.182 +
   9.183 +  SlaveVP *
   9.184 +VOMP__create_procr_with( TopLevelFnPtr fnPtr, void *initData,
   9.185 +                          SlaveVP *creatingSlv );
   9.186 +
   9.187 +  SlaveVP *
   9.188 +VOMP__create_procr_with_affinity( TopLevelFnPtr fnPtr,    void *initData,
   9.189 +                            SlaveVP *creatingPr, int32 coreToAssignOnto);
   9.190 +
   9.191 +void
   9.192 +VOMP__dissipate_procr( SlaveVP *procrToDissipate );
   9.193 +
   9.194 +//=======================
   9.195 +void *
   9.196 +VOMP__malloc_to( int numBytes, SlaveVP *ownerSlv );
   9.197 +
   9.198 +void
   9.199 +VOMP__free( void *ptrToFree, SlaveVP *owningSlv );
   9.200 +
   9.201 +void
   9.202 +VOMP__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerPr,
   9.203 +                                                    SlaveVP *newOwnerSlv );
   9.204 +                                                    
   9.205 +void
   9.206 +VOMP__add_ownership_by_to( SlaveVP *newOwnerPr, void *data );
   9.207 +
   9.208 +void
   9.209 +VOMP__remove_ownership_by_from( SlaveVP *loserPr, void *dataLosing );
   9.210 +
   9.211 +void
   9.212 +VOMP__transfer_ownership_to_outside( void *dataToTransferOwnershipOf );
   9.213 +
   9.214 +
   9.215 +
   9.216 +//=======================
   9.217 +void
   9.218 +VOMP__send_of_type_to( SlaveVP *sendPr, void *msg, const int type,
   9.219 +                        SlaveVP *receivePr);
   9.220 +
   9.221 +void
   9.222 +VOMP__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr);
   9.223 +
   9.224 +void *
   9.225 +VOMP__receive_type_to( const int type, SlaveVP *receiveSlv );
   9.226 +
   9.227 +void *
   9.228 +VOMP__receive_from_to( SlaveVP *sendPr, SlaveVP *receiveSlv );
   9.229 +
   9.230 +
   9.231 +//======================= Concurrency Stuff ======================
   9.232 +void
   9.233 +VOMP__start_fn_singleton( int32 singletonID, SlaveVP *animSlv );
   9.234 +
   9.235 +void
   9.236 +VOMP__end_fn_singleton( int32 singletonID, SlaveVP *animSlv );
   9.237 +
   9.238 +void
   9.239 +VOMP__start_data_singleton( VOMPSingleton **singeltonAddr, SlaveVP *animSlv );
   9.240 +
   9.241 +void
   9.242 +VOMP__end_data_singleton( VOMPSingleton **singletonAddr, SlaveVP *animSlv );
   9.243 +
   9.244 +void
   9.245 +VOMP__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
   9.246 +                                    void *data, SlaveVP *animSlv );
   9.247 +
   9.248 +void
   9.249 +VOMP__start_transaction( int32 transactionID, SlaveVP *animSlv );
   9.250 +
   9.251 +void
   9.252 +VOMP__end_transaction( int32 transactionID, SlaveVP *animSlv );
   9.253 +
   9.254 +
   9.255 +//=========================  Internal use only  =============================
   9.256 +void
   9.257 +VOMP__Request_Handler( SlaveVP *requestingPr, void *_semEnv );
   9.258 +
   9.259 +SlaveVP *
   9.260 +VOMP__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot );
   9.261 +
   9.262 +SlaveVP*
   9.263 +VOMP__create_procr_helper( TopLevelFnPtr fnPtr, void *initData,
   9.264 +                          VOMPSemEnv *semEnv,    int32 coreToAssignOnto );
   9.265 +
   9.266 +//=====================  Measurement of Lang Overheads  =====================
   9.267 +#include "VOMP_Measurement.h"
   9.268 +
   9.269 +//===========================================================================
   9.270 +#endif	/* _VOMP_H */
   9.271 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/VSs_PluginFns.c	Wed May 23 13:17:07 2012 -0700
    10.3 @@ -0,0 +1,302 @@
    10.4 +/*
    10.5 + * Copyright 2010  OpenSourceCodeStewardshipFoundation
    10.6 + *
    10.7 + * Licensed under BSD
    10.8 + */
    10.9 +
   10.10 +#include <stdio.h>
   10.11 +#include <stdlib.h>
   10.12 +
   10.13 +#include "Queue_impl/PrivateQueue.h"
   10.14 +#include "VOMP.h"
   10.15 +#include "VOMP_Request_Handlers.h"
   10.16 +
   10.17 +//=========================== Local Fn Prototypes ===========================
   10.18 +void
   10.19 +resume_slaveVP( SlaveVP *procr, VOMPSemEnv *semEnv );
   10.20 +
   10.21 +void
   10.22 +handleSemReq( VMSReqst *req, SlaveVP *requestingPr, VOMPSemEnv *semEnv );
   10.23 +
   10.24 +void
   10.25 +handleDissipate(             SlaveVP *requestingPr, VOMPSemEnv *semEnv );
   10.26 +
   10.27 +void
   10.28 +handleCreate( VMSReqst *req, SlaveVP *requestingPr, VOMPSemEnv *semEnv  );
   10.29 +
   10.30 +
   10.31 +//============================== Assigner ==================================
   10.32 +//
   10.33 +/*For VOMP, assigning a slave simply takes the next work-unit off the
   10.34 + * ready-to-go work-unit queue and assigns it to the offered slot.
   10.35 + *If the ready-to-go work-unit queue is empty, then nothing to assign
   10.36 + * to the animation slot -- return FALSE to let Master loop know assigning
   10.37 + * that slot failed.
   10.38 + */
   10.39 +SlaveVP *
   10.40 +VOMP__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot )
   10.41 + { SlaveVP   *assignPr;
   10.42 +   VOMPSemEnv *semEnv;
   10.43 +   int32      coreNum, slotNum;
   10.44 +   
   10.45 +   coreNum = slot->coreSlotIsOn;
   10.46 +   slotNum = slot->slotIdx;
   10.47 +   
   10.48 +   semEnv  = (VOMPSemEnv *)_semEnv;
   10.49 +
   10.50 +   assignPr = readPrivQ( semEnv->readyVPQs[coreNum] );
   10.51 +      //Note, using a non-blocking queue -- it returns NULL if queue empty
   10.52 +  if(!assignPr){
   10.53 +       assignPr = semEnv->idlePr[coreNum][slotNum];
   10.54 +      
   10.55 +      if(semEnv->shutdownInitiated) {
   10.56 +          assignPr = VMS_SS__create_shutdown_slave();
   10.57 +      }
   10.58 +     //things that would normally happen in resume(), but these VPs never go there
   10.59 +     #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   10.60 +        assignPr->assignCount++; //Somewhere here!
   10.61 +        Unit newu;
   10.62 +        newu.vp = assignPr->slaveID;
   10.63 +        newu.task = assignPr->assignCount;
   10.64 +        addToListOfArrays(Unit,newu,semEnv->unitList);
   10.65 +   
   10.66 +        if (assignPr->assignCount > 1){
   10.67 +                Dependency newd;
   10.68 +                newd.from_vp = assignPr->slaveID;
   10.69 +                newd.from_task = assignPr->assignCount - 1;
   10.70 +                newd.to_vp = assignPr->slaveID;
   10.71 +                newd.to_task = assignPr->assignCount;
   10.72 +                addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList);  
   10.73 +        }
   10.74 +      #endif
   10.75 +   }
   10.76 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
   10.77 +   if (assignPr) {
   10.78 +        //assignPr->numTimesAssigned++;
   10.79 +        Unit prev_in_slot = semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum];
   10.80 +        if(prev_in_slot.vp != 0){
   10.81 +                Dependency newd;
   10.82 +                newd.from_vp = prev_in_slot.vp;
   10.83 +                newd.from_task = prev_in_slot.task;
   10.84 +                newd.to_vp = assignPr->slaveID;
   10.85 +                newd.to_task = assignPr->assignCount;
   10.86 +                addToListOfArrays(Dependency,newd,semEnv->hwArcs);   
   10.87 +        }
   10.88 +        prev_in_slot.vp = assignPr->slaveID;
   10.89 +        prev_in_slot.task = assignPr->assignCount;
   10.90 +        semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = prev_in_slot;        
   10.91 +   }
   10.92 +   #endif
   10.93 +   return( assignPr );
   10.94 + }
   10.95 +
   10.96 +
   10.97 +//===========================  Request Handler  =============================
   10.98 +//
   10.99 +/*Will get requests to send, to receive, and to create new processors.
  10.100 + * Upon send, check the hash to see if a receive is waiting.
  10.101 + * Upon receive, check hash to see if a send has already happened.
  10.102 + * When other is not there, put in.  When other is there, the comm.
  10.103 + *  completes, which means the receiver P gets assigned and
  10.104 + *  picks up right after the receive request.  So make the work-unit
  10.105 + *  and put it into the queue of work-units ready to go.
  10.106 + * Other request is create a new Processor, with the function to run in the
  10.107 + *  Processor, and initial data.
  10.108 + */
  10.109 +void
  10.110 +VOMP__Request_Handler( SlaveVP *requestingPr, void *_semEnv )
  10.111 + { VOMPSemEnv *semEnv;
  10.112 +   VMSReqst    *req;
  10.113 +   
  10.114 +   semEnv = (VOMPSemEnv *)_semEnv;
  10.115 +
  10.116 +   req    = VMS_PI__take_next_request_out_of( requestingPr );
  10.117 +
  10.118 +   while( req != NULL )
  10.119 +    {
  10.120 +      switch( req->reqType )
  10.121 +       { case semantic:     handleSemReq(         req, requestingPr, semEnv);
  10.122 +            break;
  10.123 +         case createReq:    handleCreate(         req, requestingPr, semEnv);
  10.124 +            break;
  10.125 +         case dissipate:    handleDissipate(           requestingPr, semEnv);
  10.126 +            break;
  10.127 +         case VMSSemantic:  VMS_PI__handle_VMSSemReq(req, requestingPr, semEnv,
  10.128 +                                             (ResumeSlvFnPtr) &resume_slaveVP);
  10.129 +            break;
  10.130 +         default:
  10.131 +            break;
  10.132 +       }
  10.133 +      
  10.134 +      req = VMS_PI__take_next_request_out_of( requestingPr );
  10.135 +    } //while( req != NULL )
  10.136 +
  10.137 + }
  10.138 +
  10.139 +
  10.140 +void
  10.141 +handleSemReq( VMSReqst *req, SlaveVP *reqPr, VOMPSemEnv *semEnv )
  10.142 + { VOMPSemReq *semReq;
  10.143 +
  10.144 +   semReq = VMS_PI__take_sem_reqst_from(req);
  10.145 +   if( semReq == NULL ) return;
  10.146 +   switch( semReq->reqType )  //sem handlers are all in other file
  10.147 +    {
  10.148 +      case send_type:       handleSendType(     semReq,        semEnv);
  10.149 +         break;
  10.150 +      case send_from_to:    handleSendFromTo(   semReq,        semEnv);
  10.151 +         break;
  10.152 +      case receive_type:    handleReceiveType(  semReq,        semEnv);
  10.153 +         break;
  10.154 +      case receive_from_to: handleReceiveFromTo(semReq,        semEnv);
  10.155 +         break;
  10.156 +      case transfer_to:     handleTransferTo(   semReq,        semEnv);
  10.157 +         break;
  10.158 +      case transfer_out:    handleTransferOut(  semReq,        semEnv);
  10.159 +         break;
  10.160 +      case malloc_req:      handleMalloc(       semReq, reqPr, semEnv);
  10.161 +         break;
  10.162 +      case free_req:        handleFree(         semReq, reqPr, semEnv);
  10.163 +         break;
  10.164 +      case singleton_fn_start:  handleStartFnSingleton(semReq, reqPr, semEnv);
  10.165 +         break;
  10.166 +      case singleton_fn_end:    handleEndFnSingleton(  semReq, reqPr, semEnv);
  10.167 +         break;
  10.168 +      case singleton_data_start:handleStartDataSingleton(semReq,reqPr,semEnv);
  10.169 +         break;
  10.170 +      case singleton_data_end:  handleEndDataSingleton(semReq, reqPr, semEnv);
  10.171 +         break;
  10.172 +      case atomic:          handleAtomic(       semReq, reqPr, semEnv);
  10.173 +         break;
  10.174 +      case trans_start:     handleTransStart(   semReq, reqPr, semEnv);
  10.175 +         break;
  10.176 +      case trans_end:       handleTransEnd(     semReq, reqPr, semEnv);
  10.177 +         break;
  10.178 +    }
  10.179 + }
  10.180 +
  10.181 +
  10.182 +
  10.183 +//=========================== VMS Request Handlers ==============================
  10.184 +//
  10.185 +void
  10.186 +handleDissipate( SlaveVP *requestingPr, VOMPSemEnv *semEnv )
  10.187 + {
  10.188 +    DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d",requestingPr->slaveID)
  10.189 +      //free any semantic data allocated to the virt procr
  10.190 +   VMS_PI__free( requestingPr->semanticData );
  10.191 +
  10.192 +      //Now, call VMS to free_all AppVP state -- stack and so on
  10.193 +   VMS_PI__dissipate_slaveVP( requestingPr );
  10.194 +
  10.195 +   semEnv->numSlaveVP -= 1;
  10.196 +   if( semEnv->numSlaveVP == 0 )
  10.197 +    {    //no more work, so shutdown
  10.198 +       semEnv->shutdownInitiated = TRUE;
  10.199 +      //VMS_SS__shutdown();
  10.200 +    }
  10.201 + }
  10.202 +
  10.203 +/*Re-use this in the entry-point fn
  10.204 + */
  10.205 +  SlaveVP *
  10.206 +VOMP__create_procr_helper( TopLevelFnPtr fnPtr, void *initData,
  10.207 +                          VOMPSemEnv *semEnv,    int32 coreToAssignOnto )
  10.208 + { SlaveVP    *newPr;
  10.209 +   VOMPSemData   *semData;
  10.210 +
  10.211 +      //This is running in master, so use internal version
  10.212 +   newPr = VMS_PI__create_slaveVP( fnPtr, initData );
  10.213 +
  10.214 +   semEnv->numSlaveVP += 1;
  10.215 +
  10.216 +   semData = VMS_PI__malloc( sizeof(VOMPSemData) );
  10.217 +   semData->highestTransEntered = -1;
  10.218 +   semData->lastTransEntered    = NULL;
  10.219 +
  10.220 +   newPr->semanticData = semData;
  10.221 +
  10.222 +   //=================== Assign new processor to a core =====================
  10.223 +   #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
  10.224 +   newPr->coreAnimatedBy = 0;
  10.225 +
  10.226 +   #else
  10.227 +
  10.228 +   if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES )
  10.229 +    {    //out-of-range, so round-robin assignment
  10.230 +      newPr->coreAnimatedBy = semEnv->nextCoreToGetNewPr;
  10.231 +
  10.232 +      if( semEnv->nextCoreToGetNewPr >= NUM_CORES - 1 )
  10.233 +          semEnv->nextCoreToGetNewPr  = 0;
  10.234 +      else
  10.235 +          semEnv->nextCoreToGetNewPr += 1;
  10.236 +    }
  10.237 +   else //core num in-range, so use it
  10.238 +    { newPr->coreAnimatedBy = coreToAssignOnto;
  10.239 +    }
  10.240 +   #endif
  10.241 +   //========================================================================
  10.242 +
  10.243 +   return newPr;
  10.244 + }
  10.245 +
  10.246 +void
  10.247 +handleCreate( VMSReqst *req, SlaveVP *requestingPr, VOMPSemEnv *semEnv  )
  10.248 + { VOMPSemReq *semReq;
  10.249 +   SlaveVP    *newPr;
  10.250 +   
  10.251 +   
  10.252 +   semReq = VMS_PI__take_sem_reqst_from( req );
  10.253 + 
  10.254 +   newPr = VOMP__create_procr_helper( semReq->fnPtr, semReq->initData, semEnv,
  10.255 +                                     semReq->coreToAssignOnto );
  10.256 +   
  10.257 +         DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d", requestingPr->slaveID, newPr->slaveID)
  10.258 +
  10.259 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  10.260 +   Dependency newd;
  10.261 +   newd.from_vp = requestingPr->slaveID;
  10.262 +   newd.from_task = requestingPr->assignCount;
  10.263 +   newd.to_vp = newPr->slaveID;
  10.264 +   newd.to_task = 1;
  10.265 +   //addToListOfArraysDependency(newd,semEnv->commDependenciesList);  
  10.266 +   addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);   
  10.267 +   #endif
  10.268 +
  10.269 +      //For VOMP, caller needs ptr to created processor returned to it
  10.270 +   requestingPr->dataRetFromReq = newPr;
  10.271 +
  10.272 +   resume_slaveVP( newPr,        semEnv );
  10.273 +   resume_slaveVP( requestingPr, semEnv );
  10.274 + }
  10.275 +
  10.276 +
  10.277 +//=========================== Helper ==============================
  10.278 +void
  10.279 +resume_slaveVP( SlaveVP *procr, VOMPSemEnv *semEnv )
  10.280 + {
  10.281 +   #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS
  10.282 +/*
  10.283 +   int lastRecordIdx = procr->counter_history_array_info->numInArray -1;
  10.284 +   CounterRecord* lastRecord = procr->counter_history[lastRecordIdx];
  10.285 +   saveLowTimeStampCountInto(lastRecord->unblocked_timestamp);
  10.286 +*/
  10.287 +   #endif
  10.288 +   #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  10.289 +   procr->assignCount++; //Somewhere here!
  10.290 +   Unit newu;
  10.291 +   newu.vp = procr->slaveID;
  10.292 +   newu.task = procr->assignCount;
  10.293 +   addToListOfArrays(Unit,newu,semEnv->unitList);
  10.294 +   
  10.295 +   if (procr->assignCount > 1){
  10.296 +        Dependency newd;
  10.297 +        newd.from_vp = procr->slaveID;
  10.298 +        newd.from_task = procr->assignCount - 1;
  10.299 +        newd.to_vp = procr->slaveID;
  10.300 +        newd.to_task = procr->assignCount;
  10.301 +        addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList);  
  10.302 +   }
  10.303 +   #endif
  10.304 +   writePrivQ( procr, semEnv->readyVPQs[ procr->coreAnimatedBy] );
  10.305 + }
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/VSs_Request_Handlers.c	Wed May 23 13:17:07 2012 -0700
    11.3 @@ -0,0 +1,668 @@
    11.4 +/*
    11.5 + * Copyright 2010  OpenSourceCodeStewardshipFoundation
    11.6 + *
    11.7 + * Licensed under BSD
    11.8 + */
    11.9 +
   11.10 +#include <stdio.h>
   11.11 +#include <stdlib.h>
   11.12 +
   11.13 +#include "VMS_impl/VMS.h"
   11.14 +#include "Queue_impl/PrivateQueue.h"
   11.15 +#include "Hash_impl/PrivateHash.h"
   11.16 +#include "VOMP.h"
   11.17 +
   11.18 +
   11.19 +
   11.20 +//=========================== Local Fn Prototypes ===========================
   11.21 +void
   11.22 +resume_slaveVP( SlaveVP *procr, VOMPSemEnv *semEnv );
   11.23 +
   11.24 +
   11.25 +
   11.26 +//===========================================================================
   11.27 +//                           Helpers
   11.28 +
   11.29 +/*Only clone the elements of req used in these reqst handlers
   11.30 + */
   11.31 +  VOMPSemReq *
   11.32 +cloneReq( VOMPSemReq *semReq )
   11.33 + { VOMPSemReq *clonedReq;
   11.34 +
   11.35 +   clonedReq             = VMS_PI__malloc( sizeof(VOMPSemReq) );
   11.36 +   clonedReq->reqType    = semReq->reqType;
   11.37 +   clonedReq->sendPr     = semReq->sendPr;
   11.38 +   clonedReq->msg        = semReq->msg;
   11.39 +   clonedReq->nextReqInHashEntry = NULL;
   11.40 +   
   11.41 +   return clonedReq;
   11.42 + }
   11.43 +
   11.44 +HashEntry *
   11.45 +giveEntryElseInsertReqst( char *key, VOMPSemReq *semReq,
   11.46 +    HashTable   *commHashTbl )
   11.47 + { HashEntry    *entry;
   11.48 +   VOMPSemReq    *waitingReq;
   11.49 +
   11.50 +   entry = getEntryFromTable( (char *)key, commHashTbl );
   11.51 +   if( entry == NULL )
   11.52 +    {    //no waiting sends or receives, so add this request and exit
   11.53 +         // note: have to clone the request because it's on stack of sender
   11.54 +      addValueIntoTable( key, cloneReq( semReq ), commHashTbl );
   11.55 +      return NULL;
   11.56 +    }
   11.57 +   waitingReq = (VOMPSemReq *)entry->content;
   11.58 +   if( waitingReq == NULL )  //might happen when last waiting gets paired
   11.59 +    {    //no waiting sends or receives, so add this request and exit
   11.60 +      entry->content = semReq;
   11.61 +      return NULL;
   11.62 +    }
   11.63 +   return entry;
   11.64 + }
   11.65 +
   11.66 +
   11.67 +
   11.68 +
   11.69 +//===========================================================================
   11.70 +/*The semantic request has the receiving processor and the message type
   11.71 + *
   11.72 + *Note one value in this approach: without the extra VMS layer,
   11.73 + * the send and receive would happen in real time instead of virtual time,
   11.74 + * which would waste real time while one of them waited for other
   11.75 + *
   11.76 + *When successfully pair-up, transfer ownership of the sent data
   11.77 + * to the receiving processor
   11.78 + *
   11.79 + *Messages of a given Type have to be kept separate..  so need a separate
   11.80 + * entry in the hash table for each pair: receivePr, msgType
   11.81 + *
   11.82 + *Also, if same sender sends multiple before any get received, then need to
   11.83 + * stack the sends up -- even if a send waits until it's paired, several
   11.84 + * separate processors can send to the same receiver, and hashing on the
   11.85 + * receive processor, so they will stack up.
   11.86 + */
   11.87 +void
   11.88 +handleSendType( VOMPSemReq *semReq, VOMPSemEnv *semEnv )
   11.89 + { SlaveVP   *sendPr, *receivePr;
   11.90 +   int          key[] = {0,0,0};
   11.91 +   VOMPSemReq *waitingReq;
   11.92 +   HashEntry   *entry;
   11.93 +   HashTable   *commHashTbl = semEnv->commHashTbl;
   11.94 +   
   11.95 +         DEBUG__printf1(dbgRqstHdlr,"SendType request from processor %d",semReq->sendPr->slaveID)
   11.96 + 
   11.97 +   receivePr = semReq->receivePr; //For "send", know both send & recv procrs
   11.98 +   sendPr    = semReq->sendPr;
   11.99 +
  11.100 +         //TODO: handle transfer of msg-locs ownership
  11.101 +         //TODO: hash table implemented such that using "addEntry" or
  11.102 +         //  "addValue" to table causes the *value* in old entry to be
  11.103 +         //  *freed* -- this is bad.  Want to stack up values in a linked
  11.104 +         //  list when multiple have the same key.
  11.105 +
  11.106 +      //TODO: use a faster hash function -- see notes in intelligence gather
  11.107 +   key[0] = (int)receivePr->slaveID;
  11.108 +   key[1] = (int)(semReq->msgType);
  11.109 + //key[2] acts as the 0 that terminates the string
  11.110 +
  11.111 +   entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
  11.112 +   if( entry == NULL ) return;  //was just inserted
  11.113 +
  11.114 +   waitingReq = (VOMPSemReq *)entry->content;
  11.115 +
  11.116 +      //At this point, know have waiting request(s) -- either sends or recv
  11.117 +      //Note, can only have max of one receive waiting, and cannot have both
  11.118 +      // sends and receives waiting (they would have paired off)
  11.119 +      // but can have multiple sends from diff sending VPs, all same msg-type
  11.120 +   if( waitingReq->reqType == send_type )
  11.121 +    {    //waiting request is another send, so stack this up on list
  11.122 +         // but first clone the sending request so it persists.
  11.123 +      VOMPSemReq *clonedReq = cloneReq( semReq );
  11.124 +      clonedReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry;
  11.125 +      waitingReq->nextReqInHashEntry = clonedReq;
  11.126 +         DEBUG__printf2( dbgRqstHdlr, "linked requests: %p, %p ", clonedReq,\
  11.127 +                                                                 waitingReq )
  11.128 +      return;
  11.129 +    }
  11.130 +   else
  11.131 +    {    
  11.132 +       #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  11.133 +        Dependency newd;
  11.134 +        newd.from_vp = sendPr->slaveID;
  11.135 +        newd.from_task = sendPr->assignCount;
  11.136 +        newd.to_vp = receivePr->slaveID;
  11.137 +        newd.to_task = receivePr->assignCount +1;
  11.138 +        //(newd,semEnv->commDependenciesList);  
  11.139 +        addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList);  
  11.140 +                int32 groupId = semReq->msgType;
  11.141 +        if(semEnv->ntonGroupsInfo->numInArray <= groupId){
  11.142 +            makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId);
  11.143 +        }
  11.144 +        if(semEnv->ntonGroups[groupId] == NULL){
  11.145 +            semEnv->ntonGroups[groupId] = new_NtoN(groupId);
  11.146 +        }
  11.147 +        Unit u;
  11.148 +        u.vp = sendPr->slaveID;
  11.149 +        u.task = sendPr->assignCount;
  11.150 +        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders);
  11.151 +        u.vp = receivePr->slaveID;
  11.152 +        u.task = receivePr->assignCount +1;
  11.153 +        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers);
  11.154 +       #endif
  11.155 +
  11.156 +       //waiting request is a receive, so it pairs to this send
  11.157 +         //First, remove the waiting receive request from the entry
  11.158 +      entry->content = waitingReq->nextReqInHashEntry;
  11.159 +      VMS_PI__free( waitingReq ); //Don't use contents -- so free it
  11.160 +      
  11.161 +      if( entry->content == NULL )
  11.162 +       {    //TODO: mod hash table to double-link, so can delete entry from
  11.163 +            // table without hashing the key and looking it up again
  11.164 +         deleteEntryFromTable( entry->key, commHashTbl );  //frees hashEntry
  11.165 +       }
  11.166 +      
  11.167 +         //attach msg that's in this send request to receiving procr
  11.168 +         // when comes back from suspend will have msg in dataRetFromReq
  11.169 +      receivePr->dataRetFromReq = semReq->msg;
  11.170 +
  11.171 +         //bring both processors back from suspend
  11.172 +      resume_slaveVP( sendPr,    semEnv );
  11.173 +      resume_slaveVP( receivePr, semEnv );
  11.174 +
  11.175 +      return;
  11.176 +    }
  11.177 + }
  11.178 +
  11.179 +
  11.180 +/*Looks like can make single handler for both sends..
  11.181 + */
  11.182 +//TODO: combine both send handlers into single handler
  11.183 +void
  11.184 +handleSendFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv)
  11.185 + { SlaveVP   *sendPr, *receivePr;
  11.186 +   int          key[] = {0,0,0};
  11.187 +   VOMPSemReq *waitingReq;
  11.188 +   HashEntry   *entry;
  11.189 +   HashTable   *commHashTbl = semEnv->commHashTbl;
  11.190 +
  11.191 +         DEBUG__printf2(dbgRqstHdlr,"SendFromTo request from processor %d to %d",semReq->sendPr->slaveID,semReq->receivePr->slaveID)
  11.192 +   
  11.193 +   receivePr = semReq->receivePr; //For "send", know both send & recv procrs
  11.194 +   sendPr    = semReq->sendPr;    
  11.195 +   
  11.196 +       
  11.197 +   key[0] = (int)receivePr->slaveID;
  11.198 +   key[1] = (int)sendPr->slaveID;
  11.199 + //key[2] acts at the 0 that terminates the string
  11.200 +
  11.201 +   entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
  11.202 +   if( entry == NULL ) return;  //was just inserted
  11.203 +
  11.204 +   waitingReq = (VOMPSemReq *)entry->content;
  11.205 +
  11.206 +      //At this point, know have waiting request(s) -- either sends or recv
  11.207 +   if( waitingReq->reqType == send_from_to )
  11.208 +    { printf("\n ERROR: shouldn't be two send-from-tos waiting \n");
  11.209 +    }
  11.210 +   else
  11.211 +    {    //waiting request is a receive, so it completes pair with this send
  11.212 +      #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  11.213 +        Dependency newd;
  11.214 +        newd.from_vp = sendPr->slaveID;
  11.215 +        newd.from_task = sendPr->assignCount;
  11.216 +        newd.to_vp = receivePr->slaveID;
  11.217 +        newd.to_task = receivePr->assignCount +1;
  11.218 +        //addToListOfArraysDependency(newd,semEnv->commDependenciesList);  
  11.219 +        addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);   
  11.220 +      #endif 
  11.221 +         //First, remove the waiting receive request from the entry
  11.222 +      entry->content = waitingReq->nextReqInHashEntry;
  11.223 +      VMS_PI__free( waitingReq ); //Don't use contents -- so free it
  11.224 +      
  11.225 +         //can only be one waiting req for "from-to" semantics
  11.226 +      if( entry->content != NULL )
  11.227 +       {
  11.228 +         printf("\nERROR in handleSendFromTo\n");
  11.229 +       }
  11.230 +      deleteEntryFromTable( entry->key, commHashTbl );  //frees HashEntry
  11.231 +
  11.232 +         //attach msg that's in this send request to receiving procr
  11.233 +         // when comes back from suspend, will have msg in dataRetFromReq
  11.234 +      receivePr->dataRetFromReq = semReq->msg;
  11.235 +
  11.236 +         //bring both processors back from suspend
  11.237 +      resume_slaveVP( sendPr,    semEnv );
  11.238 +      resume_slaveVP( receivePr, semEnv );
  11.239 +            
  11.240 +      return;
  11.241 +    }
  11.242 + }
  11.243 +
  11.244 +
  11.245 +
  11.246 +//==============================  Receives  ===========================
  11.247 +//
  11.248 +/*Removed this one for now, because forces either a search or going to a
  11.249 + * two-level hash table, where one level the key is the receivePr, in the
  11.250 + * other level, the key is the type.
  11.251 + *So, each dest procr that either does a receive_type or that a send_type
  11.252 + * targets it, would have a hash table created just for it and placed
  11.253 + * into the first-level hash table entry for that receive procr.
  11.254 + *Then, doing a receive_type first looks up entry for receive procr in first
  11.255 + * table, gets the type-table out of that entry, and does a second lookup
  11.256 + * in the type-table.
  11.257 + *Doing a receive from-to looks up in the first table, gets the second table
  11.258 + * hashed on "from" procr.
  11.259 + *Doing a receive_any looks up in the first table, then looks to see if
  11.260 + * either of the hash tables have any entries -- would then have to do a
  11.261 + * linear search through the hash-table's array for the first non-empty
  11.262 + * spot
  11.263 + *Yuck.
  11.264 + *
  11.265 + *Alternatively, could keep two hash tables updated all the time -- one that
  11.266 + * does the receive_type and receive_from_to and a second that does
  11.267 + * receive_any -- would only hash the second table by the receive procr.
  11.268 + * When remove from one table, keep back-links to both tables, so can also
  11.269 + * quickly remove from other table.
  11.270 + *Cost is doing two hash-table lookups for every insert.
  11.271 + * If ever add receive_any, looking like this second option easier and even
  11.272 + * less costly.
  11.273 + */
  11.274 +void
  11.275 +handleReceiveAny( VOMPSemReq *semReq, VOMPSemEnv *semEnv)
  11.276 + {
  11.277 + 
  11.278 + }
  11.279 +
  11.280 +
  11.281 +void
  11.282 +handleReceiveType( VOMPSemReq *semReq, VOMPSemEnv *semEnv)
  11.283 + { SlaveVP   *sendPr, *receivePr;
  11.284 +   int          key[] = {0,0,0};
  11.285 +   VOMPSemReq *waitingReq;
  11.286 +   HashEntry   *entry;
  11.287 +   HashTable   *commHashTbl = semEnv->commHashTbl;
  11.288 +
  11.289 +   receivePr = semReq->receivePr;
  11.290 +
  11.291 +         DEBUG__printf1(dbgRqstHdlr,"ReceiveType request from processor %d",receivePr->slaveID)
  11.292 +   
  11.293 +   key[0] = (int)receivePr->slaveID;
  11.294 +   key[1] = (int)(semReq->msgType);
  11.295 + //key[2] acts as the 0 that terminates the string
  11.296 +
  11.297 +
  11.298 +   entry = giveEntryElseInsertReqst((char*)key, semReq, commHashTbl);//clones
  11.299 +   if( entry == NULL ) return;  //was just inserted
  11.300 +
  11.301 +   waitingReq = (VOMPSemReq *)entry->content;  //previously cloned by insert
  11.302 +
  11.303 +      //At this point, know have waiting request(s) -- should be send(s)
  11.304 +   if( waitingReq->reqType == send_type )
  11.305 +    {    //waiting request is a send, so pair it with this receive
  11.306 +         //first, remove the waiting send request from the list in entry
  11.307 +
  11.308 +      entry->content = waitingReq->nextReqInHashEntry;
  11.309 +      if( entry->content == NULL )
  11.310 +       { deleteEntryFromTable( entry->key, commHashTbl );  //frees HashEntry
  11.311 +       }
  11.312 +      
  11.313 +         //attach msg that's in the send request to receiving procr
  11.314 +         // when comes back from suspend, will have msg in dataRetFromReq
  11.315 +      receivePr->dataRetFromReq = waitingReq->msg;
  11.316 +
  11.317 +         //bring both processors back from suspend
  11.318 +      sendPr = waitingReq->sendPr;
  11.319 +      VMS_PI__free( waitingReq );
  11.320 +
  11.321 +       #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  11.322 +        Dependency newd;
  11.323 +        newd.from_vp = sendPr->slaveID;
  11.324 +        newd.from_task = sendPr->assignCount;
  11.325 +        newd.to_vp = receivePr->slaveID;
  11.326 +        newd.to_task = receivePr->assignCount +1;
  11.327 +        //addToListOfArraysDependency(newd,semEnv->commDependenciesList);  
  11.328 +        addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); 
  11.329 +        int32 groupId = semReq->msgType;
  11.330 +        if(semEnv->ntonGroupsInfo->numInArray <= groupId){
  11.331 +            makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId);
  11.332 +        }
  11.333 +        if(semEnv->ntonGroups[groupId] == NULL){
  11.334 +            semEnv->ntonGroups[groupId] = new_NtoN(groupId);
  11.335 +        }
  11.336 +        Unit u;
  11.337 +        u.vp = sendPr->slaveID;
  11.338 +        u.task = sendPr->assignCount;
  11.339 +        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders);
  11.340 +        u.vp = receivePr->slaveID;
  11.341 +        u.task = receivePr->assignCount +1;
  11.342 +        addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers);
  11.343 +       #endif
  11.344 +      
  11.345 +      resume_slaveVP( sendPr,    semEnv );
  11.346 +      resume_slaveVP( receivePr, semEnv );
  11.347 +
  11.348 +      return;
  11.349 +    }
  11.350 +   printf("\nLang Impl Error: Should never be two waiting receives!\n");
  11.351 + }
  11.352 +
  11.353 +
  11.354 +/*
  11.355 + */
  11.356 +void
  11.357 +handleReceiveFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv)
  11.358 + { SlaveVP     *sendPr, *receivePr;
  11.359 +   int          key[] = {0,0,0};
  11.360 +   VOMPSemReq   *waitingReq;
  11.361 +   HashEntry   *entry;
  11.362 +   HashTable   *commHashTbl = semEnv->commHashTbl;
  11.363 +
  11.364 +         DEBUG__printf2(dbgRqstHdlr,"ReceiveFromTo %d : %d",semReq->sendPr->slaveID,semReq->receivePr->slaveID)
  11.365 +   
  11.366 +   receivePr = semReq->receivePr;
  11.367 +   sendPr    = semReq->sendPr;    //for receive from-to, know send procr
  11.368 +
  11.369 +   key[0] = (int)receivePr->slaveID;
  11.370 +   key[1] = (int)sendPr->slaveID;
  11.371 + //key[2] acts at the 0 that terminates the string
  11.372 +
  11.373 +   entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
  11.374 +   if( entry == NULL ) return;  //was just inserted
  11.375 +
  11.376 +   waitingReq = (VOMPSemReq *)entry->content;
  11.377 +
  11.378 +      //At this point, know have waiting request(s) -- should be send(s)
  11.379 +   if( waitingReq->reqType == send_from_to )
  11.380 +    {    //waiting request is a send, so pair it with this receive
  11.381 +      #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
  11.382 +        Dependency newd;
  11.383 +        newd.from_vp = sendPr->slaveID;
  11.384 +        newd.from_task = sendPr->assignCount;
  11.385 +        newd.to_vp = receivePr->slaveID;
  11.386 +        newd.to_task = receivePr->assignCount +1;
  11.387 +        //addToListOfArraysDependency(newd,semEnv->commDependenciesList);  
  11.388 +        addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);    
  11.389 +      #endif  
  11.390 +         //For from-to, should only ever be a single reqst waiting tobe paird
  11.391 +      entry->content = waitingReq->nextReqInHashEntry;
  11.392 +      if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n");
  11.393 +      deleteEntryFromTable( entry->key, commHashTbl );  //frees entry too
  11.394 +
  11.395 +         //attach msg that's in the send request to receiving procr
  11.396 +         // when comes back from suspend, will have msg in dataRetFromReq
  11.397 +      receivePr->dataRetFromReq = waitingReq->msg;
  11.398 +
  11.399 +         //bring both processors back from suspend
  11.400 +      sendPr = waitingReq->sendPr;
  11.401 +      VMS_PI__free( waitingReq );
  11.402 +
  11.403 +      resume_slaveVP( sendPr,    semEnv );
  11.404 +      resume_slaveVP( receivePr, semEnv );
  11.405 +
  11.406 +      return;
  11.407 +    }
  11.408 +   printf("\nLang Impl Error: Should never be two waiting receives!\n");
  11.409 + }
  11.410 +
  11.411 +
  11.412 +
  11.413 +//===============================================
  11.414 +void
  11.415 +handleTransferTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv)
  11.416 + {
  11.417 +
  11.418 + }
  11.419 +
  11.420 +void
  11.421 +handleTransferOut( VOMPSemReq *semReq, VOMPSemEnv *semEnv)
  11.422 + {
  11.423 +
  11.424 + }
  11.425 +
  11.426 +
  11.427 +/*
  11.428 + */
  11.429 +void
  11.430 +handleMalloc( VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv )
  11.431 + { void *ptr;
  11.432 + 
  11.433 +      DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingPr->slaveID)
  11.434 +
  11.435 +   ptr = VMS_PI__malloc( semReq->sizeToMalloc );
  11.436 +   requestingPr->dataRetFromReq = ptr;
  11.437 +   resume_slaveVP( requestingPr, semEnv );
  11.438 + }
  11.439 +
  11.440 +/*
  11.441 + */
  11.442 +void
  11.443 +handleFree( VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv )
  11.444 + {
  11.445 +         DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingPr->slaveID)
  11.446 +   VMS_PI__free( semReq->ptrToFree );
  11.447 +   resume_slaveVP( requestingPr, semEnv );
  11.448 + }
  11.449 +
  11.450 +
  11.451 +//===========================================================================
  11.452 +//
  11.453 +/*Uses ID as index into array of flags.  If flag already set, resumes from
  11.454 + * end-label.  Else, sets flag and resumes normally.
  11.455 + */
  11.456 +void inline
  11.457 +handleStartSingleton_helper( VOMPSingleton *singleton, SlaveVP *reqstingPr,
  11.458 +                             VOMPSemEnv    *semEnv )
  11.459 + {
  11.460 +   if( singleton->hasFinished )
  11.461 +    {    //the code that sets the flag to true first sets the end instr addr
  11.462 +      reqstingPr->dataRetFromReq = singleton->endInstrAddr;
  11.463 +      resume_slaveVP( reqstingPr, semEnv );
  11.464 +      return;
  11.465 +    }
  11.466 +   else if( singleton->hasBeenStarted )
  11.467 +    {    //singleton is in-progress in a diff slave, so wait for it to finish
  11.468 +      writePrivQ(reqstingPr, singleton->waitQ );
  11.469 +      return;
  11.470 +    }
  11.471 +   else
  11.472 +    {    //hasn't been started, so this is the first attempt at the singleton
  11.473 +      singleton->hasBeenStarted = TRUE;
  11.474 +      reqstingPr->dataRetFromReq = 0x0;
  11.475 +      resume_slaveVP( reqstingPr, semEnv );
  11.476 +      return;
  11.477 +    }
  11.478 + }
  11.479 +void inline
  11.480 +handleStartFnSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr,
  11.481 +                      VOMPSemEnv *semEnv )
  11.482 + { VOMPSingleton *singleton;
  11.483 +         DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingPr->slaveID)
  11.484 +
  11.485 +   singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
  11.486 +   handleStartSingleton_helper( singleton, requestingPr, semEnv );
  11.487 + }
  11.488 +void inline
  11.489 +handleStartDataSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr,
  11.490 +                      VOMPSemEnv *semEnv )
  11.491 + { VOMPSingleton *singleton;
  11.492 +
  11.493 +         DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingPr->slaveID)
  11.494 +   if( *(semReq->singletonPtrAddr) == NULL )
  11.495 +    { singleton                 = VMS_PI__malloc( sizeof(VOMPSingleton) );
  11.496 +      singleton->waitQ          = makeVMSQ();
  11.497 +      singleton->endInstrAddr   = 0x0;
  11.498 +      singleton->hasBeenStarted = FALSE;
  11.499 +      singleton->hasFinished    = FALSE;
  11.500 +      *(semReq->singletonPtrAddr)  = singleton;
  11.501 +    }
  11.502 +   else
  11.503 +      singleton = *(semReq->singletonPtrAddr);
  11.504 +   handleStartSingleton_helper( singleton, requestingPr, semEnv );
  11.505 + }
  11.506 +
  11.507 +
  11.508 +void inline
  11.509 +handleEndSingleton_helper( VOMPSingleton *singleton, SlaveVP *requestingPr,
  11.510 +                           VOMPSemEnv    *semEnv )
  11.511 + { PrivQueueStruc *waitQ;
  11.512 +   int32           numWaiting, i;
  11.513 +   SlaveVP      *resumingPr;
  11.514 +
  11.515 +   if( singleton->hasFinished )
  11.516 +    { //by definition, only one slave should ever be able to run end singleton
  11.517 +      // so if this is true, is an error
  11.518 +      ERROR1( "singleton code ran twice", requestingPr );
  11.519 +    }
  11.520 +
  11.521 +   singleton->hasFinished = TRUE;
  11.522 +   waitQ = singleton->waitQ;
  11.523 +   numWaiting = numInPrivQ( waitQ );
  11.524 +   for( i = 0; i < numWaiting; i++ )
  11.525 +    {    //they will resume inside start singleton, then jmp to end singleton
  11.526 +      resumingPr = readPrivQ( waitQ );
  11.527 +      resumingPr->dataRetFromReq = singleton->endInstrAddr;
  11.528 +      resume_slaveVP( resumingPr, semEnv );
  11.529 +    }
  11.530 +
  11.531 +   resume_slaveVP( requestingPr, semEnv );
  11.532 +
  11.533 +}
  11.534 +void inline
  11.535 +handleEndFnSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr,
  11.536 +                        VOMPSemEnv *semEnv )
  11.537 + {
  11.538 +   VOMPSingleton   *singleton;
  11.539 +
  11.540 +         DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingPr->slaveID)
  11.541 +   
  11.542 +   singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
  11.543 +   handleEndSingleton_helper( singleton, requestingPr, semEnv );
  11.544 +  }
  11.545 +void inline
  11.546 +handleEndDataSingleton( VOMPSemReq *semReq, SlaveVP *requestingPr,
  11.547 +                        VOMPSemEnv *semEnv )
  11.548 + {
  11.549 +   VOMPSingleton   *singleton;
  11.550 +
  11.551 +         DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingPr->slaveID)
  11.552 +   
  11.553 +   singleton = *(semReq->singletonPtrAddr);
  11.554 +   handleEndSingleton_helper( singleton, requestingPr, semEnv );
  11.555 +  }
  11.556 +
  11.557 +
  11.558 +/*This executes the function in the masterVP, take the function
  11.559 + * pointer out of the request and call it, then resume the VP.
  11.560 + */
  11.561 +void
  11.562 +handleAtomic( VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv )
  11.563 + {
  11.564 +         DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingPr->slaveID)
  11.565 +   semReq->fnToExecInMaster( semReq->dataForFn );
  11.566 +   resume_slaveVP( requestingPr, semEnv );
  11.567 + }
  11.568 +
  11.569 +/*First, it looks at the VP's semantic data, to see the highest transactionID
  11.570 + * that VP
  11.571 + * already has entered.  If the current ID is not larger, it throws an
  11.572 + * exception stating a bug in the code.
  11.573 + *Otherwise it puts the current ID
  11.574 + * there, and adds the ID to a linked list of IDs entered -- the list is
  11.575 + * used to check that exits are properly ordered.
  11.576 + *Next it is uses transactionID as index into an array of transaction
  11.577 + * structures.
  11.578 + *If the "VP_currently_executing" field is non-null, then put requesting VP
  11.579 + * into queue in the struct.  (At some point a holder will request
  11.580 + * end-transaction, which will take this VP from the queue and resume it.)
  11.581 + *If NULL, then write requesting into the field and resume.
  11.582 + */
  11.583 +void
  11.584 +handleTransStart( VOMPSemReq *semReq, SlaveVP *requestingPr,
  11.585 +                  VOMPSemEnv *semEnv )
  11.586 + { VOMPSemData *semData;
  11.587 +   TransListElem *nextTransElem;
  11.588 +
  11.589 +         DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingPr->slaveID)
  11.590 +   
  11.591 +      //check ordering of entering transactions is correct
  11.592 +   semData = requestingPr->semanticData;
  11.593 +   if( semData->highestTransEntered > semReq->transID )
  11.594 +    {    //throw VMS exception, which shuts down VMS.
  11.595 +      VMS_PI__throw_exception( "transID smaller than prev", requestingPr, NULL);
  11.596 +    }
  11.597 +      //add this trans ID to the list of transactions entered -- check when
  11.598 +      // end a transaction
  11.599 +   semData->highestTransEntered = semReq->transID;
  11.600 +   nextTransElem = VMS_PI__malloc( sizeof(TransListElem) );
  11.601 +   nextTransElem->transID = semReq->transID;
  11.602 +   nextTransElem->nextTrans = semData->lastTransEntered;
  11.603 +   semData->lastTransEntered = nextTransElem;
  11.604 +
  11.605 +      //get the structure for this transaction ID
  11.606 +   VOMPTrans *
  11.607 +   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
  11.608 +
  11.609 +   if( transStruc->VPCurrentlyExecuting == NULL )
  11.610 +    {
  11.611 +      transStruc->VPCurrentlyExecuting = requestingPr;
  11.612 +      resume_slaveVP( requestingPr, semEnv );
  11.613 +    }
  11.614 +   else
  11.615 +    {    //note, might make future things cleaner if save request with VP and
  11.616 +         // add this trans ID to the linked list when gets out of queue.
  11.617 +         // but don't need for now, and lazy..
  11.618 +      writePrivQ( requestingPr, transStruc->waitingVPQ );
  11.619 +    }
  11.620 + }
  11.621 +
  11.622 +
  11.623 +/*Use the trans ID to get the transaction structure from the array.
  11.624 + *Look at VP_currently_executing to be sure it's same as requesting VP.
  11.625 + * If different, throw an exception, stating there's a bug in the code.
  11.626 + *Next, take the first element off the list of entered transactions.
  11.627 + * Check to be sure the ending transaction is the same ID as the next on
  11.628 + * the list.  If not, incorrectly nested so throw an exception.
  11.629 + *
  11.630 + *Next, get from the queue in the structure.
  11.631 + *If it's empty, set VP_currently_executing field to NULL and resume
  11.632 + * requesting VP.
  11.633 + *If get somethine, set VP_currently_executing to the VP from the queue, then
  11.634 + * resume both.
  11.635 + */
  11.636 +void
  11.637 +handleTransEnd(VOMPSemReq *semReq, SlaveVP *requestingPr, VOMPSemEnv *semEnv)
  11.638 + { VOMPSemData    *semData;
  11.639 +   SlaveVP     *waitingPr;
  11.640 +   VOMPTrans      *transStruc;
  11.641 +   TransListElem *lastTrans;
  11.642 +   
  11.643 +         DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingPr->slaveID)
  11.644 +   
  11.645 +   transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
  11.646 +
  11.647 +      //make sure transaction ended in same VP as started it.
  11.648 +   if( transStruc->VPCurrentlyExecuting != requestingPr )
  11.649 +    {
  11.650 +      VMS_PI__throw_exception( "trans ended in diff VP", requestingPr, NULL );
  11.651 +    }
  11.652 +
  11.653 +      //make sure nesting is correct -- last ID entered should == this ID
  11.654 +   semData = requestingPr->semanticData;
  11.655 +   lastTrans = semData->lastTransEntered;
  11.656 +   if( lastTrans->transID != semReq->transID )
  11.657 +    {
  11.658 +      VMS_PI__throw_exception( "trans incorrectly nested", requestingPr, NULL );
  11.659 +    }
  11.660 +
  11.661 +   semData->lastTransEntered = semData->lastTransEntered->nextTrans;
  11.662 +
  11.663 +
  11.664 +   waitingPr = readPrivQ( transStruc->waitingVPQ );
  11.665 +   transStruc->VPCurrentlyExecuting = waitingPr;
  11.666 +
  11.667 +   if( waitingPr != NULL )
  11.668 +      resume_slaveVP( waitingPr, semEnv );
  11.669 +
  11.670 +   resume_slaveVP( requestingPr, semEnv );
  11.671 + }
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/VSs_Request_Handlers.h	Wed May 23 13:17:07 2012 -0700
    12.3 @@ -0,0 +1,56 @@
    12.4 +/*
    12.5 + *  Copyright 2009 OpenSourceStewardshipFoundation.org
    12.6 + *  Licensed under GNU General Public License version 2
    12.7 + *
    12.8 + * Author: seanhalle@yahoo.com
    12.9 + *
   12.10 + */
   12.11 +
   12.12 +#ifndef _VOMP_REQ_H
   12.13 +#define	_VOMP_REQ_H
   12.14 +
   12.15 +#include "VOMP.h"
   12.16 +
   12.17 +/*This header defines everything specific to the VOMP semantic plug-in
   12.18 + */
   12.19 +
   12.20 +inline void
   12.21 +handleSendType( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.22 +inline void
   12.23 +handleSendFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.24 +inline void
   12.25 +handleReceiveAny( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.26 +inline void
   12.27 +handleReceiveType( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.28 +inline void
   12.29 +handleReceiveFromTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.30 +inline void
   12.31 +handleTransferTo( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.32 +inline void
   12.33 +handleTransferOut( VOMPSemReq *semReq, VOMPSemEnv *semEnv);
   12.34 +inline void
   12.35 +handleMalloc( VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv *semEnv);
   12.36 +inline void
   12.37 +handleFree( VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv *semEnv );
   12.38 +inline void
   12.39 +handleTransEnd(VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv*semEnv);
   12.40 +inline void
   12.41 +handleTransStart( VOMPSemReq *semReq, SlaveVP *requestingSlv,
   12.42 +                  VOMPSemEnv *semEnv );
   12.43 +inline void
   12.44 +handleAtomic( VOMPSemReq *semReq, SlaveVP *requestingSlv, VOMPSemEnv *semEnv);
   12.45 +inline void
   12.46 +handleStartFnSingleton( VOMPSemReq *semReq, SlaveVP *reqstingSlv,
   12.47 +                      VOMPSemEnv *semEnv );
   12.48 +inline void
   12.49 +handleEndFnSingleton( VOMPSemReq *semReq, SlaveVP *requestingSlv,
   12.50 +                    VOMPSemEnv *semEnv );
   12.51 +inline void
   12.52 +handleStartDataSingleton( VOMPSemReq *semReq, SlaveVP *reqstingSlv,
   12.53 +                      VOMPSemEnv *semEnv );
   12.54 +inline void
   12.55 +handleEndDataSingleton( VOMPSemReq *semReq, SlaveVP *requestingSlv,
   12.56 +                    VOMPSemEnv *semEnv );
   12.57 +
   12.58 +#endif	/* _VOMP_REQ_H */
   12.59 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/VSs_singleton_asm.s	Wed May 23 13:17:07 2012 -0700
    13.3 @@ -0,0 +1,21 @@
    13.4 +
    13.5 +//Assembly code takes the return addr off the stack and saves
    13.6 +// into the singleton.  The first field in the singleton is the
    13.7 +// "endInstrAddr" field, and the return addr is at 0x4(%ebp)
    13.8 +.globl asm_save_ret_to_singleton
    13.9 +asm_save_ret_to_singleton:
   13.10 +    movq 0x8(%rbp),     %rax   #get ret address, ebp is the same as in the calling function
   13.11 +    movq     %rax,     (%rdi) #write ret addr to endInstrAddr field
   13.12 +    ret
   13.13 +
   13.14 +
   13.15 +//Assembly code changes the return addr on the stack to the one
   13.16 +// saved into the singleton by the end-singleton-fn
   13.17 +//The stack's return addr is at 0x4(%%ebp)
   13.18 +.globl asm_write_ret_from_singleton
   13.19 +asm_write_ret_from_singleton:
   13.20 +    movq    (%rdi),    %rax  #get endInstrAddr field
   13.21 +    movq      %rax,    0x8(%rbp) #write return addr to the stack of the caller
   13.22 +    ret
   13.23 +
   13.24 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/__brch__default	Wed May 23 13:17:07 2012 -0700
    14.3 @@ -0,0 +1,4 @@
    14.4 +This branch is for the project structure defined Jan 2012..  the #includes reflect this directory structure.
    14.5 +
    14.6 +More importantly, the MC_shared  version of VMS requires a separat malloc implemeted by VMS code..  so this branch has modified the library to use the VMS-specific malloc.
    14.7 +