Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VSs_impls > VSs__MC_shared_impl
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 +