Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VSs_impls > VSs__MC_shared_impl
changeset 26:a60399b62614 ML_dev
Update.. in middle of changes..
author | Sean Halle <seanhalle@yahoo.com> |
---|---|
date | Thu, 18 Oct 2012 02:44:30 -0700 |
parents | 5bc52d3eae7d |
children | 3b30da4643d1 |
files | Measurement/VSs_Counter_Recording.c Measurement/VSs_Counter_Recording.h Measurement/VSs_Measurement.h Measurement/dependency.c VSs.c VSs.h VSs_PluginFns.c VSs_Request_Handlers.c VSs_Request_Handlers.h VSs_singleton_asm.s |
diffstat | 10 files changed, 515 insertions(+), 1058 deletions(-) [+] |
line diff
1.1 --- a/Measurement/VSs_Counter_Recording.c Mon Sep 03 03:26:12 2012 -0700 1.2 +++ b/Measurement/VSs_Counter_Recording.c Thu Oct 18 02:44:30 2012 -0700 1.3 @@ -4,18 +4,20 @@ 1.4 */ 1.5 1.6 #include "VSs_Counter_Recording.h" 1.7 -#include "VMS_impl/VMS.h" 1.8 +#include "PR_impl/PR.h" 1.9 #include "VSs_impl/VSs.h" 1.10 1.11 #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 1.12 1.13 -void VSs__init_counter_data_structs(){ 1.14 - VSsSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; 1.15 - int i; 1.16 - for(i=0;i<NUM_CORES;i++){ 1.17 - semanticEnv->counterList[i] = makeListOfArrays(sizeof(CounterEvent), 128); 1.18 +void VSs__init_counter_data_structs( SlaveVP *slave ) 1.19 + { 1.20 + VSsSemEnv *semanticEnv = 1.21 + (VSsSemEnv *)PR_SS__give_sem_env_for( slave, VSs_MAGIC_NUMBER ); 1.22 + int i; 1.23 + for(i=0;i<NUM_CORES;i++) 1.24 + { semanticEnv->counterList[i] = makeListOfArrays(sizeof(CounterEvent), 128); 1.25 } 1.26 -} 1.27 + } 1.28 1.29 void addToListOfArraysCounterEvent(CounterEvent value, ListOfArrays* list){ 1.30 int offset_in_fragment = list->next_free_index % list->num_entries_per_fragment; 1.31 @@ -36,7 +38,7 @@ 1.32 return; 1.33 } 1.34 1.35 - VSsSemEnv *semanticEnv = _VMSMasterEnv->semanticEnv; 1.36 + VSsSemEnv *semanticEnv = _PRMasterEnv->semanticEnv; 1.37 1.38 CounterEvent e; 1.39 e.event_type = evt_type;
2.1 --- a/Measurement/VSs_Counter_Recording.h Mon Sep 03 03:26:12 2012 -0700 2.2 +++ b/Measurement/VSs_Counter_Recording.h Thu Oct 18 02:44:30 2012 -0700 2.3 @@ -8,7 +8,7 @@ 2.4 #ifndef VSs_COUNTER_RECORDING_H 2.5 #define VSs_COUNTER_RECORDING_H 2.6 2.7 -#include "VMS_impl/VMS.h" 2.8 +#include "PR_impl/PR.h" 2.9 2.10 typedef struct { 2.11 int event_type;
3.1 --- a/Measurement/VSs_Measurement.h Mon Sep 03 03:26:12 2012 -0700 3.2 +++ b/Measurement/VSs_Measurement.h Thu Oct 18 02:44:30 2012 -0700 3.3 @@ -26,8 +26,8 @@ 3.4 #define ReceiveOfTypeHistIdx 4 3.5 3.6 #define MEAS__Make_Meas_Hists_for_Language \ 3.7 - _VMSMasterEnv->measHistsInfo = \ 3.8 - makePrivDynArrayOfSize( (void***)&(_VMSMasterEnv->measHists), 200); \ 3.9 + _PRMasterEnv->measHistsInfo = \ 3.10 + makePrivDynArrayOfSize( (void***)&(_PRMasterEnv->measHists), 200); \ 3.11 makeAMeasHist( SendFromToHistIdx, "SendFromTo", 50, 0, 100 ) \ 3.12 makeAMeasHist( SendOfTypeHistIdx, "SendOfType", 50, 0, 100 ) \ 3.13 makeAMeasHist( ReceiveFromToHistIdx,"ReceiveFromTo", 50, 0, 100 ) \ 3.14 @@ -40,7 +40,7 @@ 3.15 #define Meas_endSendFromTo \ 3.16 saveLowTimeStampCountInto( endStamp ); \ 3.17 addIntervalToHist( startStamp, endStamp, \ 3.18 - _VMSMasterEnv->measHists[ SendFromToHistIdx ] ); 3.19 + _PRMasterEnv->measHists[ SendFromToHistIdx ] ); 3.20 3.21 #define Meas_startSendOfType \ 3.22 int32 startStamp, endStamp; \ 3.23 @@ -49,7 +49,7 @@ 3.24 #define Meas_endSendOfType \ 3.25 saveLowTimeStampCountInto( endStamp ); \ 3.26 addIntervalToHist( startStamp, endStamp, \ 3.27 - _VMSMasterEnv->measHists[ SendOfTypeHistIdx ] ); 3.28 + _PRMasterEnv->measHists[ SendOfTypeHistIdx ] ); 3.29 3.30 #define Meas_startReceiveFromTo \ 3.31 int32 startStamp, endStamp; \ 3.32 @@ -58,7 +58,7 @@ 3.33 #define Meas_endReceiveFromTo \ 3.34 saveLowTimeStampCountInto( endStamp ); \ 3.35 addIntervalToHist( startStamp, endStamp, \ 3.36 - _VMSMasterEnv->measHists[ ReceiveFromToHistIdx ] ); 3.37 + _PRMasterEnv->measHists[ ReceiveFromToHistIdx ] ); 3.38 3.39 #define Meas_startReceiveOfType \ 3.40 int32 startStamp, endStamp; \ 3.41 @@ -67,7 +67,7 @@ 3.42 #define Meas_endReceiveOfType \ 3.43 saveLowTimeStampCountInto( endStamp ); \ 3.44 addIntervalToHist( startStamp, endStamp, \ 3.45 - _VMSMasterEnv->measHists[ReceiveOfTypeHistIdx ] ); 3.46 + _PRMasterEnv->measHists[ReceiveOfTypeHistIdx ] ); 3.47 3.48 #else //===================== turned off ========================== 3.49
4.1 --- a/Measurement/dependency.c Mon Sep 03 03:26:12 2012 -0700 4.2 +++ b/Measurement/dependency.c Thu Oct 18 02:44:30 2012 -0700 4.3 @@ -1,8 +1,8 @@ 4.4 #include "dependency.h" 4.5 -#include "VMS_impl/VMS.h" 4.6 +#include "PR_impl/PR.h" 4.7 4.8 Dependency* new_dependency(int from_vp, int from_task, int to_vp, int to_task){ 4.9 - Dependency* newDep = (Dependency*) VMS_int__malloc(sizeof(Dependency)); 4.10 + Dependency* newDep = (Dependency*) PR_int__malloc(sizeof(Dependency)); 4.11 if (newDep!=NULL){ 4.12 newDep->from_vp = from_vp; 4.13 newDep->from_task = from_task; 4.14 @@ -13,7 +13,7 @@ 4.15 } 4.16 4.17 NtoN* new_NtoN(int id){ 4.18 - NtoN* newn = (NtoN*) VMS_int__malloc(sizeof(NtoN)); 4.19 + NtoN* newn = (NtoN*) PR_int__malloc(sizeof(NtoN)); 4.20 newn->id = id; 4.21 newn->senders = makeListOfArrays(sizeof(Unit), 64); 4.22 newn->receivers = makeListOfArrays(sizeof(Unit), 64);
5.1 --- a/VSs.c Mon Sep 03 03:26:12 2012 -0700 5.2 +++ b/VSs.c Thu Oct 18 02:44:30 2012 -0700 5.3 @@ -16,11 +16,6 @@ 5.4 5.5 //========================================================================== 5.6 5.7 -void 5.8 -VSs__init(); 5.9 - 5.10 -void 5.11 -VSs__init_Helper(); 5.12 //========================================================================== 5.13 5.14 5.15 @@ -31,8 +26,8 @@ 5.16 /*These are the library functions *called in the application* 5.17 * 5.18 *There's a pattern for the outside sequential code to interact with the 5.19 - * VMS_HW code. 5.20 - *The VMS_HW system is inside a boundary.. every VSs system is in its 5.21 + * PR_HW code. 5.22 + *The PR_HW system is inside a boundary.. every VSs system is in its 5.23 * own directory that contains the functions for each of the processor types. 5.24 * One of the processor types is the "seed" processor that starts the 5.25 * cascade of creating all the processors that do the work. 5.26 @@ -58,60 +53,6 @@ 5.27 5.28 //=========================================================================== 5.29 5.30 -/*This is the "border crossing" function -- the thing that crosses from the 5.31 - * outside world, into the VMS_HW world. It initializes and starts up the 5.32 - * VMS system, then creates one processor from the specified function and 5.33 - * puts it into the readyQ. From that point, that one function is resp. 5.34 - * for creating all the other processors, that then create others, and so 5.35 - * forth. 5.36 - *When all the processors, including the seed, have dissipated, then this 5.37 - * function returns. The results will have been written by side-effect via 5.38 - * pointers read from, or written into initData. 5.39 - * 5.40 - *NOTE: no Threads should exist in the outside program that might touch 5.41 - * any of the data reachable from initData passed in to here 5.42 - */ 5.43 -void 5.44 -VSs__create_seed_slave_and_do_work( TopLevelFnPtr fnPtr, void *initData ) 5.45 - { VSsSemEnv *semEnv; 5.46 - SlaveVP *seedSlv; 5.47 - VSsSemData *semData; 5.48 - VSsTaskStub *threadTaskStub, *parentTaskStub; 5.49 - 5.50 - VSs__init(); //normal multi-thd 5.51 - 5.52 - semEnv = _VMSMasterEnv->semanticEnv; 5.53 - 5.54 - //VSs starts with one processor, which is put into initial environ, 5.55 - // and which then calls create() to create more, thereby expanding work 5.56 - seedSlv = VSs__create_slave_helper( fnPtr, initData, 5.57 - semEnv, semEnv->nextCoreToGetNewSlv++ ); 5.58 - 5.59 - //seed slave is a thread slave, so make a thread's task stub for it 5.60 - // and then make another to stand for the seed's parent task. Make 5.61 - // the parent be already ended, and have one child (the seed). This 5.62 - // will make the dissipate handler do the right thing when the seed 5.63 - // is dissipated. 5.64 - threadTaskStub = create_thread_task_stub( initData ); 5.65 - parentTaskStub = create_thread_task_stub( NULL ); 5.66 - parentTaskStub->isEnded = TRUE; 5.67 - parentTaskStub->numLiveChildThreads = 1; //so dissipate works for seed 5.68 - threadTaskStub->parentTaskStub = parentTaskStub; 5.69 - 5.70 - semData = (VSsSemData *)seedSlv->semanticData; 5.71 - //seedVP is a thread, so has a permanent task 5.72 - semData->needsTaskAssigned = FALSE; 5.73 - semData->taskStub = threadTaskStub; 5.74 - semData->slaveType = ThreadSlv; 5.75 - 5.76 - resume_slaveVP( seedSlv, semEnv ); //returns right away, just queues Slv 5.77 - 5.78 - VMS_SS__start_the_work_then_wait_until_done(); //normal multi-thd 5.79 - 5.80 - VSs__cleanup_after_shutdown(); 5.81 - } 5.82 - 5.83 - 5.84 int32 5.85 VSs__giveMinWorkUnitCycles( float32 percentOverhead ) 5.86 { 5.87 @@ -134,9 +75,12 @@ 5.88 * saves jump point, and second jumps back several times to get reliable time 5.89 */ 5.90 void 5.91 -VSs__start_primitive() 5.92 - { saveLowTimeStampCountInto( ((VSsSemEnv *)(_VMSMasterEnv->semanticEnv))-> 5.93 - primitiveStartTime ); 5.94 +VSs__begin_primitive() 5.95 + { VSsSemData *semData; 5.96 + 5.97 + semData = (VSsSemData *)PR_WL__give_sem_data( animSlv, VSs_MAGIC_NUMBER); 5.98 + 5.99 + saveLowTimeStampCountInto( semData->primitiveStartTime ); 5.100 } 5.101 5.102 /*Just quick and dirty for now -- make reliable later 5.103 @@ -145,262 +89,21 @@ 5.104 * also to throw out any "weird" values due to OS interrupt or TSC rollover 5.105 */ 5.106 int32 5.107 -VSs__end_primitive_and_give_cycles() 5.108 +VSs__end_primitive_and_give_cycles( SlaveVP animSlv ) 5.109 { int32 endTime, startTime; 5.110 + VSsSemData *semData; 5.111 + 5.112 //TODO: fix by repeating time-measurement 5.113 saveLowTimeStampCountInto( endTime ); 5.114 - startTime =((VSsSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime; 5.115 + semData = (VSsSemData *)PR_WL__give_sem_data( animSlv, VSs_MAGIC_NUMBER); 5.116 + startTime = semData->primitiveStartTime; 5.117 return (endTime - startTime); 5.118 } 5.119 5.120 + 5.121 //=========================================================================== 5.122 5.123 -/*Initializes all the data-structures for a VSs system -- but doesn't 5.124 - * start it running yet! 5.125 - * 5.126 - *This runs in the main thread -- before VMS starts up 5.127 - * 5.128 - *This sets up the semantic layer over the VMS system 5.129 - * 5.130 - *First, calls VMS_Setup, then creates own environment, making it ready 5.131 - * for creating the seed processor and then starting the work. 5.132 - */ 5.133 -void 5.134 -VSs__init() 5.135 - { 5.136 - VMS_SS__init(); 5.137 - //masterEnv, a global var, now is partially set up by init_VMS 5.138 - // after this, have VMS_int__malloc and VMS_int__free available 5.139 5.140 - VSs__init_Helper(); 5.141 - } 5.142 - 5.143 - 5.144 -void idle_fn(void* data, SlaveVP *animatingSlv){ 5.145 - while(1){ 5.146 - VMS_int__suspend_slaveVP_and_send_req(animatingSlv); 5.147 - } 5.148 -} 5.149 - 5.150 -void 5.151 -VSs__init_Helper() 5.152 - { VSsSemEnv *semanticEnv; 5.153 - int32 i, coreNum, slotNum; 5.154 - VSsSemData *semData; 5.155 - 5.156 - //Hook up the semantic layer's plug-ins to the Master virt procr 5.157 - _VMSMasterEnv->requestHandler = &VSs__Request_Handler; 5.158 - _VMSMasterEnv->slaveAssigner = &VSs__assign_slaveVP_to_slot; 5.159 - 5.160 - //create the semantic layer's environment (all its data) and add to 5.161 - // the master environment 5.162 - semanticEnv = VMS_int__malloc( sizeof( VSsSemEnv ) ); 5.163 - _VMSMasterEnv->semanticEnv = semanticEnv; 5.164 - 5.165 - #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 5.166 - _VMSMasterEnv->counterHandler = &VSs__counter_handler; 5.167 - VSs__init_counter_data_structs(); 5.168 - #endif 5.169 - 5.170 - semanticEnv->shutdownInitiated = FALSE; 5.171 - semanticEnv->coreIsDone = VMS_int__malloc( NUM_CORES * sizeof( bool32 ) ); 5.172 - //For each animation slot, there is an idle slave, and an initial 5.173 - // slave assigned as the current-task-slave. Create them here. 5.174 - SlaveVP *idleSlv, *slotTaskSlv; 5.175 - for( coreNum = 0; coreNum < NUM_CORES; coreNum++ ) 5.176 - { semanticEnv->coreIsDone[coreNum] = FALSE; //use during shutdown 5.177 - 5.178 - for( slotNum = 0; slotNum < NUM_ANIM_SLOTS; ++slotNum ) 5.179 - { idleSlv = VSs__create_slave_helper( &idle_fn, NULL, semanticEnv, 0); 5.180 - idleSlv->coreAnimatedBy = coreNum; 5.181 - idleSlv->animSlotAssignedTo = 5.182 - _VMSMasterEnv->allAnimSlots[coreNum][slotNum]; 5.183 - semanticEnv->idleSlv[coreNum][slotNum] = idleSlv; 5.184 - 5.185 - slotTaskSlv = VSs__create_slave_helper( &idle_fn, NULL, semanticEnv, 0); 5.186 - slotTaskSlv->coreAnimatedBy = coreNum; 5.187 - slotTaskSlv->animSlotAssignedTo = 5.188 - _VMSMasterEnv->allAnimSlots[coreNum][slotNum]; 5.189 - 5.190 - semData = slotTaskSlv->semanticData; 5.191 - semData->needsTaskAssigned = TRUE; 5.192 - semData->slaveType = SlotTaskSlv; 5.193 - semanticEnv->slotTaskSlvs[coreNum][slotNum] = slotTaskSlv; 5.194 - } 5.195 - } 5.196 - 5.197 - //create the ready queues, hash tables used for matching and so forth 5.198 - semanticEnv->slavesReadyToResumeQ = makeVMSQ(); 5.199 - semanticEnv->freeExtraTaskSlvQ = makeVMSQ(); 5.200 - semanticEnv->taskReadyQ = makeVMSQ(); 5.201 - 5.202 - semanticEnv->argPtrHashTbl = makeHashTable32( 16, &VMS_int__free ); 5.203 - semanticEnv->commHashTbl = makeHashTable32( 16, &VMS_int__free ); 5.204 - 5.205 - semanticEnv->nextCoreToGetNewSlv = 0; 5.206 - 5.207 - 5.208 - //TODO: bug -- turn these arrays into dyn arrays to eliminate limit 5.209 - //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( ); 5.210 - //semanticEnv->transactionStrucs = makeDynArrayInfo( ); 5.211 - for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ ) 5.212 - { 5.213 - semanticEnv->fnSingletons[i].endInstrAddr = NULL; 5.214 - semanticEnv->fnSingletons[i].hasBeenStarted = FALSE; 5.215 - semanticEnv->fnSingletons[i].hasFinished = FALSE; 5.216 - semanticEnv->fnSingletons[i].waitQ = makeVMSQ(); 5.217 - semanticEnv->transactionStrucs[i].waitingVPQ = makeVMSQ(); 5.218 - } 5.219 - 5.220 - semanticEnv->numLiveExtraTaskSlvs = 0; //must be last 5.221 - semanticEnv->numLiveThreadSlvs = 1; //must be last, counts the seed 5.222 - 5.223 - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 5.224 - semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128); 5.225 - semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128); 5.226 - semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128); 5.227 - semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128); 5.228 - semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8); 5.229 - 5.230 - semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128); 5.231 - memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_ANIM_SLOTS * sizeof(Unit))); 5.232 - #endif 5.233 - } 5.234 - 5.235 - 5.236 -/*Frees any memory allocated by VSs__init() then calls VMS_int__shutdown 5.237 - */ 5.238 -void 5.239 -VSs__cleanup_after_shutdown() 5.240 - { VSsSemEnv *semanticEnv; 5.241 - 5.242 - semanticEnv = _VMSMasterEnv->semanticEnv; 5.243 - 5.244 - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 5.245 - //UCC 5.246 - FILE* output; 5.247 - int n; 5.248 - char filename[255]; 5.249 - for(n=0;n<255;n++) 5.250 - { 5.251 - sprintf(filename, "./counters/UCC.%d",n); 5.252 - output = fopen(filename,"r"); 5.253 - if(output) 5.254 - { 5.255 - fclose(output); 5.256 - }else{ 5.257 - break; 5.258 - } 5.259 - } 5.260 - if(n<255){ 5.261 - printf("Saving UCC to File: %s ...\n", filename); 5.262 - output = fopen(filename,"w+"); 5.263 - if(output!=NULL){ 5.264 - set_dependency_file(output); 5.265 - //fprintf(output,"digraph Dependencies {\n"); 5.266 - //set_dot_file(output); 5.267 - //FIXME: first line still depends on counters being enabled, replace w/ unit struct! 5.268 - //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info ); 5.269 - forAllInListOfArraysDo(semanticEnv->unitList, &print_unit_to_file); 5.270 - forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); 5.271 - forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); 5.272 - forAllInDynArrayDo(semanticEnv->ntonGroupsInfo,&print_nton_to_file); 5.273 - //fprintf(output,"}\n"); 5.274 - fflush(output); 5.275 - 5.276 - } else 5.277 - printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 5.278 - } else { 5.279 - printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 5.280 - } 5.281 - //Loop Graph 5.282 - for(n=0;n<255;n++) 5.283 - { 5.284 - sprintf(filename, "./counters/LoopGraph.%d",n); 5.285 - output = fopen(filename,"r"); 5.286 - if(output) 5.287 - { 5.288 - fclose(output); 5.289 - }else{ 5.290 - break; 5.291 - } 5.292 - } 5.293 - if(n<255){ 5.294 - printf("Saving LoopGraph to File: %s ...\n", filename); 5.295 - output = fopen(filename,"w+"); 5.296 - if(output!=NULL){ 5.297 - set_dependency_file(output); 5.298 - //fprintf(output,"digraph Dependencies {\n"); 5.299 - //set_dot_file(output); 5.300 - //FIXME: first line still depends on counters being enabled, replace w/ unit struct! 5.301 - //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info ); 5.302 - forAllInListOfArraysDo( semanticEnv->unitList, &print_unit_to_file ); 5.303 - forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); 5.304 - forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); 5.305 - forAllInListOfArraysDo( semanticEnv->dynDependenciesList, &print_dyn_dependency_to_file ); 5.306 - forAllInListOfArraysDo( semanticEnv->hwArcs, &print_hw_dependency_to_file ); 5.307 - //fprintf(output,"}\n"); 5.308 - fflush(output); 5.309 - 5.310 - } else 5.311 - printf("Opening LoopGraph file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 5.312 - } else { 5.313 - printf("Could not open LoopGraph file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 5.314 - } 5.315 - 5.316 - 5.317 - freeListOfArrays(semanticEnv->unitList); 5.318 - freeListOfArrays(semanticEnv->commDependenciesList); 5.319 - freeListOfArrays(semanticEnv->ctlDependenciesList); 5.320 - freeListOfArrays(semanticEnv->dynDependenciesList); 5.321 - 5.322 - #endif 5.323 -#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 5.324 - for(n=0;n<255;n++) 5.325 - { 5.326 - sprintf(filename, "./counters/Counters.%d.csv",n); 5.327 - output = fopen(filename,"r"); 5.328 - if(output) 5.329 - { 5.330 - fclose(output); 5.331 - }else{ 5.332 - break; 5.333 - } 5.334 - } 5.335 - if(n<255){ 5.336 - printf("Saving Counter measurements to File: %s ...\n", filename); 5.337 - output = fopen(filename,"w+"); 5.338 - if(output!=NULL){ 5.339 - set_counter_file(output); 5.340 - int i; 5.341 - for(i=0;i<NUM_CORES;i++){ 5.342 - forAllInListOfArraysDo( semanticEnv->counterList[i], &print_counter_events_to_file ); 5.343 - fflush(output); 5.344 - } 5.345 - 5.346 - } else 5.347 - printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 5.348 - } else { 5.349 - printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 5.350 - } 5.351 - 5.352 -#endif 5.353 -/* It's all allocated inside VMS's big chunk -- that's about to be freed, so 5.354 - * nothing to do here 5.355 - 5.356 - 5.357 - for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 5.358 - { 5.359 - VMS_int__free( semanticEnv->readyVPQs[coreIdx]->startOfData ); 5.360 - VMS_int__free( semanticEnv->readyVPQs[coreIdx] ); 5.361 - } 5.362 - VMS_int__free( semanticEnv->readyVPQs ); 5.363 - 5.364 - freeHashTable( semanticEnv->commHashTbl ); 5.365 - VMS_int__free( _VMSMasterEnv->semanticEnv ); 5.366 - */ 5.367 - VMS_SS__cleanup_at_end_of_shutdown(); 5.368 - } 5.369 5.370 5.371 //=========================================================================== 5.372 @@ -408,18 +111,33 @@ 5.373 SlaveVP * 5.374 VSs__create_thread( TopLevelFnPtr fnPtr, void *initData, 5.375 SlaveVP *creatingThd ) 5.376 + { 5.377 + return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, NO_ID, 5.378 + ANY_CORE, creatingThd ); 5.379 + } 5.380 + 5.381 +SlaveVP * 5.382 +VSs__create_thread_w_ID( TopLevelFnPtr fnPtr, void *initData, int32 *thdID, 5.383 + SlaveVP *creatingThd ) 5.384 + { 5.385 + return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, thdID, 5.386 + ANY_CORE, creatingThd ); 5.387 + } 5.388 + 5.389 + 5.390 +SlaveVP * 5.391 +VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData, 5.392 + int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd ) 5.393 { VSsSemReq reqData; 5.394 5.395 //the semantic request data is on the stack and disappears when this 5.396 // call returns -- it's guaranteed to remain in the VP's stack for as 5.397 // long as the VP is suspended. 5.398 - reqData.reqType = 0; //know type because in a VMS create req 5.399 - reqData.fnPtr = fnPtr; 5.400 - reqData.initData = initData; 5.401 - reqData.callingSlv = creatingThd; 5.402 - 5.403 - VMS_WL__send_create_slaveVP_req( &reqData, creatingThd ); 5.404 - 5.405 + reqData.reqType = create_slave; //know type because in a PR create req 5.406 + reqData.coreToAssignOnto = coreToAssignOnto; 5.407 + 5.408 + PR_WL__send_create_slaveVP_req( &reqData, fnPtr, initData, thdID, 5.409 + creatingThd, VSs_MAGIC_NUMBER ); 5.410 return creatingThd->dataRetFromReq; 5.411 } 5.412 5.413 @@ -432,9 +150,8 @@ 5.414 */ 5.415 void 5.416 VSs__end_thread( SlaveVP *thdToEnd ) 5.417 - { VSsSemData *semData; 5.418 - 5.419 - VMS_WL__send_dissipate_req( thdToEnd ); 5.420 + { 5.421 + PR_WL__send_dissipate_req( thdToEnd, VSs_MAGIC_NUMBER ); 5.422 } 5.423 5.424 5.425 @@ -454,34 +171,25 @@ 5.426 reqData.taskType = taskType; 5.427 reqData.args = args; 5.428 reqData.callingSlv = animSlv; 5.429 - 5.430 - reqData.taskID = NULL; 5.431 - 5.432 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.433 - } 5.434 - 5.435 -inline int32 * 5.436 -VSs__create_taskID_of_size( int32 numInts, SlaveVP *animSlv ) 5.437 - { int32 *taskID; 5.438 5.439 - taskID = VMS_WL__malloc( sizeof(int32) + numInts * sizeof(int32) ); 5.440 - taskID[0] = numInts; 5.441 - return taskID; 5.442 + //Create task is a special form, so have to pass as parameters, the 5.443 + // top-level-fn of task and the data for that fn, plus lang's req, 5.444 + // animating slave, and lang's magic number 5.445 + PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID, animSlv, VSs_MAGIC_NUMBER ); 5.446 } 5.447 5.448 void 5.449 VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID, 5.450 SlaveVP *animSlv) 5.451 { VSsSemReq reqData; 5.452 - 5.453 + 5.454 reqData.reqType = submit_task; 5.455 5.456 reqData.taskType = taskType; 5.457 reqData.args = args; 5.458 - reqData.taskID = taskID; 5.459 reqData.callingSlv = animSlv; 5.460 5.461 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.462 + PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID, animSlv, VSs_MAGIC_NUMBER ); 5.463 } 5.464 5.465 5.466 @@ -490,8 +198,8 @@ 5.467 * assigner here.. only one slave, no slave ReadyQ, and so on.. 5.468 *Can either make the assigner take the next task out of the taskQ, or can 5.469 * leave all as it is, and make task-end take the next task. 5.470 - *Note: this fits the case in the new VMS for no-context tasks, so will use 5.471 - * the built-in taskQ of new VMS, and should be local and much faster. 5.472 + *Note: this fits the case in the new PR for no-context tasks, so will use 5.473 + * the built-in taskQ of new PR, and should be local and much faster. 5.474 * 5.475 *The task-stub is saved in the animSlv, so the request handler will get it 5.476 * from there, along with the task-type which has arg types, and so on.. 5.477 @@ -500,7 +208,7 @@ 5.478 * instead, can make a single slave per core, and coreCtrlr looks up the 5.479 * slave from having the core number. 5.480 * 5.481 - *But, to stay compatible with all the other VMS languages, leave it in.. 5.482 + *But, to stay compatible with all the other PR languages, leave it in.. 5.483 */ 5.484 void 5.485 VSs__end_task( SlaveVP *animSlv ) 5.486 @@ -509,20 +217,23 @@ 5.487 reqData.reqType = end_task; 5.488 reqData.callingSlv = animSlv; 5.489 5.490 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.491 + PR_WL__send_end_task_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.492 } 5.493 5.494 5.495 +/*Waits for all tasks that are direct children to end, then resumes calling 5.496 + * task or thread 5.497 + */ 5.498 void 5.499 VSs__taskwait(SlaveVP *animSlv) 5.500 -{ 5.501 + { 5.502 VSsSemReq reqData; 5.503 5.504 reqData.reqType = taskwait; 5.505 reqData.callingSlv = animSlv; 5.506 5.507 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.508 -} 5.509 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.510 + } 5.511 5.512 5.513 5.514 @@ -532,7 +243,7 @@ 5.515 inline int32 * 5.516 VSs__give_self_taskID( SlaveVP *animSlv ) 5.517 { 5.518 - return ((VSsSemData*)animSlv->semanticData)->taskStub->taskID; 5.519 + return PR__give_task_ID( animSlv, VSs_MAGIC_NUMBER ); 5.520 } 5.521 5.522 //================================ send =================================== 5.523 @@ -551,7 +262,7 @@ 5.524 5.525 reqData.nextReqInHashEntry = NULL; 5.526 5.527 - VMS_WL__send_sem_request( &reqData, senderSlv ); 5.528 + PR_WL__send_sem_request( &reqData, senderSlv, VSs_MAGIC_NUMBER ); 5.529 5.530 //When come back from suspend, no longer own data reachable from msg 5.531 } 5.532 @@ -569,7 +280,7 @@ 5.533 5.534 reqData.nextReqInHashEntry = NULL; 5.535 5.536 - VMS_WL__send_sem_request( &reqData, senderSlv ); 5.537 + PR_WL__send_sem_request( &reqData, senderSlv, VSs_MAGIC_NUMBER ); 5.538 } 5.539 5.540 5.541 @@ -594,7 +305,7 @@ 5.542 5.543 reqData.nextReqInHashEntry = NULL; 5.544 5.545 - VMS_WL__send_sem_request( &reqData, receiverSlv ); 5.546 + PR_WL__send_sem_request( &reqData, receiverSlv, VSs_MAGIC_NUMBER ); 5.547 5.548 return receiverSlv->dataRetFromReq; 5.549 } 5.550 @@ -619,7 +330,7 @@ 5.551 reqData.nextReqInHashEntry = NULL; 5.552 DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]); 5.553 5.554 - VMS_WL__send_sem_request( &reqData, receiverSlv ); 5.555 + PR_WL__send_sem_request( &reqData, receiverSlv, VSs_MAGIC_NUMBER ); 5.556 5.557 return receiverSlv->dataRetFromReq; 5.558 } 5.559 @@ -655,10 +366,10 @@ 5.560 reqData.reqType = singleton_fn_start; 5.561 reqData.singletonID = singletonID; 5.562 5.563 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.564 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.565 if( animSlv->dataRetFromReq ) //will be 0 or addr of label in end singleton 5.566 { 5.567 - VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animSlv ); 5.568 + VSsSemEnv *semEnv = PR_WL__give_sem_env_for( animSlv, VSs_MAGIC_NUMBER ); 5.569 asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 5.570 } 5.571 } 5.572 @@ -678,7 +389,7 @@ 5.573 reqData.reqType = singleton_data_start; 5.574 reqData.singletonPtrAddr = singletonAddr; 5.575 5.576 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.577 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.578 if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr 5.579 { //Assembly code changes the return addr on the stack to the one 5.580 // saved into the singleton by the end-singleton-fn 5.581 @@ -703,13 +414,13 @@ 5.582 5.583 //don't need this addr until after at least one singleton has reached 5.584 // this function 5.585 - VSsSemEnv *semEnv = VMS_int__give_sem_env_for( animSlv ); 5.586 + VSsSemEnv *semEnv = PR_WL__give_sem_env_for( animSlv, VSs_MAGIC_NUMBER ); 5.587 asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 5.588 5.589 reqData.reqType = singleton_fn_end; 5.590 reqData.singletonID = singletonID; 5.591 5.592 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.593 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.594 5.595 EndSingletonInstrAddr: 5.596 return; 5.597 @@ -726,15 +437,12 @@ 5.598 // data singleton -- that data-singleton can only be given to exactly 5.599 // one instance in the code of this function. However, can use this 5.600 // function in different places for different data-singletons. 5.601 -// (*(singletonAddr))->endInstrAddr = &&EndDataSingletonInstrAddr; 5.602 - 5.603 - 5.604 asm_save_ret_to_singleton(*singletonPtrAddr); 5.605 5.606 reqData.reqType = singleton_data_end; 5.607 reqData.singletonPtrAddr = singletonPtrAddr; 5.608 5.609 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.610 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.611 } 5.612 5.613 /*This executes the function in the masterVP, so it executes in isolation 5.614 @@ -758,7 +466,7 @@ 5.615 reqData.fnToExecInMaster = ptrToFnToExecInMaster; 5.616 reqData.dataForFn = data; 5.617 5.618 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.619 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.620 } 5.621 5.622 5.623 @@ -781,11 +489,11 @@ 5.624 VSsSemReq reqData; 5.625 5.626 // 5.627 - reqData.callingSlv = animSlv; 5.628 + reqData.callingSlv = animSlv; 5.629 reqData.reqType = trans_start; 5.630 reqData.transID = transactionID; 5.631 5.632 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.633 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.634 } 5.635 5.636 /*This suspends to the master, then uses transactionID as index into an 5.637 @@ -807,30 +515,12 @@ 5.638 reqData.reqType = trans_end; 5.639 reqData.transID = transactionID; 5.640 5.641 - VMS_WL__send_sem_request( &reqData, animSlv ); 5.642 + PR_WL__send_sem_request( &reqData, animSlv, VSs_MAGIC_NUMBER ); 5.643 } 5.644 5.645 //======================== Internal ================================== 5.646 /* 5.647 */ 5.648 -SlaveVP * 5.649 -VSs__create_slave_with( TopLevelFnPtr fnPtr, void *initData, 5.650 - SlaveVP *creatingSlv ) 5.651 - { VSsSemReq reqData; 5.652 - 5.653 - //the semantic request data is on the stack and disappears when this 5.654 - // call returns -- it's guaranteed to remain in the VP's stack for as 5.655 - // long as the VP is suspended. 5.656 - reqData.reqType = 0; //know type because in a VMS create req 5.657 - reqData.coreToAssignOnto = -1; //means round-robin assign 5.658 - reqData.fnPtr = fnPtr; 5.659 - reqData.initData = initData; 5.660 - reqData.callingSlv = creatingSlv; 5.661 - 5.662 - VMS_WL__send_create_slaveVP_req( &reqData, creatingSlv ); 5.663 - 5.664 - return creatingSlv->dataRetFromReq; 5.665 - } 5.666 5.667 SlaveVP * 5.668 VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, 5.669 @@ -846,7 +536,7 @@ 5.670 reqData.initData = initData; 5.671 reqData.callingSlv = creatingSlv; 5.672 5.673 - VMS_WL__send_create_slaveVP_req( &reqData, creatingSlv ); 5.674 + PR_WL__send_create_slaveVP_req( &reqData, creatingSlv, VSs_MAGIC_NUMBER ); 5.675 5.676 return creatingSlv->dataRetFromReq; 5.677 }
6.1 --- a/VSs.h Mon Sep 03 03:26:12 2012 -0700 6.2 +++ b/VSs.h Thu Oct 18 02:44:30 2012 -0700 6.3 @@ -11,24 +11,28 @@ 6.4 6.5 #include "Queue_impl/PrivateQueue.h" 6.6 #include "Hash_impl/PrivateHash.h" 6.7 -#include "VMS_impl/VMS.h" 6.8 +#include "PR_impl/PR.h" 6.9 #include "Measurement/dependency.h" 6.10 6.11 6.12 //=========================================================================== 6.13 + //uniquely identifies VSs -- should be a jenkins char-hash of "VSs" to int32 6.14 +#define VSs_MAGIC_NUMBER 0000000001 6.15 + 6.16 #define NUM_STRUCS_IN_SEM_ENV 1000 6.17 6.18 //This is hardware dependent -- it's the number of cycles of scheduling 6.19 // overhead -- if a work unit is fewer than this, it is better being 6.20 // combined sequentially with other work 6.21 - //This value depends on both VMS overhead and VSs's plugin. At some point 6.22 + //This value depends on both PR overhead and VSs's plugin. At some point 6.23 // it will be derived by perf-counter measurements during init of VSs 6.24 #define MIN_WORK_UNIT_CYCLES 20000 6.25 6.26 //=========================================================================== 6.27 /*This header defines everything specific to the VSs semantic plug-in 6.28 */ 6.29 -typedef struct _VSsSemReq VSsSemReq; 6.30 +typedef struct _VSsSemReq VSsSemReq; 6.31 +typedef struct _VSsTaskStub VSsTaskStub; 6.32 typedef void (*VSsTaskFnPtr ) ( void *, SlaveVP *); 6.33 typedef void (*PtrToAtomicFn ) ( void * ); //executed atomically in master 6.34 //=========================================================================== 6.35 @@ -45,6 +49,10 @@ 6.36 #define IS_ENDED NULL 6.37 #define SEED_SLV NULL 6.38 6.39 +#define NO_ID NULL 6.40 +#define ANY_CORE -1 6.41 + 6.42 +//=========================================================================== 6.43 typedef struct 6.44 { 6.45 VSsTaskFnPtr fn; 6.46 @@ -65,22 +73,24 @@ 6.47 } 6.48 VSsPointerEntry; 6.49 6.50 -typedef struct 6.51 +/*This is placed into semData, used for dependencies and wait construct*/ 6.52 +struct _VSsTaskStub 6.53 { 6.54 - void **args; //ctld args must come first, as ptrs 6.55 - VSsTaskType *taskType; 6.56 - int32 *taskID; 6.57 - int32 numBlockingProp; 6.58 - SlaveVP *slaveAssignedTo; //only valid before end task (thread) 6.59 - VSsPointerEntry **ptrEntries; 6.60 - void* parentTaskStub; 6.61 + int32 langMagicNumber; //magic num must be 1st field of langMetaTask 6.62 + PRMetaTask *protoMetaTask; //back-link must always be 2nd field 6.63 + void **args; //ctld args must be the first ones (as ptrs) 6.64 + VSsPointerEntry **ptrEntries; 6.65 + int32 numBlockingProp; 6.66 + 6.67 + VSsTaskType *taskType; //has VSs lang related info 6.68 + 6.69 + VSsTaskStub *parentTaskStub; //for liveness, for the wait construct 6.70 int32 numLiveChildTasks; 6.71 int32 numLiveChildThreads; 6.72 bool32 isWaitingForChildTasksToEnd; 6.73 bool32 isWaitingForChildThreadsToEnd; 6.74 bool32 isEnded; 6.75 - } 6.76 -VSsTaskStub; 6.77 + }; 6.78 6.79 6.80 typedef struct 6.81 @@ -144,7 +154,7 @@ 6.82 SlaveVP *callingSlv; 6.83 VSsTaskType *taskType; 6.84 void *args; 6.85 - VSsTaskStub *taskStub; 6.86 +// VSsTaskStub *taskStub; //not needed -- get via PR accessor from slv 6.87 6.88 SlaveVP *senderSlv; 6.89 SlaveVP *receiverSlv; 6.90 @@ -153,12 +163,13 @@ 6.91 int32 msgType; 6.92 void *msg; 6.93 VSsSemReq *nextReqInHashEntry; 6.94 - int32 *taskID; 6.95 +//In PRReq: int32 *taskID; 6.96 6.97 TopLevelFnPtr fnPtr; 6.98 void *initData; 6.99 int32 coreToAssignOnto; 6.100 6.101 +//These, below, should move to util language.. 6.102 int32 sizeToMalloc; 6.103 void *ptrToFree; 6.104 6.105 @@ -174,15 +185,15 @@ 6.106 6.107 6.108 typedef struct 6.109 - { 6.110 + { PRSemEnv *protoSemEnv; 6.111 PrivQueueStruc *slavesReadyToResumeQ; //Shared (slaves not pinned) 6.112 - PrivQueueStruc *freeExtraTaskSlvQ; //Shared 6.113 + PrivQueueStruc *freeTaskSlvRecycleQ; //Shared 6.114 PrivQueueStruc *taskReadyQ; //Shared (tasks not pinned) 6.115 - SlaveVP *slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; 6.116 +// SlaveVP *slotTaskSlvs[NUM_CORES][NUM_ANIM_SLOTS]; 6.117 HashTable *argPtrHashTbl; 6.118 HashTable *commHashTbl; 6.119 - int32 numLiveExtraTaskSlvs; 6.120 - int32 numLiveThreadSlvs; 6.121 +// int32 numLiveFreeTaskSlvs; 6.122 +// int32 numLiveThreadSlvs; 6.123 int32 nextCoreToGetNewSlv; 6.124 int32 primitiveStartTime; 6.125 6.126 @@ -190,8 +201,11 @@ 6.127 VSsSingleton fnSingletons[NUM_STRUCS_IN_SEM_ENV]; 6.128 VSsTrans transactionStrucs[NUM_STRUCS_IN_SEM_ENV]; 6.129 6.130 - bool32 *coreIsDone; 6.131 - int32 numCoresDone; 6.132 +// bool32 *coreIsDone; 6.133 +// int32 numCoresDone; 6.134 + 6.135 +// SlaveVP* idleSlv[NUM_CORES][NUM_ANIM_SLOTS]; 6.136 +// int shutdownInitiated; 6.137 6.138 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 6.139 ListOfArrays* unitList; 6.140 @@ -207,8 +221,6 @@ 6.141 #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 6.142 ListOfArrays* counterList[NUM_CORES]; 6.143 #endif 6.144 - SlaveVP* idleSlv[NUM_CORES][NUM_ANIM_SLOTS]; 6.145 - int shutdownInitiated; 6.146 } 6.147 VSsSemEnv; 6.148 6.149 @@ -221,19 +233,20 @@ 6.150 }; 6.151 //TransListElem 6.152 6.153 +/* PR now handles what this used to be used for 6.154 enum VSsSlvType 6.155 - { ExtraTaskSlv = 1, 6.156 + { FreeTaskSlv = 1, 6.157 SlotTaskSlv, 6.158 ThreadSlv 6.159 }; 6.160 +*/ 6.161 6.162 typedef struct 6.163 { 6.164 - int32 highestTransEntered; 6.165 - TransListElem *lastTransEntered; 6.166 - bool32 needsTaskAssigned; 6.167 - VSsTaskStub *taskStub; 6.168 - enum VSsSlvType slaveType; 6.169 + int32 highestTransEntered; 6.170 + TransListElem *lastTransEntered; 6.171 + int32 primitiveStartTime; 6.172 +// VSsTaskStub *taskStub; //get from slave via PR accessor 6.173 } 6.174 VSsSemData; 6.175 6.176 @@ -246,7 +259,7 @@ 6.177 VSs__giveMinWorkUnitCycles( float32 percentOverhead ); 6.178 6.179 void 6.180 -VSs__start_primitive(); 6.181 +VSs__begin_primitive(); 6.182 6.183 int32 6.184 VSs__end_primitive_and_give_cycles(); 6.185 @@ -260,7 +273,7 @@ 6.186 //======================= 6.187 6.188 void 6.189 -VSs__init(); 6.190 +VSs__start( SlaveVP *seedSlv ); 6.191 6.192 void 6.193 VSs__cleanup_after_shutdown(); 6.194 @@ -276,9 +289,9 @@ 6.195 6.196 //======================= 6.197 6.198 -#define VSs__malloc( numBytes, callingSlave ) VMS_App__malloc( numBytes, callingSlave) 6.199 +#define VSs__malloc( numBytes, callingSlave ) PR_App__malloc( numBytes, callingSlave) 6.200 6.201 -#define VSs__free(ptrToFree, callingSlave ) VMS_App__free( ptrToFree, callingSlave ) 6.202 +#define VSs__free(ptrToFree, callingSlave ) PR_App__free( ptrToFree, callingSlave ) 6.203 6.204 6.205 //======================= 6.206 @@ -351,8 +364,8 @@ 6.207 VSs__create_slave_helper( TopLevelFnPtr fnPtr, void *initData, 6.208 VSsSemEnv *semEnv, int32 coreToAssignOnto ); 6.209 6.210 -VSsTaskStub * 6.211 -create_thread_task_stub( void *initData ); 6.212 +PRMetaTask * 6.213 +PR_int__create_generic_slave_meta_task( void *initData ); 6.214 6.215 6.216 SlaveVP * 6.217 @@ -363,9 +376,6 @@ 6.218 VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData, 6.219 SlaveVP *creatingSlv, int32 coreToAssignOnto); 6.220 6.221 -void 6.222 -idle_fn(void* data, SlaveVP *animatingSlv); 6.223 - 6.224 //===================== Measurement of Lang Overheads ===================== 6.225 #include "Measurement/VSs_Measurement.h" 6.226
7.1 --- a/VSs_PluginFns.c Mon Sep 03 03:26:12 2012 -0700 7.2 +++ b/VSs_PluginFns.c Thu Oct 18 02:44:30 2012 -0700 7.3 @@ -16,13 +16,13 @@ 7.4 resume_slaveVP( SlaveVP *slave, VSsSemEnv *semEnv ); 7.5 7.6 inline void 7.7 -handleSemReq( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); 7.8 +handleSemReq( PRReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); 7.9 7.10 inline void 7.11 handleDissipate( SlaveVP *requestingSlv, VSsSemEnv *semEnv ); 7.12 7.13 inline void 7.14 -handleCreate( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); 7.15 +handleCreate( PRReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ); 7.16 7.17 //============================== Assigner ================================== 7.18 // 7.19 @@ -30,6 +30,9 @@ 7.20 * VPs, and by tasks being able to suspend. 7.21 *It can't use an explicit slave to animate a task because of stack 7.22 * pollution. So, it has to keep the two kinds separate. 7.23 + * 7.24 + *Q: one assigner for both tasks and slaves, or separate? 7.25 + * 7.26 *Simplest way for the assigner logic is with a Q for extra empty task 7.27 * slaves, and another Q for slaves of both types that are ready to resume. 7.28 * 7.29 @@ -52,10 +55,8 @@ 7.30 VSs__assign_slaveVP_to_slot( void *_semEnv, AnimSlot *slot ) 7.31 { SlaveVP *returnSlv; 7.32 VSsSemEnv *semEnv; 7.33 - VSsSemData *semData; 7.34 int32 coreNum, slotNum; 7.35 - VSsTaskStub *newTaskStub; 7.36 - SlaveVP *extraSlv; 7.37 + PRMetaTask *returnMetaTask = NULL, *newTaskStub; 7.38 7.39 coreNum = slot->coreSlotIsOn; 7.40 slotNum = slot->slotIdx; 7.41 @@ -66,173 +67,79 @@ 7.42 returnSlv = readPrivQ( semEnv->slavesReadyToResumeQ ); 7.43 if( returnSlv != NULL ) //Yes, have a slave, so return it. 7.44 { returnSlv->coreAnimatedBy = coreNum; 7.45 - 7.46 - //have work, so reset Done flag (when work generated on other core) 7.47 - if( semEnv->coreIsDone[coreNum] == TRUE ) //reads are higher perf 7.48 - semEnv->coreIsDone[coreNum] = FALSE; //don't just write always 7.49 - goto ReturnTheSlv; 7.50 + returnMetaTask = returnSlv->metaTask; 7.51 + goto ReturnTheMetaTask; 7.52 } 7.53 7.54 - //If none, speculate will have a task, so get the slot slave 7.55 - //TODO: false sharing ? (think not bad cause mostly read..) 7.56 - returnSlv = semEnv->slotTaskSlvs[coreNum][slotNum]; 7.57 - 7.58 - semData = (VSsSemData *)returnSlv->semanticData; 7.59 - 7.60 - //There is always a curr task slave, and it always needs a task 7.61 - // (task slaves that are resuming are in resumeQ) 7.62 newTaskStub = readPrivQ( semEnv->taskReadyQ ); 7.63 if( newTaskStub != NULL ) 7.64 - { //point slave to task's function, and mark slave as having task 7.65 - VMS_int__reset_slaveVP_to_TopLvlFn( returnSlv, 7.66 - newTaskStub->taskType->fn, newTaskStub->args ); 7.67 - semData->taskStub = newTaskStub; 7.68 - newTaskStub->slaveAssignedTo = returnSlv; 7.69 - semData->needsTaskAssigned = FALSE; 7.70 - 7.71 - //have work, so reset Done flag, if was set 7.72 - if( semEnv->coreIsDone[coreNum] == TRUE ) //reads are higher perf 7.73 - semEnv->coreIsDone[coreNum] = FALSE; //don't just write always 7.74 - goto ReturnTheSlv; 7.75 + { returnMetaTask = newTaskStub->protoMetaTask; 7.76 + goto ReturnTheMetaTask; 7.77 } 7.78 - else 7.79 - { //no task, so try to clean up unused extra task slaves 7.80 - extraSlv = readPrivQ( semEnv->freeExtraTaskSlvQ ); 7.81 - if( extraSlv != NULL ) 7.82 - { //have two slaves need tasks, so delete one 7.83 - //This both bounds the num extras, and delivers shutdown cond 7.84 - handleDissipate( extraSlv, semEnv ); 7.85 - //then return NULL 7.86 - returnSlv = NULL; 7.87 - goto ReturnTheSlv; 7.88 - } 7.89 - else 7.90 - { //candidate for shutdown.. if all extras dissipated, and no tasks 7.91 - // and no ready to resume slaves, then no way to generate 7.92 - // more tasks (on this core -- other core might have task still) 7.93 - if( semEnv->numLiveExtraTaskSlvs == 0 && 7.94 - semEnv->numLiveThreadSlvs == 0 ) 7.95 - { //This core sees no way to generate more tasks, so say it 7.96 - if( semEnv->coreIsDone[coreNum] == FALSE ) 7.97 - { semEnv->numCoresDone += 1; 7.98 - semEnv->coreIsDone[coreNum] = TRUE; 7.99 - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 7.100 - semEnv->shutdownInitiated = TRUE; 7.101 - 7.102 - #else 7.103 - if( semEnv->numCoresDone == NUM_CORES ) 7.104 - { //means no cores have work, and none can generate more 7.105 - semEnv->shutdownInitiated = TRUE; 7.106 - } 7.107 - #endif 7.108 - } 7.109 - } 7.110 - //return NULL.. no task and none to resume 7.111 - returnSlv = NULL; 7.112 - //except if shutdown has been initiated by this or other core 7.113 - if(semEnv->shutdownInitiated) 7.114 - { returnSlv = VMS_SS__create_shutdown_slave(); 7.115 - } 7.116 - goto ReturnTheSlv; //don't need, but completes pattern 7.117 - } //if( extraSlv != NULL ) 7.118 - } //if( newTaskStub == NULL ) 7.119 - //outcome: 1)slave was just pointed to task, 2)no tasks, so slave NULL 7.120 7.121 -ReturnTheSlv: //Nina, doing gotos to here should help with holistic.. 7.122 +ReturnTheMetaTask: //doing gotos to here should help with holistic.. 7.123 7.124 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.125 - if( returnSlv == NULL ) 7.126 - { returnSlv = semEnv->idleSlv[coreNum][slotNum]; 7.127 + //This no longer works -- should be moved into PR in master 7.128 + //This assumes the task has already been assigned to a slave, which happens 7.129 + // inside Master.. 7.130 + if( returnMetaTask == NULL ) 7.131 + { returnSlv = semEnv->process->idleSlv[coreNum][slotNum]; 7.132 7.133 //things that would normally happen in resume(), but these VPs 7.134 // never go there 7.135 - returnSlv->assignCount++; //Somewhere here! 7.136 - Unit newu; 7.137 - newu.vp = returnSlv->slaveID; 7.138 - newu.task = returnSlv->assignCount; 7.139 - addToListOfArrays(Unit,newu,semEnv->unitList); 7.140 + returnSlv->numTimesAssignedToASlot++; 7.141 + Unit newU; 7.142 + newU.vp = returnSlv->slaveID; 7.143 + newU.task = returnSlv->numTimesAssignedToASlot; 7.144 + addToListOfArrays(Unit,newU,semEnv->unitList); 7.145 7.146 - if (returnSlv->assignCount > 1) 7.147 - { Dependency newd; 7.148 - newd.from_vp = returnSlv->slaveID; 7.149 - newd.from_task = returnSlv->assignCount - 1; 7.150 - newd.to_vp = returnSlv->slaveID; 7.151 - newd.to_task = returnSlv->assignCount; 7.152 - addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); 7.153 + if (returnSlv->numTimesAssignedToASlot > 1) 7.154 + { Dependency newD; 7.155 + newD.from_vp = returnSlv->slaveID; 7.156 + newD.from_task = returnSlv->numTimesAssignedToASlot - 1; 7.157 + newD.to_vp = returnSlv->slaveID; 7.158 + newD.to_task = returnSlv->numTimesAssignedToASlot; 7.159 + addToListOfArrays(Dependency, newD, semEnv->ctlDependenciesList); 7.160 } 7.161 + returnMetaTask = returnSlv->metaTask; 7.162 } 7.163 - #endif 7.164 - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.165 - if( returnSlv != NULL ) 7.166 + else //returnSlv != NULL 7.167 { //assignSlv->numTimesAssigned++; 7.168 Unit prev_in_slot = 7.169 semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum]; 7.170 if(prev_in_slot.vp != 0) 7.171 - { Dependency newd; 7.172 - newd.from_vp = prev_in_slot.vp; 7.173 - newd.from_task = prev_in_slot.task; 7.174 - newd.to_vp = returnSlv->slaveID; 7.175 - newd.to_task = returnSlv->assignCount; 7.176 - addToListOfArrays(Dependency,newd,semEnv->hwArcs); 7.177 + { Dependency newD; 7.178 + newD.from_vp = prev_in_slot.vp; 7.179 + newD.from_task = prev_in_slot.task; 7.180 + newD.to_vp = returnSlv->slaveID; 7.181 + newD.to_task = returnSlv->numTimesAssignedToASlot; 7.182 + addToListOfArrays(Dependency,newD,semEnv->hwArcs); 7.183 } 7.184 prev_in_slot.vp = returnSlv->slaveID; 7.185 - prev_in_slot.task = returnSlv->assignCount; 7.186 + prev_in_slot.task = returnSlv->numTimesAssignedToASlot; 7.187 semEnv->last_in_slot[coreNum * NUM_ANIM_SLOTS + slotNum] = 7.188 prev_in_slot; 7.189 } 7.190 #endif 7.191 - return( returnSlv ); 7.192 + return( returnMetaTask ); 7.193 } 7.194 7.195 7.196 //=========================== Request Handler ============================ 7.197 // 7.198 /* 7.199 - * (BTW not inline because invoked indirectly via a pointer) 7.200 + * (Not inline because invoked indirectly via a pointer) 7.201 */ 7.202 + 7.203 void 7.204 -VSs__Request_Handler( SlaveVP *requestingSlv, void *_semEnv ) 7.205 - { VSsSemEnv *semEnv; 7.206 - VMSReqst *req; 7.207 - 7.208 - semEnv = (VSsSemEnv *)_semEnv; 7.209 - 7.210 - req = VMS_PI__take_next_request_out_of( requestingSlv ); 7.211 - 7.212 - while( req != NULL ) 7.213 - { 7.214 - switch( req->reqType ) 7.215 - { case semantic: handleSemReq( req, requestingSlv, semEnv); 7.216 - break; 7.217 - case createReq: handleCreate( req, requestingSlv, semEnv); 7.218 - break; 7.219 - case dissipate: handleDissipate( requestingSlv, semEnv); 7.220 - break; 7.221 - case VMSSemantic: VMS_PI__handle_VMSSemReq(req, requestingSlv, semEnv, 7.222 - (ResumeSlvFnPtr) &resume_slaveVP); 7.223 - break; 7.224 - default: 7.225 - break; 7.226 - } 7.227 - 7.228 - req = VMS_PI__take_next_request_out_of( requestingSlv ); 7.229 - } //while( req != NULL ) 7.230 - 7.231 - } 7.232 - 7.233 - 7.234 -inline void 7.235 -handleSemReq( VMSReqst *req, SlaveVP *reqSlv, VSsSemEnv *semEnv ) 7.236 +handleSemReq( PRReqst *req, SlaveVP *reqSlv, VSsSemEnv *semEnv ) 7.237 { VSsSemReq *semReq; 7.238 7.239 - semReq = VMS_PI__take_sem_reqst_from(req); 7.240 + semReq = PR_PI__take_sem_reqst_from(req); 7.241 if( semReq == NULL ) return; 7.242 switch( semReq->reqType ) //sem handlers are all in other file 7.243 { 7.244 - case submit_task: handleSubmitTask( semReq, semEnv); 7.245 - break; 7.246 - case end_task: handleEndTask( semReq, semEnv); 7.247 - break; 7.248 case send_type_to: handleSendTypeTo( semReq, semEnv); 7.249 break; 7.250 case send_from_to: handleSendFromTo( semReq, semEnv); 7.251 @@ -268,209 +175,6 @@ 7.252 7.253 7.254 7.255 -//=========================== VMS Request Handlers ============================== 7.256 -/*SlaveVP dissipate -- this is NOT task-end!, only call this to get rid of 7.257 - * extra task slaves, and to end explicitly created threads 7.258 - */ 7.259 -inline void 7.260 -handleDissipate( SlaveVP *requestingSlv, VSsSemEnv *semEnv ) 7.261 - { VSsSemData *semData; 7.262 - VSsTaskStub *parentTaskStub, *ownTaskStub; 7.263 - 7.264 - DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d", 7.265 - requestingSlv->slaveID) 7.266 - semData = (VSsSemData *)requestingSlv->semanticData; 7.267 - 7.268 - if( semData->slaveType == ExtraTaskSlv ) 7.269 - { semEnv->numLiveExtraTaskSlvs -= 1; //for detecting shutdown condition 7.270 - //Has no task assigned, so no parents and no children, so free self 7.271 - goto FreeSlaveStateAndReturn; 7.272 - } 7.273 - 7.274 - if( semData->slaveType == SlotTaskSlv ) 7.275 - { //should never call dissipate on a slot assigned slave 7.276 - VMS_PI__throw_exception( "dissipate a slot-assigned slave", requestingSlv, NULL ); 7.277 - } 7.278 - 7.279 - //if make it to here, then is a thread slave ending 7.280 - semEnv->numLiveThreadSlvs -= 1; //for detecting shutdown condition 7.281 - 7.282 - ownTaskStub = semData->taskStub; 7.283 - parentTaskStub = ownTaskStub->parentTaskStub; 7.284 - parentTaskStub->numLiveChildThreads -= 1; //not freed, even if ended 7.285 - 7.286 - //if all children ended, then free this task's stub 7.287 - // else, keep stub around, and last child will free it (below) 7.288 - if( ownTaskStub->numLiveChildTasks == 0 && 7.289 - ownTaskStub->numLiveChildThreads == 0 ) 7.290 - free_task_stub( ownTaskStub ); 7.291 - else 7.292 - ownTaskStub->isEnded = TRUE; //for children to see when they end 7.293 - 7.294 - //Now, check on parents waiting on child threads to end 7.295 - if( parentTaskStub->isWaitingForChildThreadsToEnd && 7.296 - parentTaskStub->numLiveChildThreads == 0 ) 7.297 - { parentTaskStub->isWaitingForChildThreadsToEnd = FALSE; 7.298 - if( parentTaskStub->isWaitingForChildTasksToEnd ) 7.299 - return; //still waiting on tasks (should be impossible) 7.300 - else //parent free to resume 7.301 - resume_slaveVP( parentTaskStub->slaveAssignedTo, semEnv ); 7.302 - } 7.303 - 7.304 - //check if this is last child of ended parent (note, not possible to 7.305 - // have more than one level of ancestor waiting to be freed) 7.306 - if( parentTaskStub->isEnded ) 7.307 - { if( parentTaskStub->numLiveChildTasks == 0 && 7.308 - parentTaskStub->numLiveChildThreads == 0 ) 7.309 - free_task_stub( parentTaskStub ); //just stub, semData already freed 7.310 - } 7.311 - 7.312 - //Free the semData and requesting slave's base state for all cases 7.313 - FreeSlaveStateAndReturn: 7.314 - VMS_PI__free( semData ); 7.315 - VMS_PI__dissipate_slaveVP( requestingSlv ); 7.316 - return; 7.317 - //Note, this is not a location to check for shutdown because doesn't 7.318 - // say anything about work availability here.. check for shutdown in 7.319 - // places try to get work for the core (in the assigner) 7.320 - } 7.321 - 7.322 - 7.323 - 7.324 -/*Re-use this in the entry-point fn 7.325 - */ 7.326 -inline SlaveVP * 7.327 -VSs__create_slave_helper( TopLevelFnPtr fnPtr, void *initData, 7.328 - VSsSemEnv *semEnv, int32 coreToAssignOnto ) 7.329 - { SlaveVP *newSlv; 7.330 - VSsSemData *semData; 7.331 - 7.332 - //This is running in master, so use internal version 7.333 - newSlv = VMS_PI__create_slaveVP( fnPtr, initData ); 7.334 - 7.335 - //task slaves differ from thread slaves by the settings in the taskStub 7.336 - //so, don't create task stub here, only create semData, which is same 7.337 - // for all kinds of slaves 7.338 - semData = VMS_PI__malloc( sizeof(VSsSemData) ); 7.339 - semData->highestTransEntered = -1; 7.340 - semData->lastTransEntered = NULL; 7.341 - semData->needsTaskAssigned = TRUE; 7.342 - semData->taskStub = NULL; 7.343 - 7.344 - newSlv->semanticData = semData; 7.345 - 7.346 - //=================== Assign new processor to a core ===================== 7.347 - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 7.348 - newSlv->coreAnimatedBy = 0; 7.349 - 7.350 - #else 7.351 - //Assigning slaves to cores is part of SSR code.. 7.352 - if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES ) 7.353 - { //out-of-range, so round-robin assignment 7.354 - newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv; 7.355 - 7.356 - if( semEnv->nextCoreToGetNewSlv >= NUM_CORES - 1 ) 7.357 - semEnv->nextCoreToGetNewSlv = 0; 7.358 - else 7.359 - semEnv->nextCoreToGetNewSlv += 1; 7.360 - } 7.361 - else //core num in-range, so use it 7.362 - { newSlv->coreAnimatedBy = coreToAssignOnto; 7.363 - } 7.364 - #endif 7.365 - //======================================================================== 7.366 - 7.367 - return newSlv; 7.368 - } 7.369 - 7.370 -VSsTaskStub * 7.371 -create_thread_task_stub( void *initData ) 7.372 - { VSsTaskStub *newStub; 7.373 - 7.374 - newStub = VMS_PI__malloc( sizeof(VSsTaskStub) ); 7.375 - newStub->numBlockingProp = 0; 7.376 - newStub->slaveAssignedTo = NULL; //set later 7.377 - newStub->taskType = IS_A_THREAD; 7.378 - newStub->ptrEntries = NULL; 7.379 - newStub->args = initData; 7.380 - newStub->numLiveChildTasks = 0; 7.381 - newStub->numLiveChildThreads = 0; 7.382 - newStub->parentTaskStub = NULL; 7.383 - newStub->isWaitingForChildTasksToEnd = FALSE; 7.384 - newStub->isWaitingForChildThreadsToEnd = FALSE; 7.385 - newStub->taskID = NULL; 7.386 - 7.387 - return newStub; 7.388 - } 7.389 - 7.390 -/*Application invokes this when it explicitly creates a thread via the 7.391 - * "VSs__create_thread()" command. 7.392 - * 7.393 - *The request handlers create new task slaves directly, not via this hdlr. 7.394 - * 7.395 - *Make everything in VSs be a task. An explicitly created VP is just a 7.396 - * suspendable task, and the seedVP is also a suspendable task. 7.397 - *So, here, create a task Stub. 7.398 - * Then, see if there are any extra slaveVPs hanging around, and if not, 7.399 - * call the helper to make a new one. 7.400 - * Then, put the task stub into the slave's semantic Data. 7.401 - *When the slave calls dissipate, have to recycle the task stub. 7.402 - */ 7.403 -inline void 7.404 -handleCreate( VMSReqst *req, SlaveVP *requestingSlv, VSsSemEnv *semEnv ) 7.405 - { VSsSemReq *semReq; 7.406 - SlaveVP *newSlv; 7.407 - VSsSemData *semData, *parentSemData; 7.408 - 7.409 - semReq = VMS_PI__take_sem_reqst_from( req ); 7.410 - 7.411 - semEnv->numLiveThreadSlvs += 1; 7.412 - 7.413 - //Deceptive -- must work when creator is a normal task, or seed, 7.414 - // or another thd.. think have valid sem data and task stub for all 7.415 - //This hdlr is NOT called when creating the seed slave 7.416 - parentSemData = (VSsSemData *)semReq->callingSlv->semanticData; 7.417 - parentSemData->taskStub->numLiveChildThreads += 1; 7.418 - 7.419 - //use an idle "extra" slave, if have one 7.420 - newSlv = readPrivQ( semEnv->freeExtraTaskSlvQ ); 7.421 - if( newSlv != NULL ) //got an idle one, so reset it 7.422 - { semData = (VSsSemData *)newSlv->semanticData; 7.423 - semData->highestTransEntered = -1; 7.424 - semData->lastTransEntered = NULL; 7.425 - VMS_int__reset_slaveVP_to_TopLvlFn( newSlv, semReq->fnPtr, 7.426 - semReq->initData ); 7.427 - } 7.428 - else //no idle ones, create a new 7.429 - { newSlv = VSs__create_slave_helper( semReq->fnPtr, semReq->initData, 7.430 - semEnv, semReq->coreToAssignOnto ); 7.431 - semData = (VSsSemData *)newSlv->semanticData; 7.432 - } 7.433 - 7.434 - //now, create a new task and assign to the thread 7.435 - semData->needsTaskAssigned = FALSE; //thread has a permanent task 7.436 - semData->taskStub = create_thread_task_stub( semReq->initData ); 7.437 - semData->taskStub->parentTaskStub = parentSemData->taskStub; 7.438 - semData->slaveType = ThreadSlv; //this hdlr only creates thread slvs 7.439 - 7.440 - DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d", 7.441 - requestingSlv->slaveID, newSlv->slaveID) 7.442 - 7.443 - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.444 - Dependency newd; 7.445 - newd.from_vp = requestingSlv->slaveID; 7.446 - newd.from_task = requestingSlv->assignCount; 7.447 - newd.to_vp = newSlv->slaveID; 7.448 - newd.to_task = 1; 7.449 - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); 7.450 - #endif 7.451 - 7.452 - //For VSs, caller needs ptr to created thread returned to it 7.453 - requestingSlv->dataRetFromReq = newSlv; 7.454 - resume_slaveVP(requestingSlv , semEnv ); 7.455 - resume_slaveVP( newSlv, semEnv ); 7.456 - } 7.457 - 7.458 7.459 //=========================== Helper ============================== 7.460 void 7.461 @@ -478,6 +182,8 @@ 7.462 { 7.463 //both suspended tasks and suspended explicit slaves resumed with this 7.464 writePrivQ( slave, semEnv->slavesReadyToResumeQ ); 7.465 + if( semEnv->protoSemEnv->hasWork != TRUE ) 7.466 + semEnv->protoSemEnv->hasWork = TRUE; 7.467 7.468 #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 7.469 /* 7.470 @@ -487,19 +193,19 @@ 7.471 */ 7.472 #endif 7.473 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.474 - slave->assignCount++; //Somewhere here! 7.475 - Unit newu; 7.476 - newu.vp = slave->slaveID; 7.477 - newu.task = slave->assignCount; 7.478 - addToListOfArrays(Unit,newu,semEnv->unitList); 7.479 + slave->numTimesAssignedToASlot++; //Somewhere here! 7.480 + Unit newU; 7.481 + newU.vp = slave->slaveID; 7.482 + newU.task = slave->numTimesAssignedToASlot; 7.483 + addToListOfArrays(Unit,newU,semEnv->unitList); 7.484 7.485 - if (slave->assignCount > 1){ 7.486 - Dependency newd; 7.487 - newd.from_vp = slave->slaveID; 7.488 - newd.from_task = slave->assignCount - 1; 7.489 - newd.to_vp = slave->slaveID; 7.490 - newd.to_task = slave->assignCount; 7.491 - addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); 7.492 - } 7.493 + if (slave->numTimesAssignedToASlot > 1) 7.494 + { Dependency newD; 7.495 + newD.from_vp = slave->slaveID; 7.496 + newD.from_task = slave->numTimesAssignedToASlot - 1; 7.497 + newD.to_vp = slave->slaveID; 7.498 + newD.to_task = slave->numTimesAssignedToASlot; 7.499 + addToListOfArrays(Dependency, newD ,semEnv->ctlDependenciesList); 7.500 + } 7.501 #endif 7.502 }
8.1 --- a/VSs_Request_Handlers.c Mon Sep 03 03:26:12 2012 -0700 8.2 +++ b/VSs_Request_Handlers.c Thu Oct 18 02:44:30 2012 -0700 8.3 @@ -7,7 +7,7 @@ 8.4 #include <stdio.h> 8.5 #include <stdlib.h> 8.6 8.7 -#include "VMS_impl/VMS.h" 8.8 +#include "PR_impl/PR.h" 8.9 #include "Queue_impl/PrivateQueue.h" 8.10 #include "Hash_impl/PrivateHash.h" 8.11 #include "VSs.h" 8.12 @@ -32,7 +32,7 @@ 8.13 cloneReq( VSsSemReq *semReq ) 8.14 { VSsSemReq *clonedReq; 8.15 8.16 - clonedReq = VMS_PI__malloc( sizeof(VSsSemReq) ); 8.17 + clonedReq = PR_PI__malloc( sizeof(VSsSemReq) ); 8.18 clonedReq->reqType = semReq->reqType; 8.19 clonedReq->senderSlv = semReq->senderSlv; 8.20 clonedReq->receiverSlv= semReq->receiverSlv; 8.21 @@ -71,7 +71,7 @@ 8.22 create_pointer_entry( ) 8.23 { VSsPointerEntry *newEntry; 8.24 8.25 - newEntry = VMS_PI__malloc( sizeof(VSsPointerEntry) ); 8.26 + newEntry = PR_PI__malloc( sizeof(VSsPointerEntry) ); 8.27 newEntry->hasEnabledNonFinishedWriter = FALSE; 8.28 newEntry->numEnabledNonDoneReaders = 0; 8.29 newEntry->waitersQ = makePrivQ(); 8.30 @@ -85,13 +85,12 @@ 8.31 inline VSsTaskStub * 8.32 create_task_stub( VSsTaskType *taskType, void **args ) 8.33 { void **newArgs; 8.34 - VSsTaskStub* newStub = VMS_int__malloc( sizeof(VSsTaskStub) + taskType->sizeOfArgs ); 8.35 + VSsTaskStub* newStub = PR_int__malloc( sizeof(PRMetaTask) + taskType->sizeOfArgs ); 8.36 newStub->numBlockingProp = taskType->numCtldArgs; 8.37 - newStub->slaveAssignedTo = NULL; 8.38 newStub->taskType = taskType; 8.39 newStub->ptrEntries = 8.40 - VMS_int__malloc( taskType->numCtldArgs * sizeof(VSsPointerEntry *) ); 8.41 - newArgs = (void **)( (uint8 *)newStub + sizeof(VSsTaskStub) ); 8.42 + PR_int__malloc( taskType->numCtldArgs * sizeof(VSsPointerEntry *) ); 8.43 + newArgs = (void **)( (uint8 *)newStub + sizeof(PRMetaTask) ); 8.44 newStub->args = newArgs; 8.45 newStub->numLiveChildTasks = 0; 8.46 newStub->numLiveChildThreads = 0; 8.47 @@ -108,17 +107,189 @@ 8.48 create_task_carrier( VSsTaskStub *taskStub, int32 argNum, int32 rdOrWrite ) 8.49 { VSsTaskStubCarrier *newCarrier; 8.50 8.51 - newCarrier = VMS_PI__malloc( sizeof(VSsTaskStubCarrier) ); 8.52 + newCarrier = PR_PI__malloc( sizeof(VSsTaskStubCarrier) ); 8.53 newCarrier->taskStub = taskStub; 8.54 newCarrier->argNum = argNum; 8.55 newCarrier->isReader = rdOrWrite == READER; 8.56 } 8.57 8.58 + 8.59 + 8.60 +//=========================== ============================== 8.61 + 8.62 +/*Application invokes this via wrapper library, when it explicitly creates a 8.63 + * thread with the "VSs__create_thread()" command. 8.64 + * 8.65 + *Slave creation is a special form, so PR does handling before calling this. 8.66 + * It does creation of the new slave, and hands it to this handler. 8.67 + *This handler is registered with PR during VSs__start(). 8.68 + * 8.69 + *So, here, create a task Stub that contains a marker stating this is a thread. 8.70 + * Then, attach the task stub to the slave's meta Task via a PR command. 8.71 + * 8.72 + *When slave dissipates, PR will call the registered recycler for the task stub. 8.73 + */ 8.74 +inline void 8.75 +handleCreateThd( PRReqst *req, SlaveVP *requestingSlv, SlaveVP *newSlv, VSsSemEnv *semEnv ) 8.76 + { VSsSemReq *semReq; 8.77 + VSsTaskStub *taskStub, *parentTaskStub; 8.78 + 8.79 + semReq = PR_PI__take_sem_reqst_from( req ); 8.80 + 8.81 + parentTaskStub = PR_PI__give_lang_meta_task( requestingSlv ); 8.82 + parentTaskStub->numLiveChildThreads += 1; 8.83 + 8.84 + taskStub = create_thread_task_stub(); //only used for wait info 8.85 + taskStub->parentTaskStub = parentTaskStub; 8.86 + 8.87 + //note, semantic data will be initialized by separate, registered 8.88 + // initializer, at the point it is accessed the first time. 8.89 + 8.90 + //================= Assign the new thread to a core =================== 8.91 + #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 8.92 + newSlv->coreAnimatedBy = 0; 8.93 + 8.94 + #else 8.95 + //Assigning slaves to cores is part of SSR code.. 8.96 + int32 coreToAssignOnto = semReq->coreToAssignOnto; 8.97 + if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES ) 8.98 + { //out-of-range, so round-robin assignment 8.99 + newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv; 8.100 + 8.101 + if( semEnv->nextCoreToGetNewSlv >= NUM_CORES - 1 ) 8.102 + semEnv->nextCoreToGetNewSlv = 0; 8.103 + else 8.104 + semEnv->nextCoreToGetNewSlv += 1; 8.105 + } 8.106 + else //core num in-range, so use it 8.107 + { newSlv->coreAnimatedBy = coreToAssignOnto; 8.108 + } 8.109 + #endif 8.110 + //======================================================================== 8.111 + 8.112 + 8.113 + 8.114 + DEBUG__printf2(dbgRqstHdlr,"Create from: %d, new VP: %d", 8.115 + requestingSlv->slaveID, newSlv->slaveID) 8.116 + 8.117 + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 8.118 + Dependency newD; 8.119 + newD.from_vp = requestingSlv->slaveID; 8.120 + newD.from_task = requestingSlv->numTimesAssignedToASlot; 8.121 + newD.to_vp = newSlv->slaveID; 8.122 + newD.to_task = 1; 8.123 + addToListOfArrays(Dependency,newD,semEnv->commDependenciesList); 8.124 + #endif 8.125 + 8.126 + //For VSs, caller needs ptr to created thread returned to it 8.127 + requestingSlv->dataRetFromReq = newSlv; 8.128 + resume_slaveVP(requestingSlv , semEnv ); 8.129 + resume_slaveVP( newSlv, semEnv ); 8.130 + } 8.131 + 8.132 +/*Initialize semantic data struct.. this initializer doesn't need any input, 8.133 + * but some languages may need something from inside the request that was sent 8.134 + * to create a slave.. in that case, just make initializer do the malloc then 8.135 + * use the PR_PI__give_sem_data inside the create handler, and fill in the 8.136 + * semData values there. 8.137 + */ 8.138 +void * createInitialSemanticData( ) 8.139 + { VSsSemData *semData; 8.140 + 8.141 + semData = PR_PI__malloc( sizeof(VSsSemData) ); 8.142 + 8.143 + semData->highestTransEntered = -1; 8.144 + semData->lastTransEntered = NULL; 8.145 + return semData; 8.146 + } 8.147 + 8.148 +/*SlaveVP dissipate -- this is NOT task-end!, only call this to end explicitly 8.149 + * created threads 8.150 + */ 8.151 +inline void 8.152 +handleDissipate( SlaveVP *requestingSlv, VSsSemEnv *semEnv ) 8.153 + { VSsSemData *semData; 8.154 + VSsTaskStub *parentTaskStub, *ownTaskStub; 8.155 + 8.156 + DEBUG__printf1(dbgRqstHdlr,"Dissipate request from processor %d", 8.157 + requestingSlv->slaveID) 8.158 + 8.159 + ownTaskStub = PR_PI__give_lang_meta_task( requestingSlv, VSs_MAGIC_NUMBER ); 8.160 + parentTaskStub = ownTaskStub->parentTaskStub; 8.161 + parentTaskStub->numLiveChildThreads -= 1; //parent wasn't freed, even if ended 8.162 + 8.163 + //if all children ended, then free this task's stub 8.164 + // else, keep stub around, and last child will free it (below) 8.165 + if( ownTaskStub->numLiveChildTasks == 0 && 8.166 + ownTaskStub->numLiveChildThreads == 0 ) 8.167 + free_task_stub( ownTaskStub ); 8.168 + else 8.169 + ownTaskStub->isEnded = TRUE; //for children to see when they end 8.170 + 8.171 + //Now, check on parents waiting on child threads to end 8.172 + if( parentTaskStub->isWaitingForChildThreadsToEnd && 8.173 + parentTaskStub->numLiveChildThreads == 0 ) 8.174 + { parentTaskStub->isWaitingForChildThreadsToEnd = FALSE; 8.175 + if( parentTaskStub->isWaitingForChildTasksToEnd ) 8.176 + return; //still waiting on tasks (should be impossible) 8.177 + else //parent free to resume 8.178 + resume_slaveVP( PR_PI__give_slave_assigned_to(parentTaskStub), semEnv ); 8.179 + } 8.180 + 8.181 + //check if this is last child of ended parent (note, not possible to 8.182 + // have more than one level of ancestor waiting to be freed) 8.183 + if( parentTaskStub->isEnded && 8.184 + parentTaskStub->numLiveChildTasks == 0 && 8.185 + parentTaskStub->numLiveChildThreads == 0 ) 8.186 + { free_task_stub( parentTaskStub ); //just stub, semData already freed 8.187 + } 8.188 + 8.189 + FreeSlaveStateAndReturn: 8.190 + //Used to free the semData and requesting slave's base state, but 8.191 + // now PR does those things, so nothing more to do.. 8.192 +//PR handles this: PR_PI__free( semData ); 8.193 +//PR handles this: PR_PI__dissipate_slaveVP( requestingSlv ); 8.194 + return; 8.195 + } 8.196 + 8.197 +/*Register this with PR, during VSs start 8.198 + * 8.199 + *At some point, may change PR so that it recycles semData, in which case this 8.200 + * only gets called when a process shuts down.. at that point, PR will call 8.201 + * dissipate on all the slaves it has in the recycle Q. 8.202 + */ 8.203 +void 8.204 +freeVSsSemData( void *_semData ) 8.205 + { // 8.206 + PR_PI__free( _semData ); 8.207 + } 8.208 + 8.209 +void resetVSsSemData( void *_semData ) 8.210 + { VSsSemData *semData = (VSsSemData *)_semData; 8.211 + 8.212 + semData->highestTransEntered = -1; 8.213 + semData->lastTransEntered = NULL; 8.214 + } 8.215 + 8.216 //========================================================================== 8.217 // 8.218 // 8.219 /*Submit Task 8.220 - * 8.221 + * 8.222 + *PR creates a PRMetaTask and passes it in. This handler adds language- 8.223 + * specific stuff to it. The language-specific stuff is linked to the 8.224 + * PRMetaTask, but if the task is suspended for any reason, the lang-specific 8.225 + * part is moved to the semData of the slave that is animating the task. 8.226 + *So, while the PRMetaTask is inside the creating language's semantic 8.227 + * env, waiting to be assigned to a slave for animation, the lang-specific 8.228 + * task info is accessed from the PRMetaTask. But once the task suspends, 8.229 + * that lang-specific task info transfers to the slave's semData. All lang 8.230 + * constructs that want to access it must get it from the semData. 8.231 + *However, taskEnd still accesses the lang-specific task info from the 8.232 + * PRMetaTask, whether it suspended or not.. and the task code can access 8.233 + * data to be used within the application behavior via 8.234 + * PR__give_task_info( animatingSlave ). 8.235 + * 8.236 *Uses a hash table to match the arg-pointers to each other. So, an 8.237 * argument-pointer is one-to-one with a hash-table entry. 8.238 * 8.239 @@ -182,79 +353,45 @@ 8.240 * the chain. (Means no-longer-used pointers accumulate at end of chain, 8.241 * decide garbage collection of no-longer-used pointers later) 8.242 * 8.243 - * 8.244 - * ========================== end of task =========================== 8.245 - * 8.246 - *At the end of a task, 8.247 - *The task's controlled arguments are processed one by one. 8.248 - *Processing an argument means getting the hash of the pointer. Then, 8.249 - * looking up the hash entry (and putting the entry at the start of the 8.250 - * chain, if there was a chain). 8.251 - *With the hash entry: 8.252 - * 8.253 - *If the arg is a reader, then decrement the enabled and non-finished 8.254 - * reader-count in the hash-entry. If the count becomes zero, then take 8.255 - * the next entry from the Q. It should be a writer, or else there's a 8.256 - * bug in this algorithm. 8.257 - *Set the hash-entry to have an enabled non-finished writer. Decrement 8.258 - * the blocking-propendent-count of the writer's task-stub. If the count 8.259 - * has reached zero, then put the task-stub into the readyQ. 8.260 - * 8.261 - *If the arg is a writer, then clear the enabled non-finished writer flag 8.262 - * of the hash-entry. Take the next entry from the Q. 8.263 - *If it is a writer, then turn the flag back on. Decrement the writer's 8.264 - * blocking-propendent-count in its task-stub. If it becomes zero, then 8.265 - * put the task-stub into the readyQ. 8.266 - * 8.267 - *If it is a reader, then increment the hash-entry's count of enabled 8.268 - * non-finished readers. Decrement the blocking propendents count of the 8.269 - * reader's task-stub. If it reaches zero, then put the task-stub into the 8.270 - * readyQ. 8.271 - *Then repeat until encounter a writer -- put that writer back into the Q. 8.272 - * 8.273 - *That should be it -- that should work. 8.274 */ 8.275 -inline void 8.276 +inline 8.277 +void * 8.278 handleSubmitTask( VSsSemReq *semReq, VSsSemEnv *semEnv ) 8.279 { uint32 key[3]; 8.280 HashEntry *rawHashEntry; //has char *, but use with uint32 * 8.281 VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer 8.282 void **args; 8.283 - VSsTaskStub *taskStub; 8.284 + VSsTaskStub *taskStub, *parentTaskStub; 8.285 VSsTaskType *taskType; 8.286 VSsTaskStubCarrier *taskCarrier; 8.287 8.288 HashTable * 8.289 argPtrHashTbl = semEnv->argPtrHashTbl; 8.290 8.291 - //suspending a task always makes the slave into an extra slot slave, 8.292 - // because it ends up in the resumeQ, even when resumes immediately. 8.293 - //Eventually task_end will put the slave into the freeExtraTaskSlvQ 8.294 - replaceWithNewSlotSlvIfNeeded( semReq->callingSlv, semEnv ); 8.295 8.296 /* ========================== creation ========================== 8.297 - * 8.298 - *At creation, make a task-stub. Set the count of blocking propendents 8.299 + *Make a task-stub. Set the count of blocking propendents 8.300 * to the number of controlled arguments (a task can have 8.301 * arguments that are not controlled by the language, like simple integer 8.302 * inputs from the sequential portion. Note that all controlled arguments 8.303 * are pointers, and marked as controlled in the application code). 8.304 */ 8.305 args = semReq->args; 8.306 - taskType = semReq->taskType; 8.307 + taskType = semReq->taskType; //this is VSs task type struct 8.308 taskStub = create_task_stub( taskType, args );//copies arg ptrs 8.309 + 8.310 taskStub->numBlockingProp = taskType->numCtldArgs; 8.311 - taskStub->taskID = semReq->taskID; //may be NULL 8.312 - 8.313 - VSsSemData* 8.314 - parentSemData = (VSsSemData*) semReq->callingSlv->semanticData; 8.315 - taskStub->parentTaskStub = (void*) parentSemData->taskStub; 8.316 - parentSemData->taskStub->numLiveChildTasks += 1; 8.317 + //PR does this (metaTask contains taskID): taskStub->taskID = semReq->taskID; 8.318 + 8.319 + parentTaskStub = (VSsTaskStub *)PR_PI__give_lang_meta_task(semReq->callingSlv, VSs_MAGIC_NUMBER); 8.320 + taskStub->parentTaskStub = parentTaskStub; 8.321 + parentTaskStub->numLiveChildTasks += 1; 8.322 8.323 //DEBUG__printf3(dbgRqstHdlr,"Submit req from slaveID: %d, from task: %d, for task: %d", semReq->callingSlv->slaveID, parentSemData->taskStub->taskID[1], taskStub->taskID[1]) 8.324 DEBUG__printf2(dbgRqstHdlr,"Submit req from slaveID: %d, for task: %d", semReq->callingSlv->slaveID, taskStub->taskID[1]) 8.325 8.326 - /*The controlled arguments are then processed one by one. 8.327 + /*=============== Process args ================= 8.328 + *The controlled arguments are processed one by one. 8.329 *Processing an argument means getting the hash of the pointer. Then, 8.330 * looking up the hash entry. (If none, create one). 8.331 */ 8.332 @@ -295,6 +432,8 @@ 8.333 taskStub->numBlockingProp -= 1; 8.334 if( taskStub->numBlockingProp == 0 ) 8.335 { writePrivQ( taskStub, semEnv->taskReadyQ ); 8.336 + if( semEnv->protoSemEnv->hasWork != TRUE ) 8.337 + semEnv->protoSemEnv->hasWork = TRUE; 8.338 } 8.339 ptrEntry->numEnabledNonDoneReaders += 1; 8.340 } 8.341 @@ -318,6 +457,8 @@ 8.342 taskStub->numBlockingProp -= 1; 8.343 if( taskStub->numBlockingProp == 0 ) 8.344 { writePrivQ( taskStub, semEnv->taskReadyQ ); 8.345 + if( semEnv->protoSemEnv->hasWork != TRUE ) 8.346 + semEnv->protoSemEnv->hasWork = TRUE; 8.347 } 8.348 ptrEntry->hasEnabledNonFinishedWriter = TRUE; 8.349 } 8.350 @@ -329,7 +470,7 @@ 8.351 } 8.352 } //for argNum 8.353 8.354 - 8.355 + //resume the parent, creator 8.356 resume_slaveVP( semReq->callingSlv, semEnv ); 8.357 8.358 return; 8.359 @@ -372,36 +513,38 @@ 8.360 * and no readers and no writers.. 8.361 */ 8.362 inline void 8.363 -handleEndTask( VSsSemReq *semReq, VSsSemEnv *semEnv ) 8.364 +handleEndTask( void *langMetaTask, VSsSemReq *semReq, VSsSemEnv *semEnv ) 8.365 { VSsPointerEntry *ptrEntry; //contents of hash table entry for an arg pointer 8.366 void **args; 8.367 VSsSemData *endingSlvSemData; 8.368 - VSsTaskStub *endingTaskStub, *waitingTaskStub, *parent; 8.369 + VSsTaskStub *endingTaskStub, *waitingTaskStub, *parentStub; 8.370 VSsTaskType *endingTaskType; 8.371 VSsTaskStubCarrier *waitingTaskCarrier; 8.372 VSsPointerEntry **ptrEntries; 8.373 8.374 8.375 - endingSlvSemData = (VSsSemData *)semReq->callingSlv->semanticData; 8.376 - endingTaskStub = endingSlvSemData->taskStub; 8.377 +// endingTaskStub = (VSsTaskStub *)PR_PI__give_lang_spec_task_info( semReq->callingSlv ); 8.378 + 8.379 + endingTaskStub = (VSsTaskStub *)langMetaTask; 8.380 args = endingTaskStub->args; 8.381 endingTaskType = endingTaskStub->taskType; 8.382 ptrEntries = endingTaskStub->ptrEntries; //saved in stub when create 8.383 8.384 DEBUG__printf2(dbgRqstHdlr,"EndTask req from slaveID: %d, task: %d",semReq->callingSlv->slaveID, endingTaskStub->taskID[1]) 8.385 8.386 - //Check if parent was waiting on this task 8.387 - parent = (VSsTaskStub *) endingTaskStub->parentTaskStub; 8.388 - parent->numLiveChildTasks -= 1; 8.389 - if( parent->isWaitingForChildTasksToEnd && parent->numLiveChildTasks == 0) 8.390 + //"wait" functionality: Check if parent was waiting on this task 8.391 + parentStub = endingTaskStub->parentTaskStub; 8.392 + parentStub->numLiveChildTasks -= 1; 8.393 + if( parentStub->isWaitingForChildTasksToEnd && 8.394 + parentStub->numLiveChildTasks == 0) 8.395 { 8.396 - parent->isWaitingForChildTasksToEnd = FALSE; 8.397 - resume_slaveVP( parent->slaveAssignedTo, semEnv ); 8.398 + parentStub->isWaitingForChildTasksToEnd = FALSE; 8.399 + resume_slaveVP( PR_PI__give_slave_assigned_to(parentStub), semEnv ); 8.400 } 8.401 8.402 //Check if parent ended, and this was last descendent, then free it 8.403 - if( parent->isEnded && parent->numLiveChildTasks == 0 ) 8.404 - { VMS_PI__free( parent ); 8.405 + if( parentStub->isEnded && parentStub->numLiveChildTasks == 0 ) 8.406 + { free_task_stub( parentStub ); 8.407 } 8.408 8.409 8.410 @@ -411,32 +554,16 @@ 8.411 */ 8.412 int32 argNum; 8.413 for( argNum = 0; argNum < endingTaskType->numCtldArgs; argNum++ ) 8.414 - { 8.415 - /* commented out 'cause remembering entry ptr when create stub 8.416 - key[0] = 2; //says are 2 32b values in key 8.417 - *( (uint64*)&key[1] ) = args[argNum]; //write 64b ptr into two 32b 8.418 - 8.419 - /*If the hash entry was chained, put it at the 8.420 - * start of the chain. (Means no-longer-used pointers accumulate 8.421 - * at end of chain, decide garbage collection later) 8.422 - */ 8.423 - /*NOTE: don't do hash lookups here, instead, have a pointer to the 8.424 - * hash entry inside task-stub, put there during task creation. 8.425 - rawHashEntry = getEntryFromTable32( key, ptrHashTbl ); 8.426 - ptrEntry = (VSsPointerEntry *)rawHashEntry->content; 8.427 - if( ptrEntry == NULL ) 8.428 - VMS_App__throw_exception("hash entry NULL", NULL, NULL); 8.429 - */ 8.430 - 8.431 + { 8.432 ptrEntry = ptrEntries[argNum]; 8.433 - /*check if the ending task was reader of this arg*/ 8.434 + //check if the ending task was reader of this arg 8.435 if( endingTaskType->argTypes[argNum] == READER ) 8.436 - { /*then decrement the enabled and non-finished reader-count in 8.437 - * the hash-entry. */ 8.438 + { //then decrement the enabled and non-finished reader-count in 8.439 + // the hash-entry. 8.440 ptrEntry->numEnabledNonDoneReaders -= 1; 8.441 8.442 - /*If the count becomes zero, then take the next entry from the Q. 8.443 - *It should be a writer, or else there's a bug in this algorithm.*/ 8.444 + //If the count becomes zero, then take the next entry from the Q. 8.445 + //It should be a writer, or else there's a bug in this algorithm. 8.446 if( ptrEntry->numEnabledNonDoneReaders == 0 ) 8.447 { waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ ); 8.448 if( waitingTaskCarrier == NULL ) 8.449 @@ -444,27 +571,29 @@ 8.450 continue; //next iter of loop 8.451 } 8.452 if( waitingTaskCarrier->isReader ) 8.453 - VMS_App__throw_exception("READER waiting", NULL, NULL); 8.454 + PR_App__throw_exception("READER waiting", NULL, NULL); 8.455 8.456 waitingTaskStub = waitingTaskCarrier->taskStub; 8.457 8.458 - /*Set the hash-entry to have an enabled non-finished writer.*/ 8.459 + //Set the hash-entry to have an enabled non-finished writer. 8.460 ptrEntry->hasEnabledNonFinishedWriter = TRUE; 8.461 8.462 - /* Decrement the blocking-propendent-count of the writer's 8.463 - * task-stub. If the count has reached zero, then put the 8.464 - * task-stub into the readyQ.*/ 8.465 + // Decrement the blocking-propendent-count of the writer's 8.466 + // task-stub. If the count has reached zero, then put the 8.467 + // task-stub into the readyQ. 8.468 waitingTaskStub->numBlockingProp -= 1; 8.469 if( waitingTaskStub->numBlockingProp == 0 ) 8.470 { writePrivQ( waitingTaskStub, semEnv->taskReadyQ ); 8.471 + if( semEnv->protoSemEnv->hasWork != TRUE ) 8.472 + semEnv->protoSemEnv->hasWork = TRUE; 8.473 } 8.474 } 8.475 } 8.476 - else /*the ending task is a writer of this arg*/ 8.477 - { /*clear the enabled non-finished writer flag of the hash-entry.*/ 8.478 + else //the ending task is a writer of this arg 8.479 + { //clear the enabled non-finished writer flag of the hash-entry. 8.480 ptrEntry->hasEnabledNonFinishedWriter = FALSE; 8.481 8.482 - /*Take the next waiter from the hash-entry's Q.*/ 8.483 + //Take the next waiter from the hash-entry's Q. 8.484 waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ ); 8.485 if( waitingTaskCarrier == NULL ) 8.486 { //TODO: looks safe to delete ptr entry at this point 8.487 @@ -472,36 +601,40 @@ 8.488 } 8.489 waitingTaskStub = waitingTaskCarrier->taskStub; 8.490 8.491 - /*If task is a writer of this hash-entry's pointer*/ 8.492 + //If task is a writer of this hash-entry's pointer 8.493 if( !waitingTaskCarrier->isReader ) 8.494 - { /* then turn the flag back on.*/ 8.495 + { // then turn the flag back on. 8.496 ptrEntry->hasEnabledNonFinishedWriter = TRUE; 8.497 - /*Decrement the writer's blocking-propendent-count in task-stub 8.498 - * If it becomes zero, then put the task-stub into the readyQ.*/ 8.499 + //Decrement the writer's blocking-propendent-count in task-stub 8.500 + // If it becomes zero, then put the task-stub into the readyQ. 8.501 waitingTaskStub->numBlockingProp -= 1; 8.502 if( waitingTaskStub->numBlockingProp == 0 ) 8.503 { writePrivQ( waitingTaskStub, semEnv->taskReadyQ ); 8.504 + if( semEnv->protoSemEnv->hasWork != TRUE ) 8.505 + semEnv->protoSemEnv->hasWork = TRUE; 8.506 } 8.507 } 8.508 else 8.509 - { /*Waiting task is a reader, so do a loop, of all waiting readers 8.510 - * until encounter a writer or waitersQ is empty*/ 8.511 - while( TRUE ) /*The checks guarantee have a waiting reader*/ 8.512 - { /*Increment the hash-entry's count of enabled non-finished 8.513 - * readers.*/ 8.514 + { //Waiting task is a reader, so do a loop, of all waiting readers 8.515 + // until encounter a writer or waitersQ is empty 8.516 + while( TRUE ) //The checks guarantee have a waiting reader 8.517 + { //Increment the hash-entry's count of enabled non-finished 8.518 + // readers. 8.519 ptrEntry->numEnabledNonDoneReaders += 1; 8.520 8.521 - /*Decrement the blocking propendents count of the reader's 8.522 - * task-stub. If it reaches zero, then put the task-stub 8.523 - * into the readyQ.*/ 8.524 + //Decrement the blocking propendents count of the reader's 8.525 + // task-stub. If it reaches zero, then put the task-stub 8.526 + // into the readyQ. 8.527 waitingTaskStub->numBlockingProp -= 1; 8.528 if( waitingTaskStub->numBlockingProp == 0 ) 8.529 { writePrivQ( waitingTaskStub, semEnv->taskReadyQ ); 8.530 + if( semEnv->protoSemEnv->hasWork != TRUE ) 8.531 + semEnv->protoSemEnv->hasWork = TRUE; 8.532 } 8.533 - /*Get next waiting task*/ 8.534 + //Get next waiting task 8.535 waitingTaskCarrier = peekPrivQ( ptrEntry->waitersQ ); 8.536 - if( waitingTaskCarrier == NULL ) break; 8.537 - if( !waitingTaskCarrier->isReader ) break; 8.538 + if( waitingTaskCarrier == NULL ) break; //no more waiting readers 8.539 + if( !waitingTaskCarrier->isReader ) break; //no more waiting readers 8.540 waitingTaskCarrier = readPrivQ( ptrEntry->waitersQ ); 8.541 waitingTaskStub = waitingTaskCarrier->taskStub; 8.542 }//while waiter is a reader 8.543 @@ -510,32 +643,23 @@ 8.544 }//for argnum in ending task 8.545 8.546 8.547 - //done ending the task, now free the stub + args copy 8.548 - // if still has live children, then keep stub around 8.549 + //done ending the task, if still has live children, then keep stub around 8.550 + // else, free the stub and args copy 8.551 if( endingTaskStub->numLiveChildTasks == 0 && 8.552 endingTaskStub->numLiveChildThreads == 0 ) 8.553 { free_task_stub( endingTaskStub ); 8.554 } 8.555 8.556 - 8.557 - endingSlvSemData->needsTaskAssigned = TRUE; 8.558 - 8.559 - //Check if the slave is an extra task slave, and put into free Q 8.560 - if( endingSlvSemData->slaveType == ExtraTaskSlv ) 8.561 - { writePrivQ( semReq->callingSlv, semEnv->freeExtraTaskSlvQ ); 8.562 - } 8.563 - 8.564 - //otherwise, it's a slot slave, so it will get used from matrix 8.565 - // so, do nothing with it, just return 8.566 return; 8.567 } 8.568 8.569 + 8.570 inline void 8.571 free_task_stub( VSsTaskStub *stubToFree ) 8.572 { if(stubToFree->ptrEntries != NULL ) //a thread stub has NULL entry 8.573 - { VMS_PI__free( stubToFree->ptrEntries ); 8.574 + { PR_PI__free( stubToFree->ptrEntries ); 8.575 } 8.576 - VMS_PI__free( stubToFree ); 8.577 + PR_PI__free( stubToFree ); 8.578 } 8.579 8.580 //========================== Task Comm handlers =========================== 8.581 @@ -567,14 +691,10 @@ 8.582 8.583 DEBUG__printf2(dbgRqstHdlr,"SendType req from sender slaveID: %d, recTask: %d", senderSlv->slaveID, receiverID[1]) 8.584 8.585 - //suspending a task always makes the slave into an extra slot slave, 8.586 - // because it ends up in the resumeQ, even when resumes immediately. 8.587 - //Eventually task_end will put the slave into the freeExtraTaskSlvQ 8.588 - replaceWithNewSlotSlvIfNeeded( senderSlv, semEnv ); 8.589 8.590 receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself 8.591 keySz = receiverIDNumInt * sizeof(int32) + 2 * sizeof(int32); 8.592 - key = VMS_PI__malloc( keySz ); 8.593 + key = PR_PI__malloc( keySz ); 8.594 key[0] = receiverIDNumInt + 1; //loc 0 is num int32 in key 8.595 memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); 8.596 key[ 1 + receiverIDNumInt ] = semReq->msgType; 8.597 @@ -604,13 +724,13 @@ 8.598 else 8.599 { 8.600 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 8.601 - Dependency newd; 8.602 - newd.from_vp = senderID->slaveID; 8.603 - newd.from_task = senderID->assignCount; 8.604 - newd.to_vp = receiverID->slaveID; 8.605 - newd.to_task = receiverID->assignCount +1; 8.606 - //(newd,semEnv->commDependenciesList); 8.607 - addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); 8.608 + Dependency newD; 8.609 + newD.from_vp = senderID->slaveID; 8.610 + newD.from_task = senderID->numTimesAssignedToASlot; 8.611 + newD.to_vp = receiverID->slaveID; 8.612 + newD.to_task = receiverID->numTimesAssignedToASlot +1; 8.613 + //(newD,semEnv->commDependenciesList); 8.614 + addToListOfArrays(Dependency,newD,semEnv->dynDependenciesList); 8.615 int32 groupId = semReq->msgType; 8.616 if(semEnv->ntonGroupsInfo->numInArray <= groupId){ 8.617 makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId); 8.618 @@ -620,10 +740,10 @@ 8.619 } 8.620 Unit u; 8.621 u.vp = senderID->slaveID; 8.622 - u.task = senderID->assignCount; 8.623 + u.task = senderID->numTimesAssignedToASlot; 8.624 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders); 8.625 u.vp = receiverID->slaveID; 8.626 - u.task = receiverID->assignCount +1; 8.627 + u.task = receiverID->numTimesAssignedToASlot +1; 8.628 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers); 8.629 #endif 8.630 8.631 @@ -633,7 +753,7 @@ 8.632 //waiting request is a receive_type_to, so it pairs to this send 8.633 //First, remove the waiting receive request from the entry 8.634 entry->content = waitingReq->nextReqInHashEntry; 8.635 - VMS_PI__free( waitingReq ); //Don't use contents -- so free it 8.636 + PR_PI__free( waitingReq ); //Don't use contents -- so free it 8.637 8.638 if( entry->content == NULL ) 8.639 { //TODO: mod hash table to double-link, so can delete entry from 8.640 @@ -654,7 +774,12 @@ 8.641 } 8.642 8.643 8.644 -/*Looks like can make single handler for both sends.. 8.645 +/*If Send or Receive are called within a task, it causes the task to suspend, 8.646 + * which converts the slave animating it to a free slave and suspends that slave. 8.647 + *Which means that send and receive operate upon slaves, no matter whether they 8.648 + * were called from within a task or a slave. 8.649 + * 8.650 + *Looks like can make single handler for both kinds of send.. 8.651 */ 8.652 //TODO: combine both send handlers into single handler 8.653 inline void 8.654 @@ -673,15 +798,11 @@ 8.655 senderID = semReq->senderID; 8.656 senderSlv = semReq->senderSlv; 8.657 8.658 - //suspending a task always makes the slave into an extra slot slave, 8.659 - // because it ends up in the resumeQ, even when resumes immediately. 8.660 - //Eventually task_end will put the slave into the freeExtraTaskSlvQ 8.661 - replaceWithNewSlotSlvIfNeeded( senderSlv, semEnv ); 8.662 8.663 receiverIDNumInt = receiverID[0] + 1; //include the count in the key 8.664 senderIDNumInt = senderID[0] + 1; 8.665 keySz = (receiverIDNumInt + senderIDNumInt) * sizeof(int32) + sizeof(int32); 8.666 - key = VMS_PI__malloc( keySz ); 8.667 + key = PR_PI__malloc( keySz ); 8.668 key[0] = receiverIDNumInt + senderIDNumInt; 8.669 memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); 8.670 memcpy( &key[1 + receiverIDNumInt], senderID, senderIDNumInt * sizeof(int32) ); 8.671 @@ -700,13 +821,13 @@ 8.672 else 8.673 { //waiting request is a receive, so it completes pair with this send 8.674 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 8.675 - Dependency newd; 8.676 - newd.from_vp = sendPr->slaveID; 8.677 - newd.from_task = sendPr->assignCount; 8.678 - newd.to_vp = receivePr->slaveID; 8.679 - newd.to_task = receivePr->assignCount +1; 8.680 - //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 8.681 - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); 8.682 + Dependency newD; 8.683 + newD.from_vp = sendPr->slaveID; 8.684 + newD.from_task = sendPr->numTimesAssignedToASlot; 8.685 + newD.to_vp = receivePr->slaveID; 8.686 + newD.to_task = receivePr->numTimesAssignedToASlot +1; 8.687 + //addToListOfArraysDependency(newD,semEnv->commDependenciesList); 8.688 + addToListOfArrays(Dependency,newD,semEnv->commDependenciesList); 8.689 #endif 8.690 8.691 //set receiver slave, from the waiting request 8.692 @@ -714,7 +835,7 @@ 8.693 8.694 //First, remove the waiting receive request from the entry 8.695 entry->content = waitingReq->nextReqInHashEntry; 8.696 - VMS_PI__free( waitingReq ); //Don't use contents -- so free it 8.697 + PR_PI__free( waitingReq ); //Don't use contents -- so free it 8.698 8.699 //can only be one waiting req for "from-to" semantics 8.700 if( entry->content != NULL ) 8.701 @@ -755,15 +876,11 @@ 8.702 receiverID = semReq->receiverID; //For "send", know both send & recv procrs 8.703 receiverSlv = semReq->receiverSlv; 8.704 8.705 - //suspending a task always makes the slave into an extra slot slave, 8.706 - // because it ends up in the resumeQ, even when resumes immediately. 8.707 - //Eventually task_end will put the slave into the freeExtraTaskSlvQ 8.708 - replaceWithNewSlotSlvIfNeeded( receiverSlv, semEnv ); 8.709 8.710 //key is the receiverID plus the type -- have to copy them into key 8.711 receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself 8.712 keySz = receiverIDNumInt * sizeof(int32) + 2 * sizeof(int32); 8.713 - key = VMS_PI__malloc( keySz ); 8.714 + key = PR_PI__malloc( keySz ); 8.715 key[0] = receiverIDNumInt + 1; //loc 0 is num int32s in key 8.716 memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); 8.717 key[ 1 + receiverIDNumInt ] = semReq->msgType; 8.718 @@ -793,16 +910,16 @@ 8.719 receiverSlv->dataRetFromReq = waitingReq->msg; 8.720 8.721 //bring both processors back from suspend 8.722 - VMS_PI__free( waitingReq ); 8.723 + PR_PI__free( waitingReq ); 8.724 8.725 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 8.726 - Dependency newd; 8.727 - newd.from_vp = sendPr->slaveID; 8.728 - newd.from_task = sendPr->assignCount; 8.729 - newd.to_vp = receivePr->slaveID; 8.730 - newd.to_task = receivePr->assignCount +1; 8.731 - //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 8.732 - addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); 8.733 + Dependency newD; 8.734 + newD.from_vp = sendPr->slaveID; 8.735 + newD.from_task = sendPr->numTimesAssignedToASlot; 8.736 + newD.to_vp = receivePr->slaveID; 8.737 + newD.to_task = receivePr->numTimesAssignedToASlot +1; 8.738 + //addToListOfArraysDependency(newD,semEnv->commDependenciesList); 8.739 + addToListOfArrays(Dependency,newD,semEnv->dynDependenciesList); 8.740 int32 groupId = semReq->msgType; 8.741 if(semEnv->ntonGroupsInfo->numInArray <= groupId){ 8.742 makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId); 8.743 @@ -812,10 +929,10 @@ 8.744 } 8.745 Unit u; 8.746 u.vp = sendPr->slaveID; 8.747 - u.task = sendPr->assignCount; 8.748 + u.task = sendPr->numTimesAssignedToASlot; 8.749 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders); 8.750 u.vp = receivePr->slaveID; 8.751 - u.task = receivePr->assignCount +1; 8.752 + u.task = receivePr->numTimesAssignedToASlot +1; 8.753 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers); 8.754 #endif 8.755 8.756 @@ -845,15 +962,10 @@ 8.757 senderID = semReq->senderID; 8.758 receiverSlv = semReq->receiverSlv; 8.759 8.760 - //suspending a task always makes the slave into an extra slot slave, 8.761 - // because it ends up in the resumeQ, even when resumes immediately. 8.762 - //Eventually task_end will put the slave into the freeExtraTaskSlvQ 8.763 - replaceWithNewSlotSlvIfNeeded( receiverSlv, semEnv ); 8.764 - 8.765 receiverIDNumInt = receiverID[0] + 1; //pos 0 doesn't include itself 8.766 senderIDNumInt = senderID[0] + 1; 8.767 keySz = (receiverIDNumInt + senderIDNumInt) * sizeof(int32) + sizeof(int32); 8.768 - key = VMS_PI__malloc( keySz ); 8.769 + key = PR_PI__malloc( keySz ); 8.770 key[0] = receiverIDNumInt + senderIDNumInt; //loc 0 is num int32s in key 8.771 memcpy( &key[1], receiverID, receiverIDNumInt * sizeof(int32) ); 8.772 memcpy( &key[1 + receiverIDNumInt], senderID, senderIDNumInt * sizeof(int32)); 8.773 @@ -869,13 +981,13 @@ 8.774 if( waitingReq->reqType == send_from_to ) 8.775 { //waiting request is a send, so pair it with this receive 8.776 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 8.777 - Dependency newd; 8.778 - newd.from_vp = sendPr->slaveID; 8.779 - newd.from_task = sendPr->assignCount; 8.780 - newd.to_vp = receivePr->slaveID; 8.781 - newd.to_task = receivePr->assignCount +1; 8.782 - //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 8.783 - addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); 8.784 + Dependency newD; 8.785 + newD.from_vp = sendPr->slaveID; 8.786 + newD.from_task = sendPr->numTimesAssignedToASlot; 8.787 + newD.to_vp = receivePr->slaveID; 8.788 + newD.to_task = receivePr->numTimesAssignedToASlot +1; 8.789 + //addToListOfArraysDependency(newD,semEnv->commDependenciesList); 8.790 + addToListOfArrays(Dependency,newD,semEnv->commDependenciesList); 8.791 #endif 8.792 8.793 //have receiver slave, now set sender slave 8.794 @@ -891,7 +1003,7 @@ 8.795 receiverSlv->dataRetFromReq = waitingReq->msg; 8.796 8.797 //bring both processors back from suspend 8.798 - VMS_PI__free( waitingReq ); 8.799 + PR_PI__free( waitingReq ); 8.800 8.801 resume_slaveVP( senderSlv, semEnv ); 8.802 resume_slaveVP( receiverSlv, semEnv ); 8.803 @@ -901,66 +1013,26 @@ 8.804 printf("\nLang Impl Error: Should never be two waiting receives!\n"); 8.805 } 8.806 8.807 -//========================================================================== 8.808 -inline void 8.809 -replaceWithNewSlotSlvIfNeeded( SlaveVP *requestingSlv, VSsSemEnv *semEnv ) 8.810 - { SlaveVP *newSlotSlv; 8.811 - VSsSemData *semData, *reqSemData; 8.812 8.813 - reqSemData = (VSsSemData *)requestingSlv->semanticData; 8.814 - if( reqSemData->slaveType != SlotTaskSlv ) 8.815 - return; //already replaced, so just return 8.816 - 8.817 - //get a new slave to be the slot slave 8.818 - newSlotSlv = readPrivQ( semEnv->freeExtraTaskSlvQ ); 8.819 - if( newSlotSlv == NULL ) 8.820 - { newSlotSlv = VSs__create_slave_helper( &idle_fn, NULL, semEnv, 0); 8.821 - //just made a new extra task slave, so count it 8.822 - semEnv->numLiveExtraTaskSlvs += 1; 8.823 - } 8.824 - 8.825 - //set slave values to make it the slot slave 8.826 - semData = newSlotSlv->semanticData; 8.827 - semData->taskStub = NULL; 8.828 - semData->slaveType = SlotTaskSlv; 8.829 - semData->needsTaskAssigned = TRUE; 8.830 - 8.831 - //a slot slave is pinned to a particular slot on a particular core 8.832 - newSlotSlv->animSlotAssignedTo = requestingSlv->animSlotAssignedTo; 8.833 - newSlotSlv->coreAnimatedBy = requestingSlv->coreAnimatedBy; 8.834 - 8.835 - //put it into the slot slave matrix 8.836 - int32 slotNum = requestingSlv->animSlotAssignedTo->slotIdx; 8.837 - int32 coreNum = requestingSlv->coreAnimatedBy; 8.838 - semEnv->slotTaskSlvs[coreNum][slotNum] = newSlotSlv; 8.839 - 8.840 - //Fix up requester, to be an extra slave now (but not a free one) 8.841 - // because it's not free, doesn't go into freeExtraTaskSlvQ 8.842 - semData = requestingSlv->semanticData; 8.843 - semData->slaveType = ExtraTaskSlv; 8.844 - } 8.845 - 8.846 +/*Waits for all tasks that are direct children to end, then resumes calling 8.847 + * task or thread 8.848 + */ 8.849 inline void 8.850 handleTaskwait( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv) 8.851 - { VSsTaskStub* requestingTaskStub; 8.852 - VSsSemData* semData; 8.853 - DEBUG__printf1(dbgRqstHdlr,"Taskwait request from processor %d", 8.854 + { VSsTaskStub* taskStub; 8.855 + 8.856 + DEBUG__printf1(dbgRqstHdlr,"Taskwait request from processor %d", 8.857 requestingSlv->slaveID) 8.858 8.859 - semData = (VSsSemData *)semReq->callingSlv->semanticData; 8.860 - requestingTaskStub = semData->taskStub; 8.861 + taskStub = (VSsTaskStub *)PR_PI__give_lang_meta_task( requestingSlv, VSs_MAGIC_NUMBER); 8.862 8.863 - if( semData->taskStub->numLiveChildTasks == 0 ) 8.864 + if( taskStub->numLiveChildTasks == 0 ) 8.865 { //nobody to wait for, resume 8.866 resume_slaveVP( requestingSlv, semEnv ); 8.867 } 8.868 - else //have to wait, replace requester with new slot slv & mark waiting 8.869 - { 8.870 - if(semData->slaveType == SlotTaskSlv){ 8.871 - replaceWithNewSlotSlvIfNeeded( requestingSlv, semEnv ); 8.872 - } 8.873 - 8.874 - requestingTaskStub->isWaitingForChildTasksToEnd = TRUE; 8.875 + else //have to wait, mark waiting 8.876 + { 8.877 + taskStub->isWaitingForChildTasksToEnd = TRUE; 8.878 } 8.879 } 8.880 8.881 @@ -974,7 +1046,7 @@ 8.882 8.883 DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingSlv->slaveID) 8.884 8.885 - ptr = VMS_PI__malloc( semReq->sizeToMalloc ); 8.886 + ptr = PR_PI__malloc( semReq->sizeToMalloc ); 8.887 requestingSlv->dataRetFromReq = ptr; 8.888 resume_slaveVP( requestingSlv, semEnv ); 8.889 } 8.890 @@ -985,7 +1057,7 @@ 8.891 handleFree( VSsSemReq *semReq, SlaveVP *requestingSlv, VSsSemEnv *semEnv ) 8.892 { 8.893 DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingSlv->slaveID) 8.894 - VMS_PI__free( semReq->ptrToFree ); 8.895 + PR_PI__free( semReq->ptrToFree ); 8.896 resume_slaveVP( requestingSlv, semEnv ); 8.897 } 8.898 8.899 @@ -1034,8 +1106,8 @@ 8.900 8.901 DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingSlv->slaveID) 8.902 if( *(semReq->singletonPtrAddr) == NULL ) 8.903 - { singleton = VMS_PI__malloc( sizeof(VSsSingleton) ); 8.904 - singleton->waitQ = makeVMSQ(); 8.905 + { singleton = PR_PI__malloc( sizeof(VSsSingleton) ); 8.906 + singleton->waitQ = makePRQ(); 8.907 singleton->endInstrAddr = 0x0; 8.908 singleton->hasBeenStarted = FALSE; 8.909 singleton->hasFinished = FALSE; 8.910 @@ -1133,13 +1205,13 @@ 8.911 //check ordering of entering transactions is correct 8.912 semData = requestingSlv->semanticData; 8.913 if( semData->highestTransEntered > semReq->transID ) 8.914 - { //throw VMS exception, which shuts down VMS. 8.915 - VMS_PI__throw_exception( "transID smaller than prev", requestingSlv, NULL); 8.916 + { //throw PR exception, which shuts down PR. 8.917 + PR_PI__throw_exception( "transID smaller than prev", requestingSlv, NULL); 8.918 } 8.919 //add this trans ID to the list of transactions entered -- check when 8.920 // end a transaction 8.921 semData->highestTransEntered = semReq->transID; 8.922 - nextTransElem = VMS_PI__malloc( sizeof(TransListElem) ); 8.923 + nextTransElem = PR_PI__malloc( sizeof(TransListElem) ); 8.924 nextTransElem->transID = semReq->transID; 8.925 nextTransElem->nextTrans = semData->lastTransEntered; 8.926 semData->lastTransEntered = nextTransElem; 8.927 @@ -1189,7 +1261,7 @@ 8.928 //make sure transaction ended in same VP as started it. 8.929 if( transStruc->VPCurrentlyExecuting != requestingSlv ) 8.930 { 8.931 - VMS_PI__throw_exception( "trans ended in diff VP", requestingSlv, NULL ); 8.932 + PR_PI__throw_exception( "trans ended in diff VP", requestingSlv, NULL ); 8.933 } 8.934 8.935 //make sure nesting is correct -- last ID entered should == this ID 8.936 @@ -1197,7 +1269,7 @@ 8.937 lastTrans = semData->lastTransEntered; 8.938 if( lastTrans->transID != semReq->transID ) 8.939 { 8.940 - VMS_PI__throw_exception( "trans incorrectly nested", requestingSlv, NULL ); 8.941 + PR_PI__throw_exception( "trans incorrectly nested", requestingSlv, NULL ); 8.942 } 8.943 8.944 semData->lastTransEntered = semData->lastTransEntered->nextTrans;
9.1 --- a/VSs_Request_Handlers.h Mon Sep 03 03:26:12 2012 -0700 9.2 +++ b/VSs_Request_Handlers.h Thu Oct 18 02:44:30 2012 -0700 9.3 @@ -53,9 +53,7 @@ 9.4 handleEndDataSingleton( VSsSemReq *semReq, SlaveVP *requestingSlv, 9.5 VSsSemEnv *semEnv ); 9.6 inline void 9.7 -free_task_stub( VSsTaskStub *stubToFree ); 9.8 -inline void 9.9 -replaceWithNewSlotSlvIfNeeded( SlaveVP *requestingSlv, VSsSemEnv *semEnv ); 9.10 +free_task_stub( PRMetaTask *stubToFree ); 9.11 9.12 9.13 #endif /* _VSs_REQ_H */
10.1 --- a/VSs_singleton_asm.s Mon Sep 03 03:26:12 2012 -0700 10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 10.3 @@ -1,21 +0,0 @@ 10.4 - 10.5 -//Assembly code takes the return addr off the stack and saves 10.6 -// into the singleton. The first field in the singleton is the 10.7 -// "endInstrAddr" field, and the return addr is at 0x4(%ebp) 10.8 -.globl asm_save_ret_to_singleton 10.9 -asm_save_ret_to_singleton: 10.10 - movq 0x8(%rbp), %rax #get ret address, ebp is the same as in the calling function 10.11 - movq %rax, (%rdi) #write ret addr to endInstrAddr field 10.12 - ret 10.13 - 10.14 - 10.15 -//Assembly code changes the return addr on the stack to the one 10.16 -// saved into the singleton by the end-singleton-fn 10.17 -//The stack's return addr is at 0x4(%%ebp) 10.18 -.globl asm_write_ret_from_singleton 10.19 -asm_write_ret_from_singleton: 10.20 - movq (%rdi), %rax #get endInstrAddr field 10.21 - movq %rax, 0x8(%rbp) #write return addr to the stack of the caller 10.22 - ret 10.23 - 10.24 -