Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > SSR_impls > SSR__MC_shared_impl
changeset 64:bd5ab695145c Holistic_Model
MEAS__ macros for language added, and renamed a few things
| author | Some Random Person <seanhalle@yahoo.com> |
|---|---|
| date | Tue, 13 Mar 2012 18:30:05 -0700 |
| parents | a32504bb2a1c |
| children | 51b8f15fea29 |
| files | DESIGN_NOTES.txt SSR.c SSR.h SSR.s SSR_Measurement.h SSR_PluginFns.c SSR_Request_Handlers.c SSR_asm.s SSR_lib.c dependency.c |
| diffstat | 10 files changed, 942 insertions(+), 1068 deletions(-) [+] |
line diff
1.1 --- a/DESIGN_NOTES.txt Tue Mar 13 10:04:14 2012 -0700 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,212 +0,0 @@ 1.4 - 1.5 -From e-mail to Albert, on design of app-virt-procr to core-loop animation 1.6 -switch and back. 1.7 - 1.8 -==================== 1.9 -General warnings about this code: 1.10 -It only compiles in GCC 4.x (label addr and computed goto) 1.11 -Has assembly for x86 32bit 1.12 - 1.13 - 1.14 -==================== 1.15 -AVProcr data-struc has: stack-ptr, jump-ptr, data-ptr, slotNum, coreloop-ptr 1.16 - and semantic-custom-ptr 1.17 - 1.18 -The VMS Creator: takes ptr to function and ptr to initial data 1.19 --- creates a new AVProcr struc 1.20 --- sets the jmp-ptr field to the ptr-to-function passed in 1.21 --- sets the data-ptr to ptr to initial data passed in 1.22 --- if this is for a suspendable virt processor, then create a stack and set 1.23 - the stack-ptr 1.24 - 1.25 -VMS_int__create_slaveVP( AVProcrFnPtr fnPtr, void *initialData ) 1.26 -{ 1.27 -AVProcr newSlv = malloc( sizeof(AVProcr) ); 1.28 -newSlv->jmpPtr = fnPtr; 1.29 -newSlv->coreCtlrDonePt = &CoreCtlrDonePt; //label is in coreCtlr 1.30 -newSlv->data = initialData; 1.31 -newSlv->stackPtr = createNewStack(); 1.32 -return newSlv; 1.33 -} 1.34 - 1.35 -The semantic layer can then add its own state in the cusom-ptr field 1.36 - 1.37 -The Scheduler plug-in: 1.38 --- Sets slave-ptr in AVProcr, and points the slave to AVProcr 1.39 --- if non-suspendable, sets the AVProcr's stack-ptr to the slave's stack-ptr 1.40 - 1.41 -MasterLoop: 1.42 --- puts AVProcr structures onto the workQ 1.43 - 1.44 -CoreCtlr: 1.45 --- gets stack-ptr out of AVProcr and sets the core's stack-ptr to that 1.46 --- gets data-ptr out of AVProcr and puts it into reg GCC uses for that param 1.47 --- puts AVProcr's addr into reg GCC uses for the AVProcr-pointer param 1.48 --- jumps to the addr in AVProcr's jmp-ptr field 1.49 -CoreCtlr() 1.50 -{ while( FOREVER ) 1.51 - { nextSlv = readQ( workQ ); //workQ is static (global) var declared volatile 1.52 - <dataPtr-param-register> = nextSlv->data; 1.53 - <AVProcrPtr-param-register> = nextSlv; 1.54 - <stack-pointer register> = nextSlv->stackPtr; 1.55 - jmp nextSlv->jmpPtr; 1.56 -CoreCtlrDonePt: //label's addr put into AVProcr when create new one 1.57 - } 1.58 -} 1.59 -(Note, for suspendable processors coming back from suspension, there is no 1.60 - need to fill the parameter registers -- they will be discarded) 1.61 - 1.62 -Suspend an application-level virtual processor: 1.63 -VMS_int__AVPSuspend( AVProcr *pr ) 1.64 -{ 1.65 -pr->jmpPtr = &ResumePt; //label defined a few lines below 1.66 -pr->slave->doneFlag = TRUE; 1.67 -pr->stackPtr = <current SP reg value>; 1.68 -jmp pr->coreCtlrDonePt; 1.69 -ResumePt: return; 1.70 -} 1.71 - 1.72 -This works because the core controller will have switched back to this stack 1.73 - before jumping to ResumePt.. also, the core controller never modifies the 1.74 - stack pointer, it simply switches to whatever stack pointer is in the 1.75 - next AVProcr it gets off the workQ. 1.76 - 1.77 - 1.78 - 1.79 -============================================================================= 1.80 -As it is now, there's only one major unknown about GCC (first thing below 1.81 - the line), and there are a few restrictions, the most intrusive being 1.82 - that the functions the application gives to the semantic layer have a 1.83 - pre-defined prototype -- return nothing, take a pointer to initial data 1.84 - and a pointer to an AVProcr struc, which they're not allowed to modify 1.85 - -- only pass it to semantic-lib calls. 1.86 - 1.87 -So, here are the assumptions, restrictions, and so forth: 1.88 -=========================== 1.89 -Major assumption: that GCC will do the following the same way every time: 1.90 - say the application defines a function that fits this typedef: 1.91 -typedef void (*AVProcrFnPtr) ( void *, AVProcr * ); 1.92 - 1.93 -and let's say somewhere in the code they do this: 1.94 -AVProcrFnPtr fnPtr = &someFunc; 1.95 - 1.96 -then they do this: 1.97 -(*fnPtr)( dataPtr, animatingSlaveVPPtr ); 1.98 - 1.99 -Can the registers that GCC uses to pass the two pointers be predicted? 1.100 - Will they always be the same registers, in every program that has the 1.101 - same typedef? 1.102 -If that typedef fixes, guaranteed, the registers (on x86) that GCC will use 1.103 - to send the two pointers, then the rest of this solution works. 1.104 - 1.105 -Change in model: Instead of a virtual processor whose execution trace is 1.106 - divided into work-units, replacing that with the pattern that a virtual 1.107 - processor is suspended. Which means, no more "work unit" data structure 1.108 - -- instead, it's now an "Application Virtual Processor" structure 1.109 - -- AVProcr -- which is given directly to the application function! 1.110 - 1.111 - -- You were right, don't need slaves to be virtual processors, only need 1.112 - "scheduling buckets" -- just a way to keep track of things.. 1.113 - 1.114 -Restrictions: 1.115 --- the "virtual entities" created by the semantic layer must be virtual 1.116 - processors, created with a function-to-execute and initial data -- the 1.117 - function is restricted to return nothing and only take a pointer to the 1.118 - initial data plus a pointer to an AVProcr structure, which represents 1.119 - "self", the virtual processor created. (This is the interface I showed 1.120 - you for "Hello World" semantic layer). 1.121 -What this means for synchronous dataflow, is that the nodes in the graph 1.122 - are virtual processors that in turn spawn a new virtual processor for 1.123 - every "firing" of the node. This should be fine because the function 1.124 - that the node itself is created with is a "canned" function that is part 1.125 - of the semantic layer -- the function that is spawned is the user-provided 1.126 - function. The restriction only means that the values from the inputs to 1.127 - the node are packaged as the "initial data" given to the spawned virtual 1.128 - processor -- so the user-function has to cast a void * to the 1.129 - semantic-layer-defined structure by which it gets the inputs to the node. 1.130 - 1.131 --- Second restriction is that the semantic layer has to use VMS supplied 1.132 - stuff -- for example, the data structure that represents the 1.133 - application-level virtual processor is defined in VMS, and the semantic 1.134 - layer has to call a VMS function in order to suspend a virtual processor. 1.135 - 1.136 --- Third restriction is that the application code never do anything with 1.137 - the AVProcr structure except pass it to semantic-layer lib calls. 1.138 - 1.139 --- Fourth restriction is that every virtual processor must call a 1.140 - "dissipate" function as its last act -- the user-supplied 1.141 - virtual-processor function can't just end -- it has to call 1.142 - SemLib__dissipate( AVProcr ) before the closing brace.. and after the 1.143 - semantic layer is done cleaning up its own data, it has to in turn call 1.144 - VMS_int__disspate( AVProcr ). 1.145 - 1.146 --- For performance reasons, I think I want to have two different kinds of 1.147 - app-virtual processor -- suspendable ones and non-suspendable -- where 1.148 - non-suspendable are not allowed to perform any communication with other 1.149 - virtual processors, except at birth and death. Suspendable ones, of 1.150 - course can perform communications, create other processors, and so forth 1.151 - -- all of which cause it to suspend. 1.152 -The performance difference is that I need a separate stack for each 1.153 - suspendable, but non-suspendable can re-use a fixed number of stacks 1.154 - (one for each slave). 1.155 - 1.156 - 1.157 -==================== May 29 1.158 - 1.159 -Qs: 1.160 ---1 how to safely jump between virt processor's trace and coreloop 1.161 ---2 how to set up __cdecl style stack + frame for just-born virtual processor 1.162 ---3 how to switch stack-pointers + frame-pointers 1.163 - 1.164 - 1.165 ---1: 1.166 -Not sure if GCC's computed goto is safe, because modify the stack pointer 1.167 -without GCC's knowledge -- although, don't use the stack in the coreloop 1.168 -segment, so, actually, that should be safe! 1.169 - 1.170 -So, GCC has its own special C extensions, one of which gets address of label: 1.171 - 1.172 -void *labelAddr; 1.173 -labelAddr = &&label; 1.174 -goto *labelAddr; 1.175 - 1.176 ---2 1.177 -In CoreCtlr, will check whether VirtProc just born, or was suspended. 1.178 -If just born, do bit of code that sets up the virtual processor's stack 1.179 -and frame according to the __cdecl convention for the standard virt proc 1.180 -fn typedef -- save the pointer to data and pointer to virt proc struc into 1.181 -correct places in the frame 1.182 - __cdecl says, according to: 1.183 -http://unixwiz.net/techtips/win32-callconv-asm.html 1.184 -To do this: 1.185 -push the parameters onto the stack, right most first, working backwards to 1.186 - the left. 1.187 -Then perform call instr, which pushes return addr onto stack. 1.188 -Then callee first pushes the frame pointer, %EBP followed by placing the 1.189 -then-current value of stack pointer into %EBP 1.190 -push ebp 1.191 -mov ebp, esp // ebp « esp 1.192 - 1.193 -Once %ebp has been changed, it can now refer directly to the function's 1.194 - arguments as 8(%ebp), 12(%ebp). Note that 0(%ebp) is the old base pointer 1.195 - and 4(%ebp) is the old instruction pointer. 1.196 - 1.197 -Then callee pushes regs it will use then adds to stack pointer the size of 1.198 - its local vars. 1.199 - 1.200 -Stack in callee looks like this: 1.201 -16(%ebp) - third function parameter 1.202 -12(%ebp) - second function parameter 1.203 -8(%ebp) - first function parameter 1.204 -4(%ebp) - old %EIP (the function's "return address") 1.205 -----------^^ State seen at first instr of callee ^^----------- 1.206 -0(%ebp) - old %EBP (previous function's base pointer) 1.207 --4(%ebp) - save of EAX, the only reg used in function 1.208 --8(%ebp) - first local variable 1.209 --12(%ebp) - second local variable 1.210 --16(%ebp) - third local variable 1.211 - 1.212 - 1.213 ---3 1.214 -It might be just as simple as two mov instrs, one for %ESP, one for %EBP.. 1.215 - the stack and frame pointer regs
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/SSR.c Tue Mar 13 18:30:05 2012 -0700 2.3 @@ -0,0 +1,785 @@ 2.4 +/* 2.5 + * Copyright 2010 OpenSourceCodeStewardshipFoundation 2.6 + * 2.7 + * Licensed under BSD 2.8 + */ 2.9 + 2.10 +#include <stdio.h> 2.11 +#include <stdlib.h> 2.12 +#include <malloc.h> 2.13 + 2.14 +#include "Queue_impl/PrivateQueue.h" 2.15 +#include "Hash_impl/PrivateHash.h" 2.16 + 2.17 +#include "SSR.h" 2.18 +#include "SSR_Counter_Recording.h" 2.19 + 2.20 +//========================================================================== 2.21 + 2.22 +void 2.23 +SSR__init(); 2.24 + 2.25 +void 2.26 +SSR__init_Helper(); 2.27 +//========================================================================== 2.28 + 2.29 + 2.30 +/*TODO: Q: dealing with library f()s and DKU vs WT vs FoR 2.31 + * (still want to do FoR, with time-lines as syntax, could be super cool) 2.32 + * A: thinking pin the coreCtlrs for all of BLIS -- let Master arbitrate 2.33 + * among library, DKU, WT, FoR -- all the patterns in terms of virtual 2.34 + * processors (or equivalently work-units), so Master picks which virt procr 2.35 + * from which portions of app (DKU, WT, FoR) onto which sched slots 2.36 + *Might even do hierarchy of masters -- group of sched slots for each core 2.37 + * has its own master, that keeps generated work local 2.38 + * single-reader-single-writer sync everywhere -- no atomic primitives 2.39 + * Might have the different assigners talk to each other, to negotiate 2.40 + * larger-grain sharing of resources, according to predicted critical 2.41 + * path, and expansion of work 2.42 + */ 2.43 + 2.44 + 2.45 + 2.46 +//=========================================================================== 2.47 + 2.48 + 2.49 +/*These are the library functions *called in the application* 2.50 + * 2.51 + *There's a pattern for the outside sequential code to interact with the 2.52 + * VMS_HW code. 2.53 + *The VMS_HW system is inside a boundary.. every SSR system is in its 2.54 + * own directory that contains the functions for each of the processor types. 2.55 + * One of the processor types is the "seed" processor that starts the 2.56 + * cascade of creating all the processors that do the work. 2.57 + *So, in the directory is a file called "EntryPoint.c" that contains the 2.58 + * function, named appropriately to the work performed, that the outside 2.59 + * sequential code calls. This function follows a pattern: 2.60 + *1) it calls SSR__init() 2.61 + *2) it creates the initial data for the seed processor, which is passed 2.62 + * in to the function 2.63 + *3) it creates the seed SSR processor, with the data to start it with. 2.64 + *4) it calls startSSRThenWaitUntilWorkDone 2.65 + *5) it gets the returnValue from the transfer struc and returns that 2.66 + * from the function 2.67 + * 2.68 + *For now, a new SSR system has to be created via SSR__init every 2.69 + * time an entry point function is called -- later, might add letting the 2.70 + * SSR system be created once, and let all the entry points just reuse 2.71 + * it -- want to be as simple as possible now, and see by using what makes 2.72 + * sense for later.. 2.73 + */ 2.74 + 2.75 + 2.76 + 2.77 +//=========================================================================== 2.78 + 2.79 +/*This is the "border crossing" function -- the thing that crosses from the 2.80 + * outside world, into the VMS_HW world. It initializes and starts up the 2.81 + * VMS system, then creates one processor from the specified function and 2.82 + * puts it into the readyQ. From that point, that one function is resp. 2.83 + * for creating all the other processors, that then create others, and so 2.84 + * forth. 2.85 + *When all the processors, including the seed, have dissipated, then this 2.86 + * function returns. The results will have been written by side-effect via 2.87 + * pointers read from, or written into initData. 2.88 + * 2.89 + *NOTE: no Threads should exist in the outside program that might touch 2.90 + * any of the data reachable from initData passed in to here 2.91 + */ 2.92 +void 2.93 +SSR__create_seed_procr_and_do_work( TopLevelFnPtr fnPtr, void *initData ) 2.94 + { SSRSemEnv *semEnv; 2.95 + SlaveVP *seedPr; 2.96 + 2.97 + SSR__init(); //normal multi-thd 2.98 + 2.99 + semEnv = _VMSMasterEnv->semanticEnv; 2.100 + 2.101 + //SSR starts with one processor, which is put into initial environ, 2.102 + // and which then calls create() to create more, thereby expanding work 2.103 + seedPr = SSR__create_procr_helper( fnPtr, initData, 2.104 + semEnv, semEnv->nextCoreToGetNewPr++ ); 2.105 + 2.106 + resume_slaveVP( seedPr, semEnv ); 2.107 + 2.108 + VMS_SS__start_the_work_then_wait_until_done(); //normal multi-thd 2.109 + 2.110 + SSR__cleanup_after_shutdown(); 2.111 + } 2.112 + 2.113 + 2.114 +int32 2.115 +SSR__giveMinWorkUnitCycles( float32 percentOverhead ) 2.116 + { 2.117 + return MIN_WORK_UNIT_CYCLES; 2.118 + } 2.119 + 2.120 +int32 2.121 +SSR__giveIdealNumWorkUnits() 2.122 + { 2.123 + return NUM_SCHED_SLOTS * NUM_CORES; 2.124 + } 2.125 + 2.126 +int32 2.127 +SSR__give_number_of_cores_to_schedule_onto() 2.128 + { 2.129 + return NUM_CORES; 2.130 + } 2.131 + 2.132 +/*For now, use TSC -- later, make these two macros with assembly that first 2.133 + * saves jump point, and second jumps back several times to get reliable time 2.134 + */ 2.135 +void 2.136 +SSR__start_primitive() 2.137 + { saveLowTimeStampCountInto( ((SSRSemEnv *)(_VMSMasterEnv->semanticEnv))-> 2.138 + primitiveStartTime ); 2.139 + } 2.140 + 2.141 +/*Just quick and dirty for now -- make reliable later 2.142 + * will want this to jump back several times -- to be sure cache is warm 2.143 + * because don't want comm time included in calc-time measurement -- and 2.144 + * also to throw out any "weird" values due to OS interrupt or TSC rollover 2.145 + */ 2.146 +int32 2.147 +SSR__end_primitive_and_give_cycles() 2.148 + { int32 endTime, startTime; 2.149 + //TODO: fix by repeating time-measurement 2.150 + saveLowTimeStampCountInto( endTime ); 2.151 + startTime =((SSRSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime; 2.152 + return (endTime - startTime); 2.153 + } 2.154 + 2.155 +//=========================================================================== 2.156 + 2.157 +/*Initializes all the data-structures for a SSR system -- but doesn't 2.158 + * start it running yet! 2.159 + * 2.160 + *This runs in the main thread -- before VMS starts up 2.161 + * 2.162 + *This sets up the semantic layer over the VMS system 2.163 + * 2.164 + *First, calls VMS_Setup, then creates own environment, making it ready 2.165 + * for creating the seed processor and then starting the work. 2.166 + */ 2.167 +void 2.168 +SSR__init() 2.169 + { 2.170 + VMS_SS__init(); 2.171 + //masterEnv, a global var, now is partially set up by init_VMS 2.172 + // after this, have VMS_int__malloc and VMS_int__free available 2.173 + 2.174 + SSR__init_Helper(); 2.175 + } 2.176 + 2.177 + 2.178 +void idle_fn(void* data, SlaveVP *animatingSlv){ 2.179 + while(1){ 2.180 + VMS_int__suspend_slaveVP_and_send_req(animatingSlv); 2.181 + } 2.182 +} 2.183 + 2.184 +void 2.185 +SSR__init_Helper() 2.186 + { SSRSemEnv *semanticEnv; 2.187 + PrivQueueStruc **readyVPQs; 2.188 + int coreIdx, i, j; 2.189 + 2.190 + //Hook up the semantic layer's plug-ins to the Master virt procr 2.191 + _VMSMasterEnv->requestHandler = &SSR__Request_Handler; 2.192 + _VMSMasterEnv->slaveAssigner = &SSR__assign_slaveVP; 2.193 + #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 2.194 + _VMSMasterEnv->counterHandler = &SSR__counter_handler; 2.195 + #endif 2.196 + 2.197 + //create the semantic layer's environment (all its data) and add to 2.198 + // the master environment 2.199 + semanticEnv = VMS_int__malloc( sizeof( SSRSemEnv ) ); 2.200 + _VMSMasterEnv->semanticEnv = semanticEnv; 2.201 + 2.202 + #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 2.203 + SSR__init_counter_data_structs(); 2.204 + #endif 2.205 + for(i=0;i<NUM_CORES;++i){ 2.206 + for(j=0;j<NUM_SCHED_SLOTS;++j){ 2.207 + semanticEnv->idlePr[i][j] = VMS_int__create_slaveVP(&idle_fn,NULL); 2.208 + semanticEnv->idlePr[i][j]->coreAnimatedBy = i; 2.209 + } 2.210 + } 2.211 + 2.212 + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 2.213 + semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128); 2.214 + semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128); 2.215 + semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128); 2.216 + semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128); 2.217 + semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8); 2.218 + 2.219 + semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128); 2.220 + memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_SCHED_SLOTS * sizeof(Unit))); 2.221 + #endif 2.222 + 2.223 + //create the ready queue, hash tables used for pairing send to receive 2.224 + // and so forth 2.225 + //TODO: add hash tables for pairing sends with receives, and 2.226 + // initialize the data ownership system 2.227 + readyVPQs = VMS_int__malloc( NUM_CORES * sizeof(PrivQueueStruc *) ); 2.228 + 2.229 + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 2.230 + { 2.231 + readyVPQs[ coreIdx ] = makeVMSQ(); 2.232 + } 2.233 + 2.234 + semanticEnv->readyVPQs = readyVPQs; 2.235 + 2.236 + semanticEnv->nextCoreToGetNewPr = 0; 2.237 + semanticEnv->numSlaveVP = 0; 2.238 + 2.239 + semanticEnv->commHashTbl = makeHashTable( 1<<16, &VMS_int__free );//start big 2.240 + 2.241 + //TODO: bug -- turn these arrays into dyn arrays to eliminate limit 2.242 + //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( ); 2.243 + //semanticEnv->transactionStrucs = makeDynArrayInfo( ); 2.244 + for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ ) 2.245 + { 2.246 + semanticEnv->fnSingletons[i].endInstrAddr = NULL; 2.247 + semanticEnv->fnSingletons[i].hasBeenStarted = FALSE; 2.248 + semanticEnv->fnSingletons[i].hasFinished = FALSE; 2.249 + semanticEnv->fnSingletons[i].waitQ = makeVMSQ(); 2.250 + semanticEnv->transactionStrucs[i].waitingVPQ = makeVMSQ(); 2.251 + } 2.252 + } 2.253 + 2.254 + 2.255 +/*Frees any memory allocated by SSR__init() then calls VMS_int__shutdown 2.256 + */ 2.257 +void 2.258 +SSR__cleanup_after_shutdown() 2.259 + { SSRSemEnv *semanticEnv; 2.260 + 2.261 + semanticEnv = _VMSMasterEnv->semanticEnv; 2.262 + 2.263 + #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 2.264 + //UCC 2.265 + FILE* output; 2.266 + int n; 2.267 + char filename[255]; 2.268 + for(n=0;n<255;n++) 2.269 + { 2.270 + sprintf(filename, "./counters/UCC.%d",n); 2.271 + output = fopen(filename,"r"); 2.272 + if(output) 2.273 + { 2.274 + fclose(output); 2.275 + }else{ 2.276 + break; 2.277 + } 2.278 + } 2.279 + if(n<255){ 2.280 + printf("Saving UCC to File: %s ...\n", filename); 2.281 + output = fopen(filename,"w+"); 2.282 + if(output!=NULL){ 2.283 + set_dependency_file(output); 2.284 + //fprintf(output,"digraph Dependencies {\n"); 2.285 + //set_dot_file(output); 2.286 + //FIXME: first line still depends on counters being enabled, replace w/ unit struct! 2.287 + //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info ); 2.288 + forAllInListOfArraysDo(semanticEnv->unitList, &print_unit_to_file); 2.289 + forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); 2.290 + forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); 2.291 + forAllInDynArrayDo(semanticEnv->ntonGroupsInfo,&print_nton_to_file); 2.292 + //fprintf(output,"}\n"); 2.293 + fflush(output); 2.294 + 2.295 + } else 2.296 + printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 2.297 + } else { 2.298 + printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 2.299 + } 2.300 + //Loop Graph 2.301 + for(n=0;n<255;n++) 2.302 + { 2.303 + sprintf(filename, "./counters/LoopGraph.%d",n); 2.304 + output = fopen(filename,"r"); 2.305 + if(output) 2.306 + { 2.307 + fclose(output); 2.308 + }else{ 2.309 + break; 2.310 + } 2.311 + } 2.312 + if(n<255){ 2.313 + printf("Saving LoopGraph to File: %s ...\n", filename); 2.314 + output = fopen(filename,"w+"); 2.315 + if(output!=NULL){ 2.316 + set_dependency_file(output); 2.317 + //fprintf(output,"digraph Dependencies {\n"); 2.318 + //set_dot_file(output); 2.319 + //FIXME: first line still depends on counters being enabled, replace w/ unit struct! 2.320 + //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info ); 2.321 + forAllInListOfArraysDo( semanticEnv->unitList, &print_unit_to_file ); 2.322 + forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); 2.323 + forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); 2.324 + forAllInListOfArraysDo( semanticEnv->dynDependenciesList, &print_dyn_dependency_to_file ); 2.325 + forAllInListOfArraysDo( semanticEnv->hwArcs, &print_hw_dependency_to_file ); 2.326 + //fprintf(output,"}\n"); 2.327 + fflush(output); 2.328 + 2.329 + } else 2.330 + printf("Opening LoopGraph file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 2.331 + } else { 2.332 + printf("Could not open LoopGraph file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 2.333 + } 2.334 + 2.335 + 2.336 + freeListOfArrays(semanticEnv->unitList); 2.337 + freeListOfArrays(semanticEnv->commDependenciesList); 2.338 + freeListOfArrays(semanticEnv->ctlDependenciesList); 2.339 + freeListOfArrays(semanticEnv->dynDependenciesList); 2.340 + 2.341 + #endif 2.342 +#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 2.343 + for(n=0;n<255;n++) 2.344 + { 2.345 + sprintf(filename, "./counters/Counters.%d.csv",n); 2.346 + output = fopen(filename,"r"); 2.347 + if(output) 2.348 + { 2.349 + fclose(output); 2.350 + }else{ 2.351 + break; 2.352 + } 2.353 + } 2.354 + if(n<255){ 2.355 + printf("Saving Counter measurements to File: %s ...\n", filename); 2.356 + output = fopen(filename,"w+"); 2.357 + if(output!=NULL){ 2.358 + set_counter_file(output); 2.359 + int i; 2.360 + for(i=0;i<NUM_CORES;i++){ 2.361 + forAllInListOfArraysDo( semanticEnv->counterList[i], &print_counter_events_to_file ); 2.362 + fflush(output); 2.363 + } 2.364 + 2.365 + } else 2.366 + printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 2.367 + } else { 2.368 + printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 2.369 + } 2.370 + 2.371 +#endif 2.372 +/* It's all allocated inside VMS's big chunk -- that's about to be freed, so 2.373 + * nothing to do here 2.374 + 2.375 + 2.376 + for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 2.377 + { 2.378 + VMS_int__free( semanticEnv->readyVPQs[coreIdx]->startOfData ); 2.379 + VMS_int__free( semanticEnv->readyVPQs[coreIdx] ); 2.380 + } 2.381 + VMS_int__free( semanticEnv->readyVPQs ); 2.382 + 2.383 + freeHashTable( semanticEnv->commHashTbl ); 2.384 + VMS_int__free( _VMSMasterEnv->semanticEnv ); 2.385 + */ 2.386 + VMS_SS__cleanup_at_end_of_shutdown(); 2.387 + } 2.388 + 2.389 + 2.390 +//=========================================================================== 2.391 + 2.392 +/* 2.393 + */ 2.394 + SlaveVP * 2.395 +SSR__create_procr_with( TopLevelFnPtr fnPtr, void *initData, 2.396 + SlaveVP *creatingPr ) 2.397 + { SSRSemReq reqData; 2.398 + 2.399 + //the semantic request data is on the stack and disappears when this 2.400 + // call returns -- it's guaranteed to remain in the VP's stack for as 2.401 + // long as the VP is suspended. 2.402 + reqData.reqType = 0; //know type because in a VMS create req 2.403 + reqData.coreToAssignOnto = -1; //means round-robin assign 2.404 + reqData.fnPtr = fnPtr; 2.405 + reqData.initData = initData; 2.406 + reqData.sendPr = creatingPr; 2.407 + 2.408 + VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); 2.409 + 2.410 + return creatingPr->dataRetFromReq; 2.411 + } 2.412 + 2.413 + SlaveVP * 2.414 +SSR__create_procr_with_affinity( TopLevelFnPtr fnPtr, void *initData, 2.415 + SlaveVP *creatingPr, int32 coreToAssignOnto ) 2.416 + { SSRSemReq reqData; 2.417 + 2.418 + //the semantic request data is on the stack and disappears when this 2.419 + // call returns -- it's guaranteed to remain in the VP's stack for as 2.420 + // long as the VP is suspended. 2.421 + reqData.reqType = 0; //know type because in a VMS create req 2.422 + reqData.coreToAssignOnto = coreToAssignOnto; 2.423 + reqData.fnPtr = fnPtr; 2.424 + reqData.initData = initData; 2.425 + reqData.sendPr = creatingPr; 2.426 + 2.427 + VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); 2.428 + 2.429 + return creatingPr->dataRetFromReq; 2.430 + } 2.431 + 2.432 + 2.433 + void 2.434 +SSR__dissipate_procr( SlaveVP *procrToDissipate ) 2.435 + { 2.436 + VMS_WL__send_dissipate_req( procrToDissipate ); 2.437 + } 2.438 + 2.439 + 2.440 +//=========================================================================== 2.441 + 2.442 +void * 2.443 +SSR__malloc_to( int32 sizeToMalloc, SlaveVP *owningPr ) 2.444 + { SSRSemReq reqData; 2.445 + 2.446 + reqData.reqType = malloc_req; 2.447 + reqData.sendPr = owningPr; 2.448 + reqData.sizeToMalloc = sizeToMalloc; 2.449 + 2.450 + VMS_WL__send_sem_request( &reqData, owningPr ); 2.451 + 2.452 + return owningPr->dataRetFromReq; 2.453 + } 2.454 + 2.455 + 2.456 +/*Sends request to Master, which does the work of freeing 2.457 + */ 2.458 +void 2.459 +SSR__free( void *ptrToFree, SlaveVP *owningPr ) 2.460 + { SSRSemReq reqData; 2.461 + 2.462 + reqData.reqType = free_req; 2.463 + reqData.sendPr = owningPr; 2.464 + reqData.ptrToFree = ptrToFree; 2.465 + 2.466 + VMS_WL__send_sem_request( &reqData, owningPr ); 2.467 + } 2.468 + 2.469 + 2.470 +void 2.471 +SSR__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerSlv, 2.472 + SlaveVP *newOwnerPr ) 2.473 + { 2.474 + //TODO: put in the ownership system that automatically frees when no 2.475 + // owners of data left -- will need keeper for keeping data around when 2.476 + // future created processors might need it but don't exist yet 2.477 + } 2.478 + 2.479 + 2.480 +void 2.481 +SSR__add_ownership_by_to( SlaveVP *newOwnerSlv, void *data ) 2.482 + { 2.483 + 2.484 + } 2.485 + 2.486 + 2.487 +void 2.488 +SSR__remove_ownership_by_from( SlaveVP *loserSlv, void *dataLosing ) 2.489 + { 2.490 + 2.491 + } 2.492 + 2.493 + 2.494 +/*Causes the SSR system to remove internal ownership, so data won't be 2.495 + * freed when SSR shuts down, and will persist in the external program. 2.496 + * 2.497 + *Must be called from the processor that currently owns the data. 2.498 + * 2.499 + *IMPL: Transferring ownership touches two different virtual processor's 2.500 + * state -- which means it has to be done carefully -- the VMS rules for 2.501 + * semantic layers say that a work-unit is only allowed to touch the 2.502 + * virtual processor it is part of, and that only a single work-unit per 2.503 + * virtual processor be assigned to a slave at a time. So, this has to 2.504 + * modify the virtual processor that owns the work-unit that called this 2.505 + * function, then create a request to have the other processor modified. 2.506 + *However, in this case, the TO processor is the outside, and transfers 2.507 + * are only allowed to be called by the giver-upper, so can mark caller of 2.508 + * this function as no longer owner, and return -- done. 2.509 + */ 2.510 +void 2.511 +SSR__transfer_ownership_to_outside( void *data ) 2.512 + { 2.513 + //TODO: removeAllOwnersFrom( data ); 2.514 + } 2.515 + 2.516 + 2.517 +//=========================================================================== 2.518 + 2.519 +void 2.520 +SSR__send_of_type_to( SlaveVP *sendPr, void *msg, const int type, 2.521 + SlaveVP *receivePr) 2.522 + { SSRSemReq reqData; 2.523 + 2.524 + reqData.receivePr = receivePr; 2.525 + reqData.sendPr = sendPr; 2.526 + reqData.reqType = send_type; 2.527 + reqData.msgType = type; 2.528 + reqData.msg = msg; 2.529 + reqData.nextReqInHashEntry = NULL; 2.530 + 2.531 + //On ownership -- remove inside the send and let ownership sit in limbo 2.532 + // as a potential in an entry in the hash table, when this receive msg 2.533 + // gets paired to a send, the ownership gets added to the receivePr -- 2.534 + // the next work-unit in the receivePr's trace will have ownership. 2.535 + VMS_WL__send_sem_request( &reqData, sendPr ); 2.536 + 2.537 + //When come back from suspend, no longer own data reachable from msg 2.538 + //TODO: release ownership here 2.539 + } 2.540 + 2.541 +void 2.542 +SSR__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr ) 2.543 + { SSRSemReq reqData; 2.544 + 2.545 + //hash on the receiver, 'cause always know it, but sometimes want to 2.546 + // receive from anonymous sender 2.547 + 2.548 + reqData.receivePr = receivePr; 2.549 + reqData.sendPr = sendPr; 2.550 + reqData.reqType = send_from_to; 2.551 + reqData.msg = msg; 2.552 + reqData.nextReqInHashEntry = NULL; 2.553 + 2.554 + VMS_WL__send_sem_request( &reqData, sendPr ); 2.555 + } 2.556 + 2.557 + 2.558 +//=========================================================================== 2.559 + 2.560 +void * 2.561 +SSR__receive_any_to( SlaveVP *receivePr ) 2.562 + { 2.563 + 2.564 + } 2.565 + 2.566 +void * 2.567 +SSR__receive_type_to( const int type, SlaveVP *receivePr ) 2.568 + { 2.569 + SSRSemReq reqData; 2.570 + 2.571 + reqData.receivePr = receivePr; 2.572 + reqData.reqType = receive_type; 2.573 + reqData.msgType = type; 2.574 + reqData.nextReqInHashEntry = NULL; 2.575 + 2.576 + VMS_WL__send_sem_request( &reqData, receivePr ); 2.577 + 2.578 + return receivePr->dataRetFromReq; 2.579 + } 2.580 + 2.581 + 2.582 + 2.583 +/*Call this at point receiving virt pr wants in-coming data. 2.584 + * 2.585 + *The reason receivePr must call this is that it modifies the receivPr 2.586 + * loc structure directly -- and the VMS rules state a virtual processor 2.587 + * loc structure can only be modified by itself. 2.588 + */ 2.589 +void * 2.590 +SSR__receive_from_to( SlaveVP *sendPr, SlaveVP *receivePr ) 2.591 + { SSRSemReq reqData; 2.592 + 2.593 + //hash on the receiver, 'cause always know it, but sometimes want to 2.594 + // receive from anonymous sender 2.595 + 2.596 + reqData.receivePr = receivePr; 2.597 + reqData.sendPr = sendPr; 2.598 + reqData.reqType = receive_from_to; 2.599 + reqData.nextReqInHashEntry = NULL; 2.600 + 2.601 + VMS_WL__send_sem_request( &reqData, receivePr ); 2.602 + 2.603 + return receivePr->dataRetFromReq; 2.604 + } 2.605 + 2.606 + 2.607 +//=========================================================================== 2.608 +// 2.609 +/*A function singleton is a function whose body executes exactly once, on a 2.610 + * single core, no matter how many times the fuction is called and no 2.611 + * matter how many cores or the timing of cores calling it. 2.612 + * 2.613 + *A data singleton is a ticket attached to data. That ticket can be used 2.614 + * to get the data through the function exactly once, no matter how many 2.615 + * times the data is given to the function, and no matter the timing of 2.616 + * trying to get the data through from different cores. 2.617 + */ 2.618 + 2.619 +/*asm function declarations*/ 2.620 +void asm_save_ret_to_singleton(SSRSingleton *singletonPtrAddr); 2.621 +void asm_write_ret_from_singleton(SSRSingleton *singletonPtrAddr); 2.622 + 2.623 +/*Fn singleton uses ID as index into array of singleton structs held in the 2.624 + * semantic environment. 2.625 + */ 2.626 +void 2.627 +SSR__start_fn_singleton( int32 singletonID, SlaveVP *animPr ) 2.628 + { 2.629 + SSRSemReq reqData; 2.630 + 2.631 + // 2.632 + reqData.reqType = singleton_fn_start; 2.633 + reqData.singletonID = singletonID; 2.634 + 2.635 + VMS_WL__send_sem_request( &reqData, animPr ); 2.636 + if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton 2.637 + { 2.638 + SSRSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); 2.639 + asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 2.640 + } 2.641 + } 2.642 + 2.643 +/*Data singleton hands addr of loc holding a pointer to a singleton struct. 2.644 + * The start_data_singleton makes the structure and puts its addr into the 2.645 + * location. 2.646 + */ 2.647 +void 2.648 +SSR__start_data_singleton( SSRSingleton **singletonAddr, SlaveVP *animPr ) 2.649 + { 2.650 + SSRSemReq reqData; 2.651 + 2.652 + if( *singletonAddr && (*singletonAddr)->hasFinished ) 2.653 + goto JmpToEndSingleton; 2.654 + 2.655 + reqData.reqType = singleton_data_start; 2.656 + reqData.singletonPtrAddr = singletonAddr; 2.657 + 2.658 + VMS_WL__send_sem_request( &reqData, animPr ); 2.659 + if( animPr->dataRetFromReq ) //either 0 or end singleton's return addr 2.660 + { //Assembly code changes the return addr on the stack to the one 2.661 + // saved into the singleton by the end-singleton-fn 2.662 + //The return addr is at 0x4(%%ebp) 2.663 + JmpToEndSingleton: 2.664 + asm_write_ret_from_singleton(*singletonAddr); 2.665 + } 2.666 + //now, simply return 2.667 + //will exit either from the start singleton call or the end-singleton call 2.668 + } 2.669 + 2.670 +/*Uses ID as index into array of flags. If flag already set, resumes from 2.671 + * end-label. Else, sets flag and resumes normally. 2.672 + * 2.673 + *Note, this call cannot be inlined because the instr addr at the label 2.674 + * inside is shared by all invocations of a given singleton ID. 2.675 + */ 2.676 +void 2.677 +SSR__end_fn_singleton( int32 singletonID, SlaveVP *animPr ) 2.678 + { 2.679 + SSRSemReq reqData; 2.680 + 2.681 + //don't need this addr until after at least one singleton has reached 2.682 + // this function 2.683 + SSRSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); 2.684 + asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 2.685 + 2.686 + reqData.reqType = singleton_fn_end; 2.687 + reqData.singletonID = singletonID; 2.688 + 2.689 + VMS_WL__send_sem_request( &reqData, animPr ); 2.690 + 2.691 +EndSingletonInstrAddr: 2.692 + return; 2.693 + } 2.694 + 2.695 +void 2.696 +SSR__end_data_singleton( SSRSingleton **singletonPtrAddr, SlaveVP *animPr ) 2.697 + { 2.698 + SSRSemReq reqData; 2.699 + 2.700 + //don't need this addr until after singleton struct has reached 2.701 + // this function for first time 2.702 + //do assembly that saves the return addr of this fn call into the 2.703 + // data singleton -- that data-singleton can only be given to exactly 2.704 + // one instance in the code of this function. However, can use this 2.705 + // function in different places for different data-singletons. 2.706 +// (*(singletonAddr))->endInstrAddr = &&EndDataSingletonInstrAddr; 2.707 + 2.708 + 2.709 + asm_save_ret_to_singleton(*singletonPtrAddr); 2.710 + 2.711 + reqData.reqType = singleton_data_end; 2.712 + reqData.singletonPtrAddr = singletonPtrAddr; 2.713 + 2.714 + VMS_WL__send_sem_request( &reqData, animPr ); 2.715 + } 2.716 + 2.717 +/*This executes the function in the masterVP, so it executes in isolation 2.718 + * from any other copies -- only one copy of the function can ever execute 2.719 + * at a time. 2.720 + * 2.721 + *It suspends to the master, and the request handler takes the function 2.722 + * pointer out of the request and calls it, then resumes the VP. 2.723 + *Only very short functions should be called this way -- for longer-running 2.724 + * isolation, use transaction-start and transaction-end, which run the code 2.725 + * between as work-code. 2.726 + */ 2.727 +void 2.728 +SSR__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, 2.729 + void *data, SlaveVP *animPr ) 2.730 + { 2.731 + SSRSemReq reqData; 2.732 + 2.733 + // 2.734 + reqData.reqType = atomic; 2.735 + reqData.fnToExecInMaster = ptrToFnToExecInMaster; 2.736 + reqData.dataForFn = data; 2.737 + 2.738 + VMS_WL__send_sem_request( &reqData, animPr ); 2.739 + } 2.740 + 2.741 + 2.742 +/*This suspends to the master. 2.743 + *First, it looks at the VP's data, to see the highest transactionID that VP 2.744 + * already has entered. If the current ID is not larger, it throws an 2.745 + * exception stating a bug in the code. Otherwise it puts the current ID 2.746 + * there, and adds the ID to a linked list of IDs entered -- the list is 2.747 + * used to check that exits are properly ordered. 2.748 + *Next it is uses transactionID as index into an array of transaction 2.749 + * structures. 2.750 + *If the "VP_currently_executing" field is non-null, then put requesting VP 2.751 + * into queue in the struct. (At some point a holder will request 2.752 + * end-transaction, which will take this VP from the queue and resume it.) 2.753 + *If NULL, then write requesting into the field and resume. 2.754 + */ 2.755 +void 2.756 +SSR__start_transaction( int32 transactionID, SlaveVP *animPr ) 2.757 + { 2.758 + SSRSemReq reqData; 2.759 + 2.760 + // 2.761 + reqData.sendPr = animPr; 2.762 + reqData.reqType = trans_start; 2.763 + reqData.transID = transactionID; 2.764 + 2.765 + VMS_WL__send_sem_request( &reqData, animPr ); 2.766 + } 2.767 + 2.768 +/*This suspends to the master, then uses transactionID as index into an 2.769 + * array of transaction structures. 2.770 + *It looks at VP_currently_executing to be sure it's same as requesting VP. 2.771 + * If different, throws an exception, stating there's a bug in the code. 2.772 + *Next it looks at the queue in the structure. 2.773 + *If it's empty, it sets VP_currently_executing field to NULL and resumes. 2.774 + *If something in, gets it, sets VP_currently_executing to that VP, then 2.775 + * resumes both. 2.776 + */ 2.777 +void 2.778 +SSR__end_transaction( int32 transactionID, SlaveVP *animPr ) 2.779 + { 2.780 + SSRSemReq reqData; 2.781 + 2.782 + // 2.783 + reqData.sendPr = animPr; 2.784 + reqData.reqType = trans_end; 2.785 + reqData.transID = transactionID; 2.786 + 2.787 + VMS_WL__send_sem_request( &reqData, animPr ); 2.788 + }
3.1 --- a/SSR.h Tue Mar 13 10:04:14 2012 -0700 3.2 +++ b/SSR.h Tue Mar 13 18:30:05 2012 -0700 3.3 @@ -84,7 +84,7 @@ 3.4 3.5 void *initData; 3.6 TopLevelFnPtr fnPtr; 3.7 - int32 coreToScheduleOnto; 3.8 + int32 coreToAssignOnto; 3.9 3.10 int32 sizeToMalloc; 3.11 void *ptrToFree; 3.12 @@ -182,7 +182,7 @@ 3.13 3.14 SlaveVP * 3.15 SSR__create_procr_with_affinity( TopLevelFnPtr fnPtr, void *initData, 3.16 - SlaveVP *creatingPr, int32 coreToScheduleOnto); 3.17 + SlaveVP *creatingPr, int32 coreToAssignOnto); 3.18 3.19 void 3.20 SSR__dissipate_procr( SlaveVP *procrToDissipate ); 3.21 @@ -253,11 +253,15 @@ 3.22 SSR__Request_Handler( SlaveVP *requestingPr, void *_semEnv ); 3.23 3.24 SlaveVP * 3.25 -SSR__schedule_slaveVP( void *_semEnv, int coreNum, int slotNum ); 3.26 +SSR__assign_slaveVP( void *_semEnv, int coreNum, SchedSlot *slot ); 3.27 3.28 SlaveVP* 3.29 SSR__create_procr_helper( TopLevelFnPtr fnPtr, void *initData, 3.30 - SSRSemEnv *semEnv, int32 coreToScheduleOnto ); 3.31 + SSRSemEnv *semEnv, int32 coreToAssignOnto ); 3.32 3.33 +//===================== Measurement of Lang Overheads ===================== 3.34 +#include "SSR_Measurement.h" 3.35 + 3.36 +//=========================================================================== 3.37 #endif /* _SSR_H */ 3.38
4.1 --- a/SSR.s Tue Mar 13 10:04:14 2012 -0700 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,21 +0,0 @@ 4.4 - 4.5 -//Assembly code takes the return addr off the stack and saves 4.6 -// into the singleton. The first field in the singleton is the 4.7 -// "endInstrAddr" field, and the return addr is at 0x4(%ebp) 4.8 -.globl asm_save_ret_to_singleton 4.9 -asm_save_ret_to_singleton: 4.10 - movq 0x8(%rbp), %rax #get ret address, ebp is the same as in the calling function 4.11 - movq %rax, (%rdi) #write ret addr to endInstrAddr field 4.12 - ret 4.13 - 4.14 - 4.15 -//Assembly code changes the return addr on the stack to the one 4.16 -// saved into the singleton by the end-singleton-fn 4.17 -//The stack's return addr is at 0x4(%%ebp) 4.18 -.globl asm_write_ret_from_singleton 4.19 -asm_write_ret_from_singleton: 4.20 - movq (%rdi), %rax #get endInstrAddr field 4.21 - movq %rax, 0x8(%rbp) #write return addr to the stack of the caller 4.22 - ret 4.23 - 4.24 -
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/SSR_Measurement.h Tue Mar 13 18:30:05 2012 -0700 5.3 @@ -0,0 +1,87 @@ 5.4 +/* 5.5 + * Copyright 2009 OpenSourceStewardshipFoundation.org 5.6 + * Licensed under GNU General Public License version 2 5.7 + * 5.8 + * Author: seanhalle@yahoo.com 5.9 + * 5.10 + */ 5.11 + 5.12 +#ifndef _SSR_MEAS_H 5.13 +#define _SSR_MEAS_H 5.14 + 5.15 + 5.16 +#ifdef MEAS__TURN_ON_LANG_MEAS 5.17 + 5.18 + #ifdef MEAS__Make_Meas_Hists_for_Language 5.19 + #undef MEAS__Make_Meas_Hists_for_Language 5.20 + #endif 5.21 + 5.22 + 5.23 +//=================== Language-specific Measurement Stuff =================== 5.24 +// 5.25 +// 5.26 + #define SendFromToHistIdx 1 //note: starts at 1 5.27 + #define SendOfTypeHistIdx 2 5.28 + #define ReceiveFromToHistIdx 3 5.29 + #define ReceiveOfTypeHistIdx 4 5.30 + 5.31 + #define MEAS__Make_Meas_Hists_for_Language \ 5.32 + _VMSMasterEnv->measHistsInfo = \ 5.33 + makePrivDynArrayOfSize( (void***)&(_VMSMasterEnv->measHists), 200); \ 5.34 + makeAMeasHist( SendFromToHistIdx, "SendFromTo", 50, 0, 100 ) \ 5.35 + makeAMeasHist( SendOfTypeHistIdx, "SendOfType", 50, 0, 100 ) \ 5.36 + makeAMeasHist( ReceiveFromToHistIdx,"ReceiveFromTo", 50, 0, 100 ) \ 5.37 + makeAMeasHist( ReceiveOfTypeHistIdx,"ReceiveOfType", 50, 0, 100 ) 5.38 + 5.39 + #define Meas_startSendFromTo \ 5.40 + int32 startStamp, endStamp; \ 5.41 + saveLowTimeStampCountInto( startStamp ); \ 5.42 + 5.43 + #define Meas_endSendFromTo \ 5.44 + saveLowTimeStampCountInto( endStamp ); \ 5.45 + addIntervalToHist( startStamp, endStamp, \ 5.46 + _VMSMasterEnv->measHists[ SendFromToHistIdx ] ); 5.47 + 5.48 + #define Meas_startSendOfType \ 5.49 + int32 startStamp, endStamp; \ 5.50 + saveLowTimeStampCountInto( startStamp ); \ 5.51 + 5.52 + #define Meas_endSendOfType \ 5.53 + saveLowTimeStampCountInto( endStamp ); \ 5.54 + addIntervalToHist( startStamp, endStamp, \ 5.55 + _VMSMasterEnv->measHists[ SendOfTypeHistIdx ] ); 5.56 + 5.57 + #define Meas_startReceiveFromTo \ 5.58 + int32 startStamp, endStamp; \ 5.59 + saveLowTimeStampCountInto( startStamp ); \ 5.60 + 5.61 + #define Meas_endReceiveFromTo \ 5.62 + saveLowTimeStampCountInto( endStamp ); \ 5.63 + addIntervalToHist( startStamp, endStamp, \ 5.64 + _VMSMasterEnv->measHists[ ReceiveFromToHistIdx ] ); 5.65 + 5.66 + #define Meas_startReceiveOfType \ 5.67 + int32 startStamp, endStamp; \ 5.68 + saveLowTimeStampCountInto( startStamp ); \ 5.69 + 5.70 + #define Meas_endReceiveOfType \ 5.71 + saveLowTimeStampCountInto( endStamp ); \ 5.72 + addIntervalToHist( startStamp, endStamp, \ 5.73 + _VMSMasterEnv->measHists[ReceiveOfTypeHistIdx ] ); 5.74 + 5.75 +#else //===================== turned off ========================== 5.76 + 5.77 + #define MEAS__Make_Meas_Hists_for_Language 5.78 + #define Meas_startSendFromTo 5.79 + #define Meas_endSendFromTo 5.80 + #define Meas_startSendOfType 5.81 + #define Meas_endSendOfType 5.82 + #define Meas_startReceiveFromTo 5.83 + #define Meas_endReceiveFromTo 5.84 + #define Meas_startReceiveOfType 5.85 + #define Meas_endReceiveOfType 5.86 + 5.87 +#endif /* MEAS__TURN_ON_LANG_MEAS */ 5.88 + 5.89 +#endif /* */ 5.90 +
6.1 --- a/SSR_PluginFns.c Tue Mar 13 10:04:14 2012 -0700 6.2 +++ b/SSR_PluginFns.c Tue Mar 13 18:30:05 2012 -0700 6.3 @@ -7,7 +7,7 @@ 6.4 #include <stdio.h> 6.5 #include <stdlib.h> 6.6 6.7 -#include "../../C_Libraries/Queue_impl/PrivateQueue.h" 6.8 +#include "Queue_impl/PrivateQueue.h" 6.9 #include "SSR.h" 6.10 #include "SSR_Request_Handlers.h" 6.11 6.12 @@ -25,21 +25,22 @@ 6.13 handleCreate( VMSReqst *req, SlaveVP *requestingPr, SSRSemEnv *semEnv ); 6.14 6.15 6.16 -//============================== Scheduler ================================== 6.17 +//============================== Assigner ================================== 6.18 // 6.19 -/*For SSR, scheduling a slave simply takes the next work-unit off the 6.20 +/*For SSR, assigning a slave simply takes the next work-unit off the 6.21 * ready-to-go work-unit queue and assigns it to the slaveToSched. 6.22 - *If the ready-to-go work-unit queue is empty, then nothing to schedule 6.23 + *If the ready-to-go work-unit queue is empty, then nothing to assign 6.24 * to the slave -- return FALSE to let Master loop know scheduling that 6.25 * slave failed. 6.26 */ 6.27 -char __Scheduler[] = "FIFO Scheduler"; //Gobal variable for name in saved histogram 6.28 - 6.29 SlaveVP * 6.30 -SSR__schedule_slaveVP( void *_semEnv, int coreNum, int slotNum ) 6.31 +SSR__assign_slaveVP( void *_semEnv, int coreNum, SchedSlot *slot ) 6.32 { SlaveVP *schedPr; 6.33 SSRSemEnv *semEnv; 6.34 - 6.35 + int32 slotNum; 6.36 + 6.37 + slotNum = slot->slotIdx; 6.38 + 6.39 semEnv = (SSRSemEnv *)_semEnv; 6.40 6.41 schedPr = readPrivQ( semEnv->readyVPQs[coreNum] ); 6.42 @@ -48,36 +49,36 @@ 6.43 schedPr = semEnv->idlePr[coreNum][slotNum]; 6.44 //things that would normally happen in resume(), but these VPs never go there 6.45 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 6.46 - schedPr->numTimesScheduled++; //Somewhere here! 6.47 + schedPr->numTimesAssigned++; //Somewhere here! 6.48 Unit newu; 6.49 newu.vp = schedPr->slaveID; 6.50 - newu.task = schedPr->numTimesScheduled; 6.51 + newu.task = schedPr->numTimesAssigned; 6.52 addToListOfArrays(Unit,newu,semEnv->unitList); 6.53 6.54 - if (schedPr->numTimesScheduled > 1){ 6.55 + if (schedPr->numTimesAssigned > 1){ 6.56 Dependency newd; 6.57 newd.from_vp = schedPr->slaveID; 6.58 - newd.from_task = schedPr->numTimesScheduled - 1; 6.59 + newd.from_task = schedPr->numTimesAssigned - 1; 6.60 newd.to_vp = schedPr->slaveID; 6.61 - newd.to_task = schedPr->numTimesScheduled; 6.62 + newd.to_task = schedPr->numTimesAssigned; 6.63 addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); 6.64 } 6.65 #endif 6.66 } 6.67 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 6.68 if (schedPr) { 6.69 - //schedPr->numTimesScheduled++; 6.70 + //schedPr->numTimesAssigned++; 6.71 Unit prev_in_slot = semEnv->last_in_slot[coreNum * NUM_SCHED_SLOTS + slotNum]; 6.72 if(prev_in_slot.vp != 0){ 6.73 Dependency newd; 6.74 newd.from_vp = prev_in_slot.vp; 6.75 newd.from_task = prev_in_slot.task; 6.76 newd.to_vp = schedPr->slaveID; 6.77 - newd.to_task = schedPr->numTimesScheduled; 6.78 + newd.to_task = schedPr->numTimesAssigned; 6.79 addToListOfArrays(Dependency,newd,semEnv->hwArcs); 6.80 } 6.81 prev_in_slot.vp = schedPr->slaveID; 6.82 - prev_in_slot.task = schedPr->numTimesScheduled; 6.83 + prev_in_slot.task = schedPr->numTimesAssigned; 6.84 semEnv->last_in_slot[coreNum * NUM_SCHED_SLOTS + slotNum] = prev_in_slot; 6.85 } 6.86 #endif 6.87 @@ -91,7 +92,7 @@ 6.88 * Upon send, check the hash to see if a receive is waiting. 6.89 * Upon receive, check hash to see if a send has already happened. 6.90 * When other is not there, put in. When other is there, the comm. 6.91 - * completes, which means the receiver P gets scheduled and 6.92 + * completes, which means the receiver P gets assigned and 6.93 * picks up right after the receive request. So make the work-unit 6.94 * and put it into the queue of work-units ready to go. 6.95 * Other request is create a new Processor, with the function to run in the 6.96 @@ -194,7 +195,7 @@ 6.97 */ 6.98 SlaveVP * 6.99 SSR__create_procr_helper( TopLevelFnPtr fnPtr, void *initData, 6.100 - SSRSemEnv *semEnv, int32 coreToScheduleOnto ) 6.101 + SSRSemEnv *semEnv, int32 coreToAssignOnto ) 6.102 { SlaveVP *newPr; 6.103 SSRSemData *semData; 6.104 6.105 @@ -215,7 +216,7 @@ 6.106 6.107 #else 6.108 6.109 - if(coreToScheduleOnto < 0 || coreToScheduleOnto >= NUM_CORES ) 6.110 + if(coreToAssignOnto < 0 || coreToAssignOnto >= NUM_CORES ) 6.111 { //out-of-range, so round-robin assignment 6.112 newPr->coreAnimatedBy = semEnv->nextCoreToGetNewPr; 6.113 6.114 @@ -225,7 +226,7 @@ 6.115 semEnv->nextCoreToGetNewPr += 1; 6.116 } 6.117 else //core num in-range, so use it 6.118 - { newPr->coreAnimatedBy = coreToScheduleOnto; 6.119 + { newPr->coreAnimatedBy = coreToAssignOnto; 6.120 } 6.121 #endif 6.122 //======================================================================== 6.123 @@ -243,14 +244,14 @@ 6.124 semReq = VMS_PI__take_sem_reqst_from( req ); 6.125 6.126 newPr = SSR__create_procr_helper( semReq->fnPtr, semReq->initData, semEnv, 6.127 - semReq->coreToScheduleOnto ); 6.128 + semReq->coreToAssignOnto ); 6.129 6.130 DEBUG_Print1(dbgRqstHdlr,"(new VP: %d)\n",newPr->slaveID) 6.131 6.132 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 6.133 Dependency newd; 6.134 newd.from_vp = requestingPr->slaveID; 6.135 - newd.from_task = requestingPr->numTimesScheduled; 6.136 + newd.from_task = requestingPr->numTimesAssigned; 6.137 newd.to_vp = newPr->slaveID; 6.138 newd.to_task = 1; 6.139 //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 6.140 @@ -277,18 +278,18 @@ 6.141 */ 6.142 #endif 6.143 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 6.144 - procr->numTimesScheduled++; //Somewhere here! 6.145 + procr->numTimesAssigned++; //Somewhere here! 6.146 Unit newu; 6.147 newu.vp = procr->slaveID; 6.148 - newu.task = procr->numTimesScheduled; 6.149 + newu.task = procr->numTimesAssigned; 6.150 addToListOfArrays(Unit,newu,semEnv->unitList); 6.151 6.152 - if (procr->numTimesScheduled > 1){ 6.153 + if (procr->numTimesAssigned > 1){ 6.154 Dependency newd; 6.155 newd.from_vp = procr->slaveID; 6.156 - newd.from_task = procr->numTimesScheduled - 1; 6.157 + newd.from_task = procr->numTimesAssigned - 1; 6.158 newd.to_vp = procr->slaveID; 6.159 - newd.to_task = procr->numTimesScheduled; 6.160 + newd.to_task = procr->numTimesAssigned; 6.161 addToListOfArrays(Dependency, newd ,semEnv->ctlDependenciesList); 6.162 } 6.163 #endif
7.1 --- a/SSR_Request_Handlers.c Tue Mar 13 10:04:14 2012 -0700 7.2 +++ b/SSR_Request_Handlers.c Tue Mar 13 18:30:05 2012 -0700 7.3 @@ -129,9 +129,9 @@ 7.4 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.5 Dependency newd; 7.6 newd.from_vp = sendPr->slaveID; 7.7 - newd.from_task = sendPr->numTimesScheduled; 7.8 + newd.from_task = sendPr->numTimesAssigned; 7.9 newd.to_vp = receivePr->slaveID; 7.10 - newd.to_task = receivePr->numTimesScheduled +1; 7.11 + newd.to_task = receivePr->numTimesAssigned +1; 7.12 //(newd,semEnv->commDependenciesList); 7.13 addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); 7.14 int32 groupId = semReq->msgType; 7.15 @@ -143,10 +143,10 @@ 7.16 } 7.17 Unit u; 7.18 u.vp = sendPr->slaveID; 7.19 - u.task = sendPr->numTimesScheduled; 7.20 + u.task = sendPr->numTimesAssigned; 7.21 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders); 7.22 u.vp = receivePr->slaveID; 7.23 - u.task = receivePr->numTimesScheduled +1; 7.24 + u.task = receivePr->numTimesAssigned +1; 7.25 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers); 7.26 #endif 7.27 7.28 @@ -209,9 +209,9 @@ 7.29 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.30 Dependency newd; 7.31 newd.from_vp = sendPr->slaveID; 7.32 - newd.from_task = sendPr->numTimesScheduled; 7.33 + newd.from_task = sendPr->numTimesAssigned; 7.34 newd.to_vp = receivePr->slaveID; 7.35 - newd.to_task = receivePr->numTimesScheduled +1; 7.36 + newd.to_task = receivePr->numTimesAssigned +1; 7.37 //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 7.38 addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); 7.39 #endif 7.40 @@ -318,9 +318,9 @@ 7.41 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.42 Dependency newd; 7.43 newd.from_vp = sendPr->slaveID; 7.44 - newd.from_task = sendPr->numTimesScheduled; 7.45 + newd.from_task = sendPr->numTimesAssigned; 7.46 newd.to_vp = receivePr->slaveID; 7.47 - newd.to_task = receivePr->numTimesScheduled +1; 7.48 + newd.to_task = receivePr->numTimesAssigned +1; 7.49 //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 7.50 addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList); 7.51 int32 groupId = semReq->msgType; 7.52 @@ -332,10 +332,10 @@ 7.53 } 7.54 Unit u; 7.55 u.vp = sendPr->slaveID; 7.56 - u.task = sendPr->numTimesScheduled; 7.57 + u.task = sendPr->numTimesAssigned; 7.58 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders); 7.59 u.vp = receivePr->slaveID; 7.60 - u.task = receivePr->numTimesScheduled +1; 7.61 + u.task = receivePr->numTimesAssigned +1; 7.62 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers); 7.63 #endif 7.64 7.65 @@ -378,9 +378,9 @@ 7.66 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 7.67 Dependency newd; 7.68 newd.from_vp = sendPr->slaveID; 7.69 - newd.from_task = sendPr->numTimesScheduled; 7.70 + newd.from_task = sendPr->numTimesAssigned; 7.71 newd.to_vp = receivePr->slaveID; 7.72 - newd.to_task = receivePr->numTimesScheduled +1; 7.73 + newd.to_task = receivePr->numTimesAssigned +1; 7.74 //addToListOfArraysDependency(newd,semEnv->commDependenciesList); 7.75 addToListOfArrays(Dependency,newd,semEnv->commDependenciesList); 7.76 #endif
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/SSR_asm.s Tue Mar 13 18:30:05 2012 -0700 8.3 @@ -0,0 +1,21 @@ 8.4 + 8.5 +//Assembly code takes the return addr off the stack and saves 8.6 +// into the singleton. The first field in the singleton is the 8.7 +// "endInstrAddr" field, and the return addr is at 0x4(%ebp) 8.8 +.globl asm_save_ret_to_singleton 8.9 +asm_save_ret_to_singleton: 8.10 + movq 0x8(%rbp), %rax #get ret address, ebp is the same as in the calling function 8.11 + movq %rax, (%rdi) #write ret addr to endInstrAddr field 8.12 + ret 8.13 + 8.14 + 8.15 +//Assembly code changes the return addr on the stack to the one 8.16 +// saved into the singleton by the end-singleton-fn 8.17 +//The stack's return addr is at 0x4(%%ebp) 8.18 +.globl asm_write_ret_from_singleton 8.19 +asm_write_ret_from_singleton: 8.20 + movq (%rdi), %rax #get endInstrAddr field 8.21 + movq %rax, 0x8(%rbp) #write return addr to the stack of the caller 8.22 + ret 8.23 + 8.24 +
9.1 --- a/SSR_lib.c Tue Mar 13 10:04:14 2012 -0700 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,807 +0,0 @@ 9.4 -/* 9.5 - * Copyright 2010 OpenSourceCodeStewardshipFoundation 9.6 - * 9.7 - * Licensed under BSD 9.8 - */ 9.9 - 9.10 -#include <stdio.h> 9.11 -#include <stdlib.h> 9.12 -#include <malloc.h> 9.13 - 9.14 -#include "../VMS_impl/VMS.h" 9.15 -#include "SSR.h" 9.16 -#include "../../C_Libraries/Queue_impl/PrivateQueue.h" 9.17 -#include "../../C_Libraries/Hash_impl/PrivateHash.h" 9.18 -#include "SSR.h" 9.19 -#include "SSR_Counter_Recording.h" 9.20 - 9.21 -//========================================================================== 9.22 - 9.23 -void 9.24 -SSR__init(); 9.25 - 9.26 -void 9.27 -SSR__init_Seq(); 9.28 - 9.29 -void 9.30 -SSR__init_Helper(); 9.31 -//========================================================================== 9.32 - 9.33 - 9.34 -/*TODO: Q: dealing with library f()s and DKU vs WT vs FoR 9.35 - * (still want to do FoR, with time-lines as syntax, could be super cool) 9.36 - * A: thinking pin the coreCtlrs for all of BLIS -- let Master arbitrate 9.37 - * among library, DKU, WT, FoR -- all the patterns in terms of virtual 9.38 - * processors (or equivalently work-units), so Master picks which virt procr 9.39 - * from which portions of app (DKU, WT, FoR) onto which sched slots 9.40 - *Might even do hierarchy of masters -- group of sched slots for each core 9.41 - * has its own master, that keeps generated work local 9.42 - * single-reader-single-writer sync everywhere -- no atomic primitives 9.43 - * Might have the different schedulers talk to each other, to negotiate 9.44 - * larger-grain sharing of resources, according to predicted critical 9.45 - * path, and expansion of work 9.46 - */ 9.47 - 9.48 - 9.49 - 9.50 -//=========================================================================== 9.51 - 9.52 - 9.53 -/*These are the library functions *called in the application* 9.54 - * 9.55 - *There's a pattern for the outside sequential code to interact with the 9.56 - * VMS_HW code. 9.57 - *The VMS_HW system is inside a boundary.. every SSR system is in its 9.58 - * own directory that contains the functions for each of the processor types. 9.59 - * One of the processor types is the "seed" processor that starts the 9.60 - * cascade of creating all the processors that do the work. 9.61 - *So, in the directory is a file called "EntryPoint.c" that contains the 9.62 - * function, named appropriately to the work performed, that the outside 9.63 - * sequential code calls. This function follows a pattern: 9.64 - *1) it calls SSR__init() 9.65 - *2) it creates the initial data for the seed processor, which is passed 9.66 - * in to the function 9.67 - *3) it creates the seed SSR processor, with the data to start it with. 9.68 - *4) it calls startSSRThenWaitUntilWorkDone 9.69 - *5) it gets the returnValue from the transfer struc and returns that 9.70 - * from the function 9.71 - * 9.72 - *For now, a new SSR system has to be created via SSR__init every 9.73 - * time an entry point function is called -- later, might add letting the 9.74 - * SSR system be created once, and let all the entry points just reuse 9.75 - * it -- want to be as simple as possible now, and see by using what makes 9.76 - * sense for later.. 9.77 - */ 9.78 - 9.79 - 9.80 - 9.81 -//=========================================================================== 9.82 - 9.83 -/*This is the "border crossing" function -- the thing that crosses from the 9.84 - * outside world, into the VMS_HW world. It initializes and starts up the 9.85 - * VMS system, then creates one processor from the specified function and 9.86 - * puts it into the readyQ. From that point, that one function is resp. 9.87 - * for creating all the other processors, that then create others, and so 9.88 - * forth. 9.89 - *When all the processors, including the seed, have dissipated, then this 9.90 - * function returns. The results will have been written by side-effect via 9.91 - * pointers read from, or written into initData. 9.92 - * 9.93 - *NOTE: no Threads should exist in the outside program that might touch 9.94 - * any of the data reachable from initData passed in to here 9.95 - */ 9.96 -void 9.97 -SSR__create_seed_procr_and_do_work( TopLevelFnPtr fnPtr, void *initData ) 9.98 - { SSRSemEnv *semEnv; 9.99 - SlaveVP *seedPr; 9.100 - 9.101 - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 9.102 - SSR__init_Seq(); //debug sequential exe 9.103 - #else 9.104 - SSR__init(); //normal multi-thd 9.105 - #endif 9.106 - semEnv = _VMSMasterEnv->semanticEnv; 9.107 - 9.108 - //SSR starts with one processor, which is put into initial environ, 9.109 - // and which then calls create() to create more, thereby expanding work 9.110 - seedPr = SSR__create_procr_helper( fnPtr, initData, 9.111 - semEnv, semEnv->nextCoreToGetNewPr++ ); 9.112 - 9.113 - resume_slaveVP( seedPr, semEnv ); 9.114 - 9.115 - #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 9.116 - VMS_SS__start_the_work_then_wait_until_done_Seq(); //debug sequential exe 9.117 - #else 9.118 - VMS_SS__start_the_work_then_wait_until_done(); //normal multi-thd 9.119 - #endif 9.120 - 9.121 - SSR__cleanup_after_shutdown(); 9.122 - } 9.123 - 9.124 - 9.125 -int32 9.126 -SSR__giveMinWorkUnitCycles( float32 percentOverhead ) 9.127 - { 9.128 - return MIN_WORK_UNIT_CYCLES; 9.129 - } 9.130 - 9.131 -int32 9.132 -SSR__giveIdealNumWorkUnits() 9.133 - { 9.134 - return NUM_SCHED_SLOTS * NUM_CORES; 9.135 - } 9.136 - 9.137 -int32 9.138 -SSR__give_number_of_cores_to_schedule_onto() 9.139 - { 9.140 - return NUM_CORES; 9.141 - } 9.142 - 9.143 -/*For now, use TSC -- later, make these two macros with assembly that first 9.144 - * saves jump point, and second jumps back several times to get reliable time 9.145 - */ 9.146 -void 9.147 -SSR__start_primitive() 9.148 - { saveLowTimeStampCountInto( ((SSRSemEnv *)(_VMSMasterEnv->semanticEnv))-> 9.149 - primitiveStartTime ); 9.150 - } 9.151 - 9.152 -/*Just quick and dirty for now -- make reliable later 9.153 - * will want this to jump back several times -- to be sure cache is warm 9.154 - * because don't want comm time included in calc-time measurement -- and 9.155 - * also to throw out any "weird" values due to OS interrupt or TSC rollover 9.156 - */ 9.157 -int32 9.158 -SSR__end_primitive_and_give_cycles() 9.159 - { int32 endTime, startTime; 9.160 - //TODO: fix by repeating time-measurement 9.161 - saveLowTimeStampCountInto( endTime ); 9.162 - startTime =((SSRSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime; 9.163 - return (endTime - startTime); 9.164 - } 9.165 - 9.166 -//=========================================================================== 9.167 - 9.168 -/*Initializes all the data-structures for a SSR system -- but doesn't 9.169 - * start it running yet! 9.170 - * 9.171 - *This runs in the main thread -- before VMS starts up 9.172 - * 9.173 - *This sets up the semantic layer over the VMS system 9.174 - * 9.175 - *First, calls VMS_Setup, then creates own environment, making it ready 9.176 - * for creating the seed processor and then starting the work. 9.177 - */ 9.178 -void 9.179 -SSR__init() 9.180 - { 9.181 - VMS_SS__init(); 9.182 - //masterEnv, a global var, now is partially set up by init_VMS 9.183 - // after this, have VMS_int__malloc and VMS_int__free available 9.184 - 9.185 - SSR__init_Helper(); 9.186 - } 9.187 - 9.188 -#ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE 9.189 -void 9.190 -SSR__init_Seq() 9.191 - { 9.192 - VMS_SS__init_Seq(); 9.193 - flushRegisters(); 9.194 - //masterEnv, a global var, now is partially set up by init_VMS 9.195 - 9.196 - SSR__init_Helper(); 9.197 - } 9.198 -#endif 9.199 - 9.200 -void idle_fn(void* data, SlaveVP *animatingSlv){ 9.201 - while(1){ 9.202 - VMS_int__suspend_slaveVP_and_send_req(animatingSlv); 9.203 - } 9.204 -} 9.205 - 9.206 -void 9.207 -SSR__init_Helper() 9.208 - { SSRSemEnv *semanticEnv; 9.209 - PrivQueueStruc **readyVPQs; 9.210 - int coreIdx, i, j; 9.211 - 9.212 - //Hook up the semantic layer's plug-ins to the Master virt procr 9.213 - _VMSMasterEnv->requestHandler = &SSR__Request_Handler; 9.214 - _VMSMasterEnv->slaveAssigner = &SSR__schedule_slaveVP; 9.215 - #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 9.216 - _VMSMasterEnv->counterHandler = &SSR__counter_handler; 9.217 - #endif 9.218 - 9.219 - //create the semantic layer's environment (all its data) and add to 9.220 - // the master environment 9.221 - semanticEnv = VMS_int__malloc( sizeof( SSRSemEnv ) ); 9.222 - _VMSMasterEnv->semanticEnv = semanticEnv; 9.223 - 9.224 - #ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 9.225 - SSR__init_counter_data_structs(); 9.226 - #endif 9.227 - for(i=0;i<NUM_CORES;++i){ 9.228 - for(j=0;j<NUM_SCHED_SLOTS;++j){ 9.229 - semanticEnv->idlePr[i][j] = VMS_int__create_slaveVP(&idle_fn,NULL); 9.230 - semanticEnv->idlePr[i][j]->coreAnimatedBy = i; 9.231 - } 9.232 - } 9.233 - 9.234 - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 9.235 - semanticEnv->unitList = makeListOfArrays(sizeof(Unit),128); 9.236 - semanticEnv->ctlDependenciesList = makeListOfArrays(sizeof(Dependency),128); 9.237 - semanticEnv->commDependenciesList = makeListOfArrays(sizeof(Dependency),128); 9.238 - semanticEnv->dynDependenciesList = makeListOfArrays(sizeof(Dependency),128); 9.239 - semanticEnv->ntonGroupsInfo = makePrivDynArrayOfSize((void***)&(semanticEnv->ntonGroups),8); 9.240 - 9.241 - semanticEnv->hwArcs = makeListOfArrays(sizeof(Dependency),128); 9.242 - memset(semanticEnv->last_in_slot,0,sizeof(NUM_CORES * NUM_SCHED_SLOTS * sizeof(Unit))); 9.243 - #endif 9.244 - 9.245 - //create the ready queue, hash tables used for pairing send to receive 9.246 - // and so forth 9.247 - //TODO: add hash tables for pairing sends with receives, and 9.248 - // initialize the data ownership system 9.249 - readyVPQs = VMS_int__malloc( NUM_CORES * sizeof(PrivQueueStruc *) ); 9.250 - 9.251 - for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 9.252 - { 9.253 - readyVPQs[ coreIdx ] = makeVMSQ(); 9.254 - } 9.255 - 9.256 - semanticEnv->readyVPQs = readyVPQs; 9.257 - 9.258 - semanticEnv->nextCoreToGetNewPr = 0; 9.259 - semanticEnv->numSlaveVP = 0; 9.260 - 9.261 - semanticEnv->commHashTbl = makeHashTable( 1<<16, &VMS_int__free );//start big 9.262 - 9.263 - //TODO: bug -- turn these arrays into dyn arrays to eliminate limit 9.264 - //semanticEnv->singletonHasBeenExecutedFlags = makeDynArrayInfo( ); 9.265 - //semanticEnv->transactionStrucs = makeDynArrayInfo( ); 9.266 - for( i = 0; i < NUM_STRUCS_IN_SEM_ENV; i++ ) 9.267 - { 9.268 - semanticEnv->fnSingletons[i].endInstrAddr = NULL; 9.269 - semanticEnv->fnSingletons[i].hasBeenStarted = FALSE; 9.270 - semanticEnv->fnSingletons[i].hasFinished = FALSE; 9.271 - semanticEnv->fnSingletons[i].waitQ = makeVMSQ(); 9.272 - semanticEnv->transactionStrucs[i].waitingVPQ = makeVMSQ(); 9.273 - } 9.274 - } 9.275 - 9.276 - 9.277 -/*Frees any memory allocated by SSR__init() then calls VMS_int__shutdown 9.278 - */ 9.279 -void 9.280 -SSR__cleanup_after_shutdown() 9.281 - { SSRSemEnv *semanticEnv; 9.282 - 9.283 - semanticEnv = _VMSMasterEnv->semanticEnv; 9.284 - 9.285 - #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC 9.286 - //UCC 9.287 - FILE* output; 9.288 - int n; 9.289 - char filename[255]; 9.290 - for(n=0;n<255;n++) 9.291 - { 9.292 - sprintf(filename, "./counters/UCC.%d",n); 9.293 - output = fopen(filename,"r"); 9.294 - if(output) 9.295 - { 9.296 - fclose(output); 9.297 - }else{ 9.298 - break; 9.299 - } 9.300 - } 9.301 - if(n<255){ 9.302 - printf("Saving UCC to File: %s ...\n", filename); 9.303 - output = fopen(filename,"w+"); 9.304 - if(output!=NULL){ 9.305 - set_dependency_file(output); 9.306 - //fprintf(output,"digraph Dependencies {\n"); 9.307 - //set_dot_file(output); 9.308 - //FIXME: first line still depends on counters being enabled, replace w/ unit struct! 9.309 - //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info ); 9.310 - forAllInListOfArraysDo(semanticEnv->unitList, &print_unit_to_file); 9.311 - forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); 9.312 - forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); 9.313 - forAllInDynArrayDo(semanticEnv->ntonGroupsInfo,&print_nton_to_file); 9.314 - //fprintf(output,"}\n"); 9.315 - fflush(output); 9.316 - 9.317 - } else 9.318 - printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 9.319 - } else { 9.320 - printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 9.321 - } 9.322 - //Loop Graph 9.323 - for(n=0;n<255;n++) 9.324 - { 9.325 - sprintf(filename, "./counters/LoopGraph.%d",n); 9.326 - output = fopen(filename,"r"); 9.327 - if(output) 9.328 - { 9.329 - fclose(output); 9.330 - }else{ 9.331 - break; 9.332 - } 9.333 - } 9.334 - if(n<255){ 9.335 - printf("Saving LoopGraph to File: %s ...\n", filename); 9.336 - output = fopen(filename,"w+"); 9.337 - if(output!=NULL){ 9.338 - set_dependency_file(output); 9.339 - //fprintf(output,"digraph Dependencies {\n"); 9.340 - //set_dot_file(output); 9.341 - //FIXME: first line still depends on counters being enabled, replace w/ unit struct! 9.342 - //forAllInDynArrayDo(_VMSMasterEnv->counter_history_array_info, &print_dot_node_info ); 9.343 - forAllInListOfArraysDo( semanticEnv->unitList, &print_unit_to_file ); 9.344 - forAllInListOfArraysDo( semanticEnv->commDependenciesList, &print_comm_dependency_to_file ); 9.345 - forAllInListOfArraysDo( semanticEnv->ctlDependenciesList, &print_ctl_dependency_to_file ); 9.346 - forAllInListOfArraysDo( semanticEnv->dynDependenciesList, &print_dyn_dependency_to_file ); 9.347 - forAllInListOfArraysDo( semanticEnv->hwArcs, &print_hw_dependency_to_file ); 9.348 - //fprintf(output,"}\n"); 9.349 - fflush(output); 9.350 - 9.351 - } else 9.352 - printf("Opening LoopGraph file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 9.353 - } else { 9.354 - printf("Could not open LoopGraph file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 9.355 - } 9.356 - 9.357 - 9.358 - freeListOfArrays(semanticEnv->unitList); 9.359 - freeListOfArrays(semanticEnv->commDependenciesList); 9.360 - freeListOfArrays(semanticEnv->ctlDependenciesList); 9.361 - freeListOfArrays(semanticEnv->dynDependenciesList); 9.362 - 9.363 - #endif 9.364 -#ifdef HOLISTIC__TURN_ON_PERF_COUNTERS 9.365 - for(n=0;n<255;n++) 9.366 - { 9.367 - sprintf(filename, "./counters/Counters.%d.csv",n); 9.368 - output = fopen(filename,"r"); 9.369 - if(output) 9.370 - { 9.371 - fclose(output); 9.372 - }else{ 9.373 - break; 9.374 - } 9.375 - } 9.376 - if(n<255){ 9.377 - printf("Saving Counter measurements to File: %s ...\n", filename); 9.378 - output = fopen(filename,"w+"); 9.379 - if(output!=NULL){ 9.380 - set_counter_file(output); 9.381 - int i; 9.382 - for(i=0;i<NUM_CORES;i++){ 9.383 - forAllInListOfArraysDo( semanticEnv->counterList[i], &print_counter_events_to_file ); 9.384 - fflush(output); 9.385 - } 9.386 - 9.387 - } else 9.388 - printf("Opening UCC file failed. Please check that folder \"counters\" exists in run directory and has write permission.\n"); 9.389 - } else { 9.390 - printf("Could not open UCC file, please clean \"counters\" folder. (Must contain less than 255 files.)\n"); 9.391 - } 9.392 - 9.393 -#endif 9.394 -/* It's all allocated inside VMS's big chunk -- that's about to be freed, so 9.395 - * nothing to do here 9.396 - 9.397 - 9.398 - for( coreIdx = 0; coreIdx < NUM_CORES; coreIdx++ ) 9.399 - { 9.400 - VMS_int__free( semanticEnv->readyVPQs[coreIdx]->startOfData ); 9.401 - VMS_int__free( semanticEnv->readyVPQs[coreIdx] ); 9.402 - } 9.403 - VMS_int__free( semanticEnv->readyVPQs ); 9.404 - 9.405 - freeHashTable( semanticEnv->commHashTbl ); 9.406 - VMS_int__free( _VMSMasterEnv->semanticEnv ); 9.407 - */ 9.408 - VMS_SS__cleanup_at_end_of_shutdown(); 9.409 - } 9.410 - 9.411 - 9.412 -//=========================================================================== 9.413 - 9.414 -/* 9.415 - */ 9.416 - SlaveVP * 9.417 -SSR__create_procr_with( TopLevelFnPtr fnPtr, void *initData, 9.418 - SlaveVP *creatingPr ) 9.419 - { SSRSemReq reqData; 9.420 - 9.421 - //the semantic request data is on the stack and disappears when this 9.422 - // call returns -- it's guaranteed to remain in the VP's stack for as 9.423 - // long as the VP is suspended. 9.424 - reqData.reqType = 0; //know type because in a VMS create req 9.425 - reqData.coreToScheduleOnto = -1; //means round-robin schedule 9.426 - reqData.fnPtr = fnPtr; 9.427 - reqData.initData = initData; 9.428 - reqData.sendPr = creatingPr; 9.429 - 9.430 - VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); 9.431 - 9.432 - return creatingPr->dataRetFromReq; 9.433 - } 9.434 - 9.435 - SlaveVP * 9.436 -SSR__create_procr_with_affinity( TopLevelFnPtr fnPtr, void *initData, 9.437 - SlaveVP *creatingPr, int32 coreToScheduleOnto ) 9.438 - { SSRSemReq reqData; 9.439 - 9.440 - //the semantic request data is on the stack and disappears when this 9.441 - // call returns -- it's guaranteed to remain in the VP's stack for as 9.442 - // long as the VP is suspended. 9.443 - reqData.reqType = 0; //know type because in a VMS create req 9.444 - reqData.coreToScheduleOnto = coreToScheduleOnto; 9.445 - reqData.fnPtr = fnPtr; 9.446 - reqData.initData = initData; 9.447 - reqData.sendPr = creatingPr; 9.448 - 9.449 - VMS_WL__send_create_slaveVP_req( &reqData, creatingPr ); 9.450 - 9.451 - return creatingPr->dataRetFromReq; 9.452 - } 9.453 - 9.454 - 9.455 - void 9.456 -SSR__dissipate_procr( SlaveVP *procrToDissipate ) 9.457 - { 9.458 - VMS_WL__send_dissipate_req( procrToDissipate ); 9.459 - } 9.460 - 9.461 - 9.462 -//=========================================================================== 9.463 - 9.464 -void * 9.465 -SSR__malloc_to( int32 sizeToMalloc, SlaveVP *owningPr ) 9.466 - { SSRSemReq reqData; 9.467 - 9.468 - reqData.reqType = malloc_req; 9.469 - reqData.sendPr = owningPr; 9.470 - reqData.sizeToMalloc = sizeToMalloc; 9.471 - 9.472 - VMS_WL__send_sem_request( &reqData, owningPr ); 9.473 - 9.474 - return owningPr->dataRetFromReq; 9.475 - } 9.476 - 9.477 - 9.478 -/*Sends request to Master, which does the work of freeing 9.479 - */ 9.480 -void 9.481 -SSR__free( void *ptrToFree, SlaveVP *owningPr ) 9.482 - { SSRSemReq reqData; 9.483 - 9.484 - reqData.reqType = free_req; 9.485 - reqData.sendPr = owningPr; 9.486 - reqData.ptrToFree = ptrToFree; 9.487 - 9.488 - VMS_WL__send_sem_request( &reqData, owningPr ); 9.489 - } 9.490 - 9.491 - 9.492 -void 9.493 -SSR__transfer_ownership_of_from_to( void *data, SlaveVP *oldOwnerSlv, 9.494 - SlaveVP *newOwnerPr ) 9.495 - { 9.496 - //TODO: put in the ownership system that automatically frees when no 9.497 - // owners of data left -- will need keeper for keeping data around when 9.498 - // future created processors might need it but don't exist yet 9.499 - } 9.500 - 9.501 - 9.502 -void 9.503 -SSR__add_ownership_by_to( SlaveVP *newOwnerSlv, void *data ) 9.504 - { 9.505 - 9.506 - } 9.507 - 9.508 - 9.509 -void 9.510 -SSR__remove_ownership_by_from( SlaveVP *loserSlv, void *dataLosing ) 9.511 - { 9.512 - 9.513 - } 9.514 - 9.515 - 9.516 -/*Causes the SSR system to remove internal ownership, so data won't be 9.517 - * freed when SSR shuts down, and will persist in the external program. 9.518 - * 9.519 - *Must be called from the processor that currently owns the data. 9.520 - * 9.521 - *IMPL: Transferring ownership touches two different virtual processor's 9.522 - * state -- which means it has to be done carefully -- the VMS rules for 9.523 - * semantic layers say that a work-unit is only allowed to touch the 9.524 - * virtual processor it is part of, and that only a single work-unit per 9.525 - * virtual processor be scheduled to a slave at a time. So, this has to 9.526 - * modify the virtual processor that owns the work-unit that called this 9.527 - * function, then create a request to have the other processor modified. 9.528 - *However, in this case, the TO processor is the outside, and transfers 9.529 - * are only allowed to be called by the giver-upper, so can mark caller of 9.530 - * this function as no longer owner, and return -- done. 9.531 - */ 9.532 -void 9.533 -SSR__transfer_ownership_to_outside( void *data ) 9.534 - { 9.535 - //TODO: removeAllOwnersFrom( data ); 9.536 - } 9.537 - 9.538 - 9.539 -//=========================================================================== 9.540 - 9.541 -void 9.542 -SSR__send_of_type_to( SlaveVP *sendPr, void *msg, const int type, 9.543 - SlaveVP *receivePr) 9.544 - { SSRSemReq reqData; 9.545 - 9.546 - reqData.receivePr = receivePr; 9.547 - reqData.sendPr = sendPr; 9.548 - reqData.reqType = send_type; 9.549 - reqData.msgType = type; 9.550 - reqData.msg = msg; 9.551 - reqData.nextReqInHashEntry = NULL; 9.552 - 9.553 - //On ownership -- remove inside the send and let ownership sit in limbo 9.554 - // as a potential in an entry in the hash table, when this receive msg 9.555 - // gets paired to a send, the ownership gets added to the receivePr -- 9.556 - // the next work-unit in the receivePr's trace will have ownership. 9.557 - VMS_WL__send_sem_request( &reqData, sendPr ); 9.558 - 9.559 - //When come back from suspend, no longer own data reachable from msg 9.560 - //TODO: release ownership here 9.561 - } 9.562 - 9.563 -void 9.564 -SSR__send_from_to( void *msg, SlaveVP *sendPr, SlaveVP *receivePr ) 9.565 - { SSRSemReq reqData; 9.566 - 9.567 - //hash on the receiver, 'cause always know it, but sometimes want to 9.568 - // receive from anonymous sender 9.569 - 9.570 - reqData.receivePr = receivePr; 9.571 - reqData.sendPr = sendPr; 9.572 - reqData.reqType = send_from_to; 9.573 - reqData.msg = msg; 9.574 - reqData.nextReqInHashEntry = NULL; 9.575 - 9.576 - VMS_WL__send_sem_request( &reqData, sendPr ); 9.577 - } 9.578 - 9.579 - 9.580 -//=========================================================================== 9.581 - 9.582 -void * 9.583 -SSR__receive_any_to( SlaveVP *receivePr ) 9.584 - { 9.585 - 9.586 - } 9.587 - 9.588 -void * 9.589 -SSR__receive_type_to( const int type, SlaveVP *receivePr ) 9.590 - { 9.591 - SSRSemReq reqData; 9.592 - 9.593 - reqData.receivePr = receivePr; 9.594 - reqData.reqType = receive_type; 9.595 - reqData.msgType = type; 9.596 - reqData.nextReqInHashEntry = NULL; 9.597 - 9.598 - VMS_WL__send_sem_request( &reqData, receivePr ); 9.599 - 9.600 - return receivePr->dataRetFromReq; 9.601 - } 9.602 - 9.603 - 9.604 - 9.605 -/*Call this at point receiving virt pr wants in-coming data. 9.606 - * 9.607 - *The reason receivePr must call this is that it modifies the receivPr 9.608 - * loc structure directly -- and the VMS rules state a virtual processor 9.609 - * loc structure can only be modified by itself. 9.610 - */ 9.611 -void * 9.612 -SSR__receive_from_to( SlaveVP *sendPr, SlaveVP *receivePr ) 9.613 - { SSRSemReq reqData; 9.614 - 9.615 - //hash on the receiver, 'cause always know it, but sometimes want to 9.616 - // receive from anonymous sender 9.617 - 9.618 - reqData.receivePr = receivePr; 9.619 - reqData.sendPr = sendPr; 9.620 - reqData.reqType = receive_from_to; 9.621 - reqData.nextReqInHashEntry = NULL; 9.622 - 9.623 - VMS_WL__send_sem_request( &reqData, receivePr ); 9.624 - 9.625 - return receivePr->dataRetFromReq; 9.626 - } 9.627 - 9.628 - 9.629 -//=========================================================================== 9.630 -// 9.631 -/*A function singleton is a function whose body executes exactly once, on a 9.632 - * single core, no matter how many times the fuction is called and no 9.633 - * matter how many cores or the timing of cores calling it. 9.634 - * 9.635 - *A data singleton is a ticket attached to data. That ticket can be used 9.636 - * to get the data through the function exactly once, no matter how many 9.637 - * times the data is given to the function, and no matter the timing of 9.638 - * trying to get the data through from different cores. 9.639 - */ 9.640 - 9.641 -/*asm function declarations*/ 9.642 -void asm_save_ret_to_singleton(SSRSingleton *singletonPtrAddr); 9.643 -void asm_write_ret_from_singleton(SSRSingleton *singletonPtrAddr); 9.644 - 9.645 -/*Fn singleton uses ID as index into array of singleton structs held in the 9.646 - * semantic environment. 9.647 - */ 9.648 -void 9.649 -SSR__start_fn_singleton( int32 singletonID, SlaveVP *animPr ) 9.650 - { 9.651 - SSRSemReq reqData; 9.652 - 9.653 - // 9.654 - reqData.reqType = singleton_fn_start; 9.655 - reqData.singletonID = singletonID; 9.656 - 9.657 - VMS_WL__send_sem_request( &reqData, animPr ); 9.658 - if( animPr->dataRetFromReq ) //will be 0 or addr of label in end singleton 9.659 - { 9.660 - SSRSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); 9.661 - asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 9.662 - } 9.663 - } 9.664 - 9.665 -/*Data singleton hands addr of loc holding a pointer to a singleton struct. 9.666 - * The start_data_singleton makes the structure and puts its addr into the 9.667 - * location. 9.668 - */ 9.669 -void 9.670 -SSR__start_data_singleton( SSRSingleton **singletonAddr, SlaveVP *animPr ) 9.671 - { 9.672 - SSRSemReq reqData; 9.673 - 9.674 - if( *singletonAddr && (*singletonAddr)->hasFinished ) 9.675 - goto JmpToEndSingleton; 9.676 - 9.677 - reqData.reqType = singleton_data_start; 9.678 - reqData.singletonPtrAddr = singletonAddr; 9.679 - 9.680 - VMS_WL__send_sem_request( &reqData, animPr ); 9.681 - if( animPr->dataRetFromReq ) //either 0 or end singleton's return addr 9.682 - { //Assembly code changes the return addr on the stack to the one 9.683 - // saved into the singleton by the end-singleton-fn 9.684 - //The return addr is at 0x4(%%ebp) 9.685 - JmpToEndSingleton: 9.686 - asm_write_ret_from_singleton(*singletonAddr); 9.687 - } 9.688 - //now, simply return 9.689 - //will exit either from the start singleton call or the end-singleton call 9.690 - } 9.691 - 9.692 -/*Uses ID as index into array of flags. If flag already set, resumes from 9.693 - * end-label. Else, sets flag and resumes normally. 9.694 - * 9.695 - *Note, this call cannot be inlined because the instr addr at the label 9.696 - * inside is shared by all invocations of a given singleton ID. 9.697 - */ 9.698 -void 9.699 -SSR__end_fn_singleton( int32 singletonID, SlaveVP *animPr ) 9.700 - { 9.701 - SSRSemReq reqData; 9.702 - 9.703 - //don't need this addr until after at least one singleton has reached 9.704 - // this function 9.705 - SSRSemEnv *semEnv = VMS_int__give_sem_env_for( animPr ); 9.706 - asm_write_ret_from_singleton(&(semEnv->fnSingletons[ singletonID])); 9.707 - 9.708 - reqData.reqType = singleton_fn_end; 9.709 - reqData.singletonID = singletonID; 9.710 - 9.711 - VMS_WL__send_sem_request( &reqData, animPr ); 9.712 - 9.713 -EndSingletonInstrAddr: 9.714 - return; 9.715 - } 9.716 - 9.717 -void 9.718 -SSR__end_data_singleton( SSRSingleton **singletonPtrAddr, SlaveVP *animPr ) 9.719 - { 9.720 - SSRSemReq reqData; 9.721 - 9.722 - //don't need this addr until after singleton struct has reached 9.723 - // this function for first time 9.724 - //do assembly that saves the return addr of this fn call into the 9.725 - // data singleton -- that data-singleton can only be given to exactly 9.726 - // one instance in the code of this function. However, can use this 9.727 - // function in different places for different data-singletons. 9.728 -// (*(singletonAddr))->endInstrAddr = &&EndDataSingletonInstrAddr; 9.729 - 9.730 - 9.731 - asm_save_ret_to_singleton(*singletonPtrAddr); 9.732 - 9.733 - reqData.reqType = singleton_data_end; 9.734 - reqData.singletonPtrAddr = singletonPtrAddr; 9.735 - 9.736 - VMS_WL__send_sem_request( &reqData, animPr ); 9.737 - } 9.738 - 9.739 -/*This executes the function in the masterVP, so it executes in isolation 9.740 - * from any other copies -- only one copy of the function can ever execute 9.741 - * at a time. 9.742 - * 9.743 - *It suspends to the master, and the request handler takes the function 9.744 - * pointer out of the request and calls it, then resumes the VP. 9.745 - *Only very short functions should be called this way -- for longer-running 9.746 - * isolation, use transaction-start and transaction-end, which run the code 9.747 - * between as work-code. 9.748 - */ 9.749 -void 9.750 -SSR__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster, 9.751 - void *data, SlaveVP *animPr ) 9.752 - { 9.753 - SSRSemReq reqData; 9.754 - 9.755 - // 9.756 - reqData.reqType = atomic; 9.757 - reqData.fnToExecInMaster = ptrToFnToExecInMaster; 9.758 - reqData.dataForFn = data; 9.759 - 9.760 - VMS_WL__send_sem_request( &reqData, animPr ); 9.761 - } 9.762 - 9.763 - 9.764 -/*This suspends to the master. 9.765 - *First, it looks at the VP's data, to see the highest transactionID that VP 9.766 - * already has entered. If the current ID is not larger, it throws an 9.767 - * exception stating a bug in the code. Otherwise it puts the current ID 9.768 - * there, and adds the ID to a linked list of IDs entered -- the list is 9.769 - * used to check that exits are properly ordered. 9.770 - *Next it is uses transactionID as index into an array of transaction 9.771 - * structures. 9.772 - *If the "VP_currently_executing" field is non-null, then put requesting VP 9.773 - * into queue in the struct. (At some point a holder will request 9.774 - * end-transaction, which will take this VP from the queue and resume it.) 9.775 - *If NULL, then write requesting into the field and resume. 9.776 - */ 9.777 -void 9.778 -SSR__start_transaction( int32 transactionID, SlaveVP *animPr ) 9.779 - { 9.780 - SSRSemReq reqData; 9.781 - 9.782 - // 9.783 - reqData.sendPr = animPr; 9.784 - reqData.reqType = trans_start; 9.785 - reqData.transID = transactionID; 9.786 - 9.787 - VMS_WL__send_sem_request( &reqData, animPr ); 9.788 - } 9.789 - 9.790 -/*This suspends to the master, then uses transactionID as index into an 9.791 - * array of transaction structures. 9.792 - *It looks at VP_currently_executing to be sure it's same as requesting VP. 9.793 - * If different, throws an exception, stating there's a bug in the code. 9.794 - *Next it looks at the queue in the structure. 9.795 - *If it's empty, it sets VP_currently_executing field to NULL and resumes. 9.796 - *If something in, gets it, sets VP_currently_executing to that VP, then 9.797 - * resumes both. 9.798 - */ 9.799 -void 9.800 -SSR__end_transaction( int32 transactionID, SlaveVP *animPr ) 9.801 - { 9.802 - SSRSemReq reqData; 9.803 - 9.804 - // 9.805 - reqData.sendPr = animPr; 9.806 - reqData.reqType = trans_end; 9.807 - reqData.transID = transactionID; 9.808 - 9.809 - VMS_WL__send_sem_request( &reqData, animPr ); 9.810 - }
10.1 --- a/dependency.c Tue Mar 13 10:04:14 2012 -0700 10.2 +++ b/dependency.c Tue Mar 13 18:30:05 2012 -0700 10.3 @@ -1,5 +1,5 @@ 10.4 #include "dependency.h" 10.5 -#include "../VMS_impl/VMS.h" 10.6 +#include "VMS_impl/VMS.h" 10.7 10.8 Dependency* new_dependency(int from_vp, int from_task, int to_vp, int to_task){ 10.9 Dependency* newDep = (Dependency*) VMS_int__malloc(sizeof(Dependency));
