Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > SSR_impls > SSR__MC_shared_impl
changeset 1:06ca89bafbb8
1st working version -- as far as can tell due to SEH bugs
| author | Me |
|---|---|
| date | Wed, 07 Jul 2010 13:15:29 -0700 |
| parents | 35b53e6de714 |
| children | f6b960f40005 |
| files | VMSHW.h VMSHW_PluginFns.c VMSHW_Request_Handlers.c VMSHW_Request_Handlers.h VMSHW_lib.c |
| diffstat | 5 files changed, 782 insertions(+), 252 deletions(-) [+] |
line diff
1.1 --- a/VMSHW.h Sat May 22 19:33:11 2010 -0700 1.2 +++ b/VMSHW.h Wed Jul 07 13:15:29 2010 -0700 1.3 @@ -9,38 +9,117 @@ 1.4 #ifndef _VMSHW_H 1.5 #define _VMSHW_H 1.6 1.7 -#include "VMS/VMS_primitive_data_types.h" 1.8 -#include "VMS/Queue_impl/BlockingQueue.h" 1.9 +#include "VMS/Queue_impl/PrivateQueue.h" 1.10 +#include "VMS/Hash_impl/PrivateHash.h" 1.11 +#include "VMS/VMS.h" 1.12 1.13 /*This header defines everything specific to the VMSHW semantic plug-in 1.14 */ 1.15 -typedef struct VMSHWReqData VMSHWReqData; 1.16 +typedef struct _VMSHWSemReq VMSHWSemReq; 1.17 1.18 -typedef struct 1.19 - { 1.20 - } 1.21 -VMSHWProcr; 1.22 1.23 /*Semantic layer-specific data sent inside a request from lib called in app 1.24 * to request handler called in MasterLoop 1.25 */ 1.26 -enum VMSHW_ReqType 1.27 +enum VMSHWReqType 1.28 { 1.29 - receive, 1.30 - send, 1.31 - create 1.32 + send_type = 1, 1.33 + send_from_to, 1.34 + receive_any, //order and grouping matter -- send before receive 1.35 + receive_type, // and receive_any first of the receives -- Handlers 1.36 + receive_from_to,// rely upon this ordering of enum 1.37 + transfer_to, 1.38 + transfer_out 1.39 }; 1.40 1.41 -struct VMSHWReqData 1.42 - { VMSHW_ReqType reqType; 1.43 - 1.44 - }; 1.45 +struct _VMSHWSemReq 1.46 + { enum VMSHWReqType reqType; 1.47 + VirtProcr *sendPr; 1.48 + VirtProcr *receivePr; 1.49 + int32 msgType; 1.50 + void *msg; 1.51 + VMSHWSemReq *nextReqInHashEntry; 1.52 + } 1.53 +/* VMSHWSemReq */; 1.54 1.55 typedef struct 1.56 { 1.57 + PrivQueueStruc *readyVirtProcrQ; 1.58 + HashTable *commHashTbl; 1.59 + int numVirtPr; 1.60 + } 1.61 +VMSHWSemEnv; 1.62 1.63 - } 1.64 -VMSHWSemanticEnv; 1.65 + 1.66 +//=========================================================================== 1.67 + 1.68 +void 1.69 +VMSHW__create_seed_procr_and_do_work( VirtProcrFnPtr fn, void *initData ); 1.70 + 1.71 +//======================= 1.72 + 1.73 +void 1.74 +VMSHW__init(); 1.75 + 1.76 +void 1.77 +VMSHW__shutdown(); 1.78 + 1.79 +//======================= 1.80 + 1.81 +inline VirtProcr * 1.82 +VMSHW__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, 1.83 + VirtProcr *creatingPr ); 1.84 + 1.85 +void 1.86 +VMSHW__dissipate_procr( VirtProcr *procrToDissipate ); 1.87 + 1.88 +//======================= 1.89 +void * 1.90 +VMSHW__malloc_size_to( int numBytes, VirtProcr *ownerPr ); 1.91 + 1.92 +void 1.93 +VMSHW__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, 1.94 + VirtProcr *newOwnerPr ); 1.95 + 1.96 +void 1.97 +VMSHW__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ); 1.98 + 1.99 +void 1.100 +VMSHW__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ); 1.101 + 1.102 +void 1.103 +VMSHW__transfer_ownership_to_outside( void *dataToTransferOwnershipOf ); 1.104 + 1.105 + 1.106 + 1.107 +//======================= 1.108 +void 1.109 +VMSHW__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, 1.110 + VirtProcr *receivePr); 1.111 + 1.112 +void 1.113 +VMSHW__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr); 1.114 + 1.115 +void * 1.116 +VMSHW__receive_type_to( const int type, VirtProcr *receivePr ); 1.117 + 1.118 +void * 1.119 +VMSHW__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ); 1.120 + 1.121 + 1.122 +//======================= 1.123 + 1.124 +void 1.125 +VMSHW__free_semantic_request( VMSHWSemReq *semReq ); 1.126 + 1.127 + 1.128 +//========================= Internal use only ============================= 1.129 +void 1.130 +VMSHW__Request_Handler( VirtProcr *requestingPr, void *_semEnv ); 1.131 + 1.132 +VirtProcr * 1.133 +VMSHW__schedule_virt_procr( void *_semEnv ); 1.134 + 1.135 1.136 #endif /* _VMSHW_H */ 1.137
2.1 --- a/VMSHW_PluginFns.c Sat May 22 19:33:11 2010 -0700 2.2 +++ b/VMSHW_PluginFns.c Wed Jul 07 13:15:29 2010 -0700 2.3 @@ -11,107 +11,84 @@ 2.4 #include "VMS/VMS.h" 2.5 #include "VMS/Queue_impl/PrivateQueue.h" 2.6 #include "VMSHW.h" 2.7 +#include "VMSHW_Request_Handlers.h" 2.8 2.9 2.10 /*Will get requests to send, to receive, and to create new processors. 2.11 * Upon send, check the hash to see if a receive is waiting. 2.12 * Upon receive, check hash to see if a send has already happened. 2.13 * When other is not there, put in. When other is there, the comm. 2.14 - * completes, which means the receiver P gets a new work-unit generated 2.15 - * that picks up right after the receive request. So make the work-unit 2.16 + * completes, which means the receiver P gets scheduled and 2.17 + * picks up right after the receive request. So make the work-unit 2.18 * and put it into the queue of work-units ready to go. 2.19 * Other request is create a new Processor, with the function to run in the 2.20 * Processor, and initial data. 2.21 */ 2.22 +void 2.23 +VMSHW__Request_Handler( VirtProcr *requestingPr, void *_semEnv ) 2.24 + { VMSHWSemEnv *semEnv; 2.25 + VMSReqst *req; 2.26 + VMSHWSemReq *semReq; 2.27 + 2.28 + semEnv = (VMSHWSemEnv *)_semEnv; 2.29 2.30 -/*Old idea, but want to keep around: 2.31 - * give pointer to initialization function to create-processor call, in 2.32 - * addition to the work-function and initial data 2.33 - * Then, make the initialization be a work-unit, that places the created 2.34 - * processor-struc, and an initial work-unit for that processor in a 2.35 - * request that comes to the req handler when done. The initial work-unit 2.36 - * has the pointer to a special VMS code snippet that 2.37 - * the function to run in the Processor is pointed to by the work-unit 2.38 - * code pointer, and the initial data as the work-unit's data-pointer. 2.39 - * Another request is the result of create-processor request. It has a new 2.40 - * Processor, and the processor's inital work-unit. Add the Processor to 2.41 - * the data-structures that track Processors, and put the work-unit into the 2.42 - * queue of ready-to-go work-units. 2.43 - * The reason to make the create-processor work-unit return the new 2.44 - * processor and its initial work unit, is that only the MasterLoop 2.45 - * work-unit owns the semantic environment, with the Processor-tracking 2.46 - * data-structures, and only it can put work-units into or take out of 2.47 - * the ready-to-go work-unit queue. 2.48 - */ 2.49 -void 2.50 -VMSHW__Request_Handler( VMSProcr *slave, void *semanticEnv ) 2.51 - { VMSHWEnviron semEnv; 2.52 - 2.53 - semEnv = (VMSHWEnviron *)semanticEnv; 2.54 - 2.55 - req = slave->requestsToMaster; 2.56 + req = VMS__take_top_request_from( requestingPr ); 2.57 + 2.58 while( req != NULL ) 2.59 { 2.60 - //TODO: figure out better separation -- maybe MasterLoop gives 2.61 - // request payloads one at a time to this handler 2.62 - if( req->type == VMSInternal ) /*do something*/; 2.63 - else //request is to be handled by VMSHW 2.64 + if( VMS__isSemanticReqst( req ) ) 2.65 { 2.66 - semanticReq = req->reqPayload; //TODO: make sure not NULL in creator 2.67 - switch( semanticReq->type ) 2.68 + semReq = VMS__take_sem_reqst_from( req ); 2.69 + if( semReq == NULL ) goto DoneWithReqst; 2.70 + switch( semReq->reqType ) 2.71 { 2.72 - case sendFromName: handleSendFromName( semanticReq, semEnv); 2.73 + case send_type: handleSendType( semReq, semEnv); 2.74 break; 2.75 - case sendToPort: handleSendToPort( semanticReq, semEnv); 2.76 + case send_from_to: handleSendFromTo( semReq, semEnv); 2.77 break; 2.78 - case receiveFromName: handleReceiveFromName(semanticReq, semEnv); 2.79 + case receive_type: handleReceiveType( semReq, semEnv); 2.80 break; 2.81 - case receiveOnPort: handleReceiveOnPort( semanticReq, semEnv); 2.82 + case receive_from_to: handleReceiveFromTo(semReq, semEnv); 2.83 break; 2.84 - case create: handleCreate( semanticReq, semEnv); 2.85 + case transfer_to: handleTransferTo( semReq, semEnv); 2.86 + VMSHW__free_semantic_request( semReq ); 2.87 + break; 2.88 + case transfer_out: handleTransferOut( semReq, semEnv); 2.89 + VMSHW__free_semantic_request( semReq ); 2.90 break; 2.91 } 2.92 } 2.93 - req = req->next; 2.94 - } 2.95 + else if( VMS__isCreateReqst( req ) ) //only plugin can add to ready Q 2.96 + { VirtProcr * 2.97 + newPr = (VirtProcr *)req->semReqData; 2.98 + semEnv->numVirtPr += 1; 2.99 + 2.100 + //resume procr asked for registration & start new pr 2.101 + writePrivQ( requestingPr, semEnv->readyVirtProcrQ ); 2.102 + writePrivQ( newPr, semEnv->readyVirtProcrQ ); 2.103 + } 2.104 + else if( VMS__isDissipateReqst( req ) ) 2.105 + { 2.106 + //free any semantic data allocated to the virt procr 2.107 + 2.108 + //Now, call VMS's dissipate fn, which will free stack and rest 2.109 + VMS__dissipate_procr( requestingPr ); 2.110 + 2.111 + semEnv->numVirtPr -= 1; 2.112 + if( semEnv->numVirtPr == 0 ) 2.113 + { //no more work, so shutdown -- create shutdown procr & Q it 2.114 + VirtProcr * shutdownPr = VMS__create_the_shutdown_procr(); 2.115 + writePrivQ( shutdownPr, semEnv->readyVirtProcrQ ); 2.116 + } 2.117 + } 2.118 + 2.119 + DoneWithReqst: 2.120 + VMS__free_request( req ); 2.121 + req = VMS__take_top_request_from( requestingPr ); 2.122 + } //while( req != NULL ) 2.123 } 2.124 2.125 -/*The payload has the receiving processor and its port 2.126 - * 2.127 - *Note one value in this approach: without the extra (VMS) virtual layer, 2.128 - * the send and receive would happen in real time instead of virtual time, 2.129 - * which would waste real time while one of them waited for other 2.130 - */ 2.131 - void 2.132 -handleSendToPort( VMSHWRequest *reqPayload, VMSHWEnviron *semEnv ) 2.133 - { 2.134 - reqProcr = reqPayload->reqProcr; 2.135 - receivePr = reqPayload->receivePr; 2.136 - 2.137 - key = receivePr->keys[ reqPayload->portNum ]; 2.138 - value = getValueFromTable( key, semEnv->commHash ); 2.139 - if( value == NULL ) 2.140 - { 2.141 - //TODO: is hash entry really just a flag -- empty? Want work-unit? No 2.142 - // 'cause want to make an entry when only a send, no receive yet 2.143 - value = malloc( sizeof(CommHashFlag) ); 2.144 - putValueIntoTable( key, value, semEnv->commHash ); 2.145 - } 2.146 - else //receive waiting for this send 2.147 - { 2.148 - workUPayload = malloc( sizeof(VMSHWWorkUnit) ); 2.149 - workUPayload->owningProcr = receivePr; 2.150 - newWorkUnit = VMS__create_workUnit( workUPayload ); 2.151 - 2.152 - writePrivQ( newWorkUnit, semEnv->readyWorkUnitQ ); 2.153 - 2.154 - //NOTE: this is sequential! Don't have to worry about sharing or syncs 2.155 - //in semantic environment -- even though shared by work units, slaves, 2.156 - // and virtual processors -- all the sharing is in virtual time, and 2.157 - // mapped onto safe sequence in physical time by VMS 2.158 - 2.159 - } 2.160 - } 2.161 +//=========================================================================== 2.162 2.163 2.164 /*For VMSHW, scheduling a slave simply takes the next work-unit off the 2.165 @@ -120,22 +97,16 @@ 2.166 * to the slave -- return FALSE to let Master loop know scheduling that 2.167 * slave failed. 2.168 */ 2.169 -bool8 2.170 -VMSHW__schedule_slave( VMSProcr *slaveToSched, void *semanticEnv ) 2.171 - { PrivQueueStruc *readyWorkUnitQ; 2.172 - WorkUnit *workUnitToSched; 2.173 - VMSHWSemanticEnv *semEnv; 2.174 +VirtProcr * 2.175 +VMSHW__schedule_virt_procr( void *_semEnv ) 2.176 + { VirtProcr *schedPr; 2.177 + VMSHWSemEnv *semEnv; 2.178 2.179 - semEnv = (VMSHWSemanticEnv *)semanticEnv; 2.180 + semEnv = (VMSHWSemEnv *)_semEnv; 2.181 2.182 + schedPr = readPrivQ( semEnv->readyVirtProcrQ ); 2.183 //Note, using a non-blocking queue -- it returns NULL if queue empty 2.184 - readyWorkUnitQ = semEnv->readyWorkUnitQ; 2.185 2.186 - workUnitToSched = readPrivQ( readyWorkUnitQ ); 2.187 - if( readQ == NULL ) return FALSE; 2.188 + return( schedPr ); 2.189 + } 2.190 2.191 - slaveToSched->workUnitToDo = workUnitToSched; 2.192 - workUnitToSched->slaveAssignedTo = slaveToSched; 2.193 - 2.194 - return TRUE; 2.195 - }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/VMSHW_Request_Handlers.c Wed Jul 07 13:15:29 2010 -0700 3.3 @@ -0,0 +1,321 @@ 3.4 +/* 3.5 + * Copyright 2010 OpenSourceCodeStewardshipFoundation 3.6 + * 3.7 + * Licensed under BSD 3.8 + */ 3.9 + 3.10 +#include <stdio.h> 3.11 +#include <stdlib.h> 3.12 +#include <malloc.h> 3.13 + 3.14 +#include "VMS/VMS.h" 3.15 +#include "VMS/Queue_impl/PrivateQueue.h" 3.16 +#include "VMS/Hash_impl/PrivateHash.h" 3.17 +#include "VMSHW.h" 3.18 + 3.19 + 3.20 + 3.21 +//=========================================================================== 3.22 +// Helpers 3.23 + 3.24 +HashEntry * 3.25 +lookupReqAndGiveEntryElseInsertIfEmpty( char *key, VMSHWSemReq *semReq, 3.26 + HashTable *commHashTbl ) 3.27 + { HashEntry *entry; 3.28 + VMSHWSemReq *waitingReq; 3.29 + 3.30 + entry = getEntryFromTable( (char *)key, commHashTbl ); 3.31 + if( entry == NULL ) 3.32 + { //no waiting sends or receives, so add this request and exit 3.33 + addValueIntoTable( key, semReq, commHashTbl ); 3.34 + return NULL; 3.35 + } 3.36 + waitingReq = (VMSHWSemReq *)entry->content; 3.37 + if( waitingReq == NULL ) //might happen when last waiting gets paired 3.38 + { //no waiting sends or receives, so add this request and exit 3.39 + entry->content = semReq; 3.40 + return NULL; 3.41 + } 3.42 + return entry; 3.43 + } 3.44 + 3.45 + 3.46 + 3.47 + 3.48 +//=========================================================================== 3.49 +/*The semantic request has the receiving processor and the message type 3.50 + * 3.51 + *Note one value in this approach: without the extra VMS layer, 3.52 + * the send and receive would happen in real time instead of virtual time, 3.53 + * which would waste real time while one of them waited for other 3.54 + * 3.55 + *When successfully pair-up, transfer ownership of the sent data 3.56 + * to the receiving processor 3.57 + * 3.58 + *Messages of a given Type have to be kept separate.. so need a separate 3.59 + * entry in the hash table for each pair: receivePr, msgType 3.60 + * 3.61 + *Also, if same sender sends multiple before any get received, then need to 3.62 + * stack the sends up -- even if a send waits until it's paired, several 3.63 + * separate processors can send to the same receiver, and hashing on the 3.64 + * receive processor, so they will stack up. 3.65 + */ 3.66 +void 3.67 +handleSendType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv ) 3.68 + { VirtProcr *sendPr, *receivePr; 3.69 + int key[] = {0,0,0}; 3.70 + VMSHWSemReq *waitingReq; 3.71 + HashEntry *entry; 3.72 + HashTable *commHashTbl = semEnv->commHashTbl; 3.73 + 3.74 + receivePr = semReq->receivePr; //For "send", know both send & recv procrs 3.75 + sendPr = semReq->sendPr; 3.76 + 3.77 + //TODO: handle transfer of msg-locs ownership 3.78 + //TODO: hash table implemented such that using "addEntry" or 3.79 + // "addValue" to table causes the *value* in old entry to be 3.80 + // *freed* -- this is bad. Want to stack up values in a linked 3.81 + // list when multiple have the same key. 3.82 + 3.83 + //TODO: use a faster hash function -- see notes in intelligence gather 3.84 + key[0] = (int)receivePr; 3.85 + key[1] = (int)(semReq->msgType); 3.86 + //key[2] acts at the 0 that terminates the string 3.87 + 3.88 + entry = lookupReqAndGiveEntryElseInsertIfEmpty( key, semReq, commHashTbl); 3.89 + if( entry == NULL ) return; //was just inserted 3.90 + 3.91 + waitingReq = (VMSHWSemReq *)entry->content; 3.92 + 3.93 + //At this point, know have waiting request(s) -- either sends or recv 3.94 + //Note, can only have max of one receive waiting, and cannot have both 3.95 + // sends and receives waiting (they would have paired off) 3.96 + // but can have multiple send_type requests waiting (from diff senders) 3.97 + if( waitingReq->reqType == send_type ) 3.98 + { //waiting request is another send, so stack this up on list 3.99 + semReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry; 3.100 + waitingReq->nextReqInHashEntry = semReq; 3.101 + return; 3.102 + } 3.103 + else 3.104 + { //waiting request is a receive, so pair it to this send 3.105 + //first, remove the waiting receive request from the list in entry 3.106 + entry->content = waitingReq->nextReqInHashEntry; 3.107 + if( entry->content == NULL ) 3.108 + { //TODO: mod hash table to double-link, so can delete entry from 3.109 + // table without hashing the key and looking it up again 3.110 + deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too 3.111 + } 3.112 + 3.113 + //attach msg that's in this send request to receiving procr 3.114 + // when comes back from suspend, will have msg in semanticData 3.115 + receivePr->semanticData = semReq->msg; 3.116 + 3.117 + //bring both processors back from suspend 3.118 + writePrivQ( sendPr, semEnv->readyVirtProcrQ ); 3.119 + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); 3.120 + 3.121 + //don't need semReq anymore -- free it 3.122 + VMSHW__free_semantic_request( waitingReq ); 3.123 + VMSHW__free_semantic_request( semReq ); 3.124 + return; 3.125 + } 3.126 + } 3.127 + 3.128 + 3.129 +/*Looks like can make single handler for both sends.. 3.130 + */ 3.131 +//TODO: combine both send handlers into single handler 3.132 +void 3.133 +handleSendFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) 3.134 + { VirtProcr *sendPr, *receivePr; 3.135 + int key[] = {0,0,0}; 3.136 + VMSHWSemReq *waitingReq; 3.137 + HashEntry *entry; 3.138 + HashTable *commHashTbl = semEnv->commHashTbl; 3.139 + 3.140 + receivePr = semReq->receivePr; //For "send", know both send & recv procrs 3.141 + sendPr = semReq->sendPr; 3.142 + 3.143 + key[0] = (int)receivePr; 3.144 + key[1] = (int)sendPr; 3.145 + //key[2] acts at the 0 that terminates the string 3.146 + 3.147 + entry = lookupReqAndGiveEntryElseInsertIfEmpty( key, semReq, commHashTbl); 3.148 + if( entry == NULL ) return; //was just inserted 3.149 + 3.150 + waitingReq = (VMSHWSemReq *)entry->content; 3.151 + 3.152 + //At this point, know have waiting request(s) -- either sends or recv 3.153 + if( waitingReq->reqType == send_from_to ) 3.154 + { printf("\n ERROR: shouldn't be two send from-tos waiting \n"); 3.155 + } 3.156 + else 3.157 + { //waiting request is a receive, so pair it to this send 3.158 + //first, remove the waiting receive request from the list in entry 3.159 + entry->content = waitingReq->nextReqInHashEntry; 3.160 + //can only be one waiting req for "from-to" semantics 3.161 + if( entry->content != NULL ) printf("\nERROR in handleSendFromTo\n"); 3.162 + deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too 3.163 + 3.164 + //attach msg that's in this send request to receiving procr 3.165 + // when comes back from suspend, will have msg in semanticData 3.166 + receivePr->semanticData = semReq->msg; 3.167 + 3.168 + //bring both processors back from suspend 3.169 + writePrivQ( sendPr, semEnv->readyVirtProcrQ ); 3.170 + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); 3.171 + 3.172 + //done with requests, so free them 3.173 + VMSHW__free_semantic_request( waitingReq ); 3.174 + VMSHW__free_semantic_request( semReq ); 3.175 + return; 3.176 + } 3.177 + } 3.178 + 3.179 + 3.180 + 3.181 +//======================================================= 3.182 + 3.183 +/*Removed this one for now, because forces either a search or going to a 3.184 + * two-level hash table, where one level the key is the receivePr, in the 3.185 + * other level, the key is the type. 3.186 + *So, each dest procr that either does a receive_type or that a send_type 3.187 + * targets it, would have a hash table created just for it and placed 3.188 + * into the first-level hash table entry for that receive procr. 3.189 + *Then, doing a receive_type first looks up entry for receive procr in first 3.190 + * table, gets the type-table out of that entry, and does a second lookup 3.191 + * in the type-table. 3.192 + *Doing a receive from-to looks up in the first table, gets the second table 3.193 + * hashed on "from" procr. 3.194 + *Doing a receive_any looks up in the first table, then looks to see if 3.195 + * either of the hash tables have any entries -- would then have to do a 3.196 + * linear search through the hash-table's array for the first non-empty 3.197 + * spot 3.198 + *Yuck. 3.199 + * 3.200 + *Alternatively, could keep two hash tables updated all the time -- one that 3.201 + * does the receive_type and receive_from_to and a second that does 3.202 + * receive_any -- would only hash the second table by the receive procr. 3.203 + * When remove from one table, keep back-links to both tables, so can also 3.204 + * quickly remove from other table. 3.205 + *Cost is doing two hash-table lookups for every insert. 3.206 + * If ever add receive_any, looking like this second option easier and even 3.207 + * less costly. 3.208 + */ 3.209 +void 3.210 +handleReceiveAny( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) 3.211 + { 3.212 + 3.213 + } 3.214 + 3.215 + 3.216 +void 3.217 +handleReceiveType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) 3.218 + { VirtProcr *sendPr, *receivePr; 3.219 + int key[] = {0,0,0}; 3.220 + VMSHWSemReq *waitingReq; 3.221 + HashEntry *entry; 3.222 + HashTable *commHashTbl = semEnv->commHashTbl; 3.223 + 3.224 + receivePr = semReq->receivePr; 3.225 + 3.226 + key[0] = (int)receivePr; 3.227 + key[1] = (int)(semReq->msgType); 3.228 + //key[2] acts at the 0 that terminates the string 3.229 + 3.230 + 3.231 + entry = lookupReqAndGiveEntryElseInsertIfEmpty( key, semReq, commHashTbl); 3.232 + if( entry == NULL ) return; //was just inserted 3.233 + 3.234 + waitingReq = (VMSHWSemReq *)entry->content; 3.235 + 3.236 + //At this point, know have waiting request(s) -- should be send(s) 3.237 + if( waitingReq->reqType == send_type ) 3.238 + { //waiting request is a send, so pair it with this receive 3.239 + //first, remove the waiting send request from the list in entry 3.240 + entry->content = waitingReq->nextReqInHashEntry; 3.241 + if( entry->content == NULL ) 3.242 + { deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too 3.243 + } 3.244 + 3.245 + //attach msg that's in the send request to receiving procr 3.246 + // when comes back from suspend, will have msg in semanticData 3.247 + receivePr->semanticData = waitingReq->msg; 3.248 + 3.249 + //bring both processors back from suspend 3.250 + writePrivQ( waitingReq->sendPr, semEnv->readyVirtProcrQ ); 3.251 + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); 3.252 + 3.253 + //done with requests, so free them 3.254 + VMSHW__free_semantic_request( waitingReq ); 3.255 + VMSHW__free_semantic_request( semReq ); 3.256 + return; 3.257 + } 3.258 + printf("\nLang Impl Error: Should never be two waiting receives!\n"); 3.259 + } 3.260 + 3.261 + 3.262 +/* 3.263 + */ 3.264 +void 3.265 +handleReceiveFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) 3.266 + { VirtProcr *sendPr, *receivePr; 3.267 + int key[] = {0,0,0}; 3.268 + VMSHWSemReq *waitingReq; 3.269 + HashEntry *entry; 3.270 + HashTable *commHashTbl = semEnv->commHashTbl; 3.271 + 3.272 + receivePr = semReq->receivePr; 3.273 + sendPr = semReq->sendPr; //for receive from-to, know send procr 3.274 + 3.275 + key[0] = (int)receivePr; 3.276 + key[1] = (int)sendPr; 3.277 + //key[2] acts at the 0 that terminates the string 3.278 + 3.279 + entry = lookupReqAndGiveEntryElseInsertIfEmpty( key, semReq, commHashTbl); 3.280 + if( entry == NULL ) return; //was just inserted 3.281 + 3.282 + waitingReq = (VMSHWSemReq *)entry->content; 3.283 + 3.284 + //At this point, know have waiting request(s) -- should be send(s) 3.285 + if( waitingReq->reqType == send_from_to ) 3.286 + { //waiting request is a send, so pair it with this receive 3.287 + 3.288 + //For from-to, should only ever be a single reqst waiting tobe paird 3.289 + entry->content = waitingReq->nextReqInHashEntry; 3.290 + if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n"); 3.291 + deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too 3.292 + 3.293 + //attach msg that's in the send request to receiving procr 3.294 + // when comes back from suspend, will have msg in semanticData 3.295 + receivePr->semanticData = waitingReq->msg; 3.296 + 3.297 + //bring both processors back from suspend 3.298 + writePrivQ( waitingReq->sendPr, semEnv->readyVirtProcrQ ); 3.299 + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); 3.300 + 3.301 + //done with requests, so free them 3.302 + VMSHW__free_semantic_request( waitingReq ); 3.303 + VMSHW__free_semantic_request( semReq ); 3.304 + return; 3.305 + } 3.306 + printf("\nLang Impl Error: Should never be two waiting receives!\n"); 3.307 + } 3.308 + 3.309 + 3.310 + 3.311 +//=============================================== 3.312 +void 3.313 +handleTransferTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) 3.314 + { 3.315 + 3.316 + } 3.317 + 3.318 +void 3.319 +handleTransferOut( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) 3.320 + { 3.321 + 3.322 + } 3.323 + 3.324 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/VMSHW_Request_Handlers.h Wed Jul 07 13:15:29 2010 -0700 4.3 @@ -0,0 +1,33 @@ 4.4 +/* 4.5 + * Copyright 2009 OpenSourceStewardshipFoundation.org 4.6 + * Licensed under GNU General Public License version 2 4.7 + * 4.8 + * Author: seanhalle@yahoo.com 4.9 + * 4.10 + */ 4.11 + 4.12 +#ifndef _VMSHW_REQ_H 4.13 +#define _VMSHW_REQ_H 4.14 + 4.15 +#include "VMSHW.h" 4.16 + 4.17 +/*This header defines everything specific to the VMSHW semantic plug-in 4.18 + */ 4.19 + 4.20 +void 4.21 +handleSendType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.22 +void 4.23 +handleSendFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.24 +void 4.25 +handleReceiveAny( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.26 +void 4.27 +handleReceiveType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.28 +void 4.29 +handleReceiveFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.30 +void 4.31 +handleTransferTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.32 +void 4.33 +handleTransferOut( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); 4.34 + 4.35 +#endif /* _VMSHW_REQ_H */ 4.36 +
5.1 --- a/VMSHW_lib.c Sat May 22 19:33:11 2010 -0700 5.2 +++ b/VMSHW_lib.c Wed Jul 07 13:15:29 2010 -0700 5.3 @@ -8,17 +8,37 @@ 5.4 #include <stdlib.h> 5.5 #include <malloc.h> 5.6 5.7 -#include "../VMS/VMS.h" 5.8 +#include "VMS/VMS.h" 5.9 #include "VMSHW.h" 5.10 -#include "../VMS/Queue_impl/NonBlockingQueue.h" 5.11 +#include "VMS/Queue_impl/PrivateQueue.h" 5.12 +#include "VMS/Hash_impl/PrivateHash.h" 5.13 + 5.14 + 5.15 + 5.16 +/*TODO: Q: dealing with library f()s and DKU vs WT vs FoR 5.17 + * (still want to do FoR, with time-lines as syntax, could be super cool) 5.18 + * A: thinking pin the coreLoops for all of BLIS -- let Master arbitrate 5.19 + * among library, DKU, WT, FoR -- all the patterns in terms of virtual 5.20 + * processors (or equivalently work-units), so Master picks which virt procr 5.21 + * from which portions of app (DKU, WT, FoR) onto which sched slots 5.22 + *Might even do hierarchy of masters -- group of sched slots for each core 5.23 + * has its own master, that keeps generated work local 5.24 + * single-reader-single-writer sync everywhere -- no atomic primitives 5.25 + * Might have the different schedulers talk to each other, to negotiate 5.26 + * larger-grain sharing of resources, according to predicted critical 5.27 + * path, and expansion of work 5.28 + */ 5.29 + 5.30 + 5.31 + 5.32 +//=========================================================================== 5.33 5.34 5.35 /*These are the library functions *called in the application* 5.36 - *They all run in the virtual slaves, never in the virtual master. 5.37 * 5.38 *There's a pattern for the outside sequential code to interact with the 5.39 - * VMSHW code. 5.40 - *The VMSHW system is inside a boundary.. every VMSHW system is in its 5.41 + * VMS_HW code. 5.42 + *The VMS_HW system is inside a boundary.. every VMSHW system is in its 5.43 * own directory that contains the functions for each of the processor types. 5.44 * One of the processor types is the "seed" processor that starts the 5.45 * cascade of creating all the processors that do the work. 5.46 @@ -41,6 +61,47 @@ 5.47 */ 5.48 5.49 5.50 + 5.51 +//=========================================================================== 5.52 + 5.53 +/*This is the "border crossing" function -- the thing that crosses from the 5.54 + * outside world, into the VMS_HW world. It initializes and starts up the 5.55 + * VMS system, then creates one processor from the specified function and 5.56 + * puts it into the readyQ. From that point, that one function is resp. 5.57 + * for creating all the other processors, that then create others, and so 5.58 + * forth. 5.59 + *When all the processors, including the seed, have dissipated, then this 5.60 + * function returns. The results will have been written by side-effect via 5.61 + * pointers read from, or written into initData. 5.62 + */ 5.63 +void 5.64 +VMSHW__create_seed_procr_and_do_work( VirtProcrFnPtr fnPtr, void *initData ) 5.65 + { VMSHWSemEnv *semEnv; 5.66 + VirtProcr *seedProcr; 5.67 + 5.68 + VMSHW__init(); 5.69 + 5.70 + semEnv = _VMSMasterEnv->semanticEnv; 5.71 + 5.72 + //VMSHW starts with one processor, which is put into initial environ, 5.73 + // and which then calls create() to create more, thereby expanding work 5.74 + seedProcr = VMS__create_procr( fnPtr, initData ); 5.75 + 5.76 + writePrivQ( seedProcr, semEnv->readyVirtProcrQ ); 5.77 + semEnv->numVirtPr = 1; 5.78 + 5.79 + //NOTE: no Threads should exist in the outside program that might touch 5.80 + // any of the data reachable from initData given to the seed procr 5.81 + VMS__start_the_work_then_wait_until_done(); 5.82 + 5.83 + VMSHW__shutdown(); 5.84 + } 5.85 + 5.86 + 5.87 + 5.88 + 5.89 +//=========================================================================== 5.90 + 5.91 /*Initializes all the data-structures for a VMSHW system -- but doesn't 5.92 * start it running yet! 5.93 * 5.94 @@ -48,183 +109,248 @@ 5.95 *This sets up the semantic layer over the VMS system 5.96 * 5.97 *First, calls VMS_Setup, then creates own environment, making it ready 5.98 - * for creating the seed processor. 5.99 + * for creating the seed processor and then starting the work. 5.100 */ 5.101 - void 5.102 +void 5.103 VMSHW__init() 5.104 - { VMSHWEnv *semanticEnv; 5.105 + { VMSHWSemEnv *semanticEnv; 5.106 5.107 - init_VMS(); 5.108 + VMS__init(); 5.109 + //masterEnv, a global var, now is partially set up by init_VMS 5.110 5.111 - //masterEnv, a global var, now is partially set up by init_VMS 5.112 - semanticEnv = malloc( sizeof( VMSHWEnv ) ); 5.113 - masterEnv->semanticEnv = semanticEnv; 5.114 + //Hook up the semantic layer's plug-ins to the Master virt procr 5.115 + _VMSMasterEnv->requestHandler = &VMSHW__Request_Handler; 5.116 + _VMSMasterEnv->slaveScheduler = &VMSHW__schedule_virt_procr; 5.117 5.118 - semanticEnv->readyWorkUnitsQ = mareadyWorkUnitsQkePrivQ(); 5.119 + //create the semantic layer's environment (all its data) and add to 5.120 + // the master environment 5.121 + semanticEnv = malloc( sizeof( VMSHWSemEnv ) ); 5.122 + _VMSMasterEnv->semanticEnv = semanticEnv; 5.123 + 5.124 + //create the ready queue, hash tables used for pairing send to receive 5.125 + // and so forth 5.126 + //TODO: add hash tables for pairing sends with receives, and 5.127 + // initialize the data ownership system 5.128 + semanticEnv->readyVirtProcrQ = makePrivQ(); 5.129 + semanticEnv->commHashTbl = makeHashTable( 1<<16, NULL ); //start big 5.130 } 5.131 5.132 +/*Frees any memory allocated by VMSHW__init() then calls VMS__shutdown 5.133 + */ 5.134 +void 5.135 +VMSHW__shutdown() 5.136 + { VMSHWSemEnv *semanticEnv; 5.137 + 5.138 + semanticEnv = _VMSMasterEnv->semanticEnv; 5.139 5.140 -/*This is the entry point to the VMSHW system from the sequential part of 5.141 - * the app.. 5.142 - * 5.143 - *Calling this starts the VMS system, passing it the input data given to 5.144 - * this, then waits for the work to finish, and returns whatever pointer 5.145 - * the final VMSHW call said to return to the outside via the 5.146 - * VMSHW__transfer_out_as_result call 5.147 - */ 5.148 - 5.149 -VMSHW__start_then_wait_until_work_done() 5.150 - { 5.151 - VMS__start(); 5.152 - 5.153 - //Wait for work to complete 5.154 - //Use PThreads to put the main thread to sleep until something executes 5.155 - // a notify(), which is the last thing VMS does when work is done 5.156 - 5.157 - 5.158 - //This will suspend the main PThread until all VMSHW processors have 5.159 - // performed dissipate_self(), at which point the VMSHW system will 5.160 - // shut itself down, then shut VMS down then call notify to make this 5.161 - // wait wake up the main thread again. 5.162 - status = 5.163 - pthread_cond_wait( &VMS_Environ->doneCondition/*,&VMS_Environ->doneLock*/); 5.164 - if (status != 0){perror("Error waiting for work to finish\n"); exit(1);} 5.165 - 5.166 - //signal like this: pthread_cond_signal( &VMS_Environ->doneCondition ); 5.167 - 5.168 + //TODO: double check all sem env locations freed 5.169 + free( semanticEnv->readyVirtProcrQ->startOfData ); 5.170 + free( semanticEnv->readyVirtProcrQ ); 5.171 + freeHashTable( semanticEnv->commHashTbl ); 5.172 + free( _VMSMasterEnv->semanticEnv ); 5.173 + VMS__shutdown(); 5.174 } 5.175 5.176 -/*TODO: Q: dealing with library f()s and DKU vs WT vs FoR 5.177 - * (still want to do FoR, with time-lines as syntax, could be super cool) 5.178 - * A: thinking pin the coreLoops for all of BLIS -- let Master arbitrate 5.179 - * among library, DKU, WT, FoR -- all the patterns in terms of work-units, 5.180 - * so Master picks which work-units from which portions of app onto which 5.181 - * Slaves 5.182 - *Might even do one master plus several slaves for each core -- allows 5.183 - * single-reader-single-writer sync everywhere -- no atomic primitives 5.184 - * Might have the different schedulers talk to each other, to negotiate 5.185 - * larger-grain sharing of resources, according to predicted critical 5.186 - * path, and expansion of work 5.187 + 5.188 +//=========================================================================== 5.189 + 5.190 +/* 5.191 */ 5.192 +inline VirtProcr * 5.193 +VMSHW__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, 5.194 + VirtProcr *creatingPr ) 5.195 + { VirtProcr *newPr; 5.196 5.197 + newPr = VMS__create_procr( fnPtr, initData ); 5.198 5.199 + //After create, have to send request to plugin for any sem env 5.200 + // modifications -- such as putting the new procr into the ready Q 5.201 + //Need a processor to "animate" the creation -- it's one the register 5.202 + // request is attached to, and one suspended in order to send req 5.203 + // to plugin 5.204 + VMS__send_register_new_procr_request( newPr, creatingPr ); 5.205 5.206 -/*Causes the VMSHW system to remove internal ownership, so data won't be 5.207 - * freed when VMSHW shuts down, and will persist in the external program. 5.208 - */ 5.209 -void 5.210 -VMSHW__transfer_to_external( void *data ) 5.211 + return newPr; 5.212 + } 5.213 + 5.214 + 5.215 +inline void 5.216 +VMSHW__dissipate_procr( VirtProcr *procrToDissipate ) 5.217 + { 5.218 + VMS__dissipate_procr( procrToDissipate ); 5.219 + } 5.220 + 5.221 + 5.222 +//=========================================================================== 5.223 + 5.224 +void * 5.225 +VMSHW__malloc_size_to( int numBytes, VirtProcr *ownerPr ) 5.226 { 5.227 5.228 } 5.229 5.230 + 5.231 void 5.232 -VMSHW__create_seed_processor_then_wait_until_work_done 5.233 - ( VMSHWProcrFnPtr fn, void *data ) 5.234 - { VMSHWEnviron semEnv; 5.235 +VMSHW__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, 5.236 + VirtProcr *newOwnerPr ) 5.237 + { 5.238 5.239 - VMSHW__init(); 5.240 - semEnv = masterEnv->semanticEnv; 5.241 - 5.242 - //VMSHW starts with one processor, which is put into initial environ, 5.243 - // and, which then calls create() to create more thereby expanding work 5.244 - firstVirtProcr = VMSHW__create_processor( ); 5.245 + } 5.246 5.247 - firstWorkUnit = 5.248 5.249 - writePrivQ( firstWorkUnit, semEnv->readyWorkUnitsQ ); 5.250 +void 5.251 +VMSHW__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ) 5.252 + { 5.253 5.254 - //start the VMSHW system then wait for work to end 5.255 - //NOTE: no Threads should exist in the outside program that might touch 5.256 - // any of the data reachable from the params given to the seed procr 5.257 - VMSHW__start_then_wait_until_work_done(); 5.258 + } 5.259 + 5.260 + 5.261 +void 5.262 +VMSHW__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ) 5.263 + { 5.264 + 5.265 + } 5.266 + 5.267 + 5.268 +/*Causes the VMSHW system to remove internal ownership, so data won't be 5.269 + * freed when VMSHW shuts down, and will persist in the external program. 5.270 + * 5.271 + *Must be called from the processor that currently owns the data. 5.272 + * 5.273 + *IMPL: Transferring ownership touches two different virtual processor's 5.274 + * state -- which means it has to be done carefully -- the VMS rules for 5.275 + * semantic layers say that a work-unit is only allowed to touch the 5.276 + * virtual processor it is part of, and that only a single work-unit per 5.277 + * virtual processor be scheduled to a slave at a time. So, this has to 5.278 + * modify the virtual processor that owns the work-unit that called this 5.279 + * function, then create a request to have the other processor modified. 5.280 + *However, in this case, the TO processor is the outside, and transfers 5.281 + * are only allowed to be called by the giver-upper, so can mark caller of 5.282 + * this function as no longer owner, and return -- done. 5.283 + */ 5.284 +void 5.285 +VMSHW__transfer_ownership_to_outside( void *data ) 5.286 + { 5.287 + //TODO: removeAllOwnersFrom( data ); 5.288 + } 5.289 + 5.290 + 5.291 +//=========================================================================== 5.292 + 5.293 +void 5.294 +VMSHW__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, 5.295 + VirtProcr *receivePr) 5.296 + { VMSHWSemReq *reqData; 5.297 + 5.298 + reqData = malloc( sizeof(VMSHWSemReq) ); 5.299 + reqData->receivePr = receivePr; 5.300 + reqData->sendPr = sendPr; 5.301 + reqData->reqType = send_type; 5.302 + reqData->msgType = type; 5.303 + reqData->msg = msg; 5.304 + 5.305 + //On ownership -- remove inside the send and let ownership sit in limbo 5.306 + // as a potential in an entry in the hash table, when this receive msg 5.307 + // gets paired to a send, the ownership gets added to the receivePr -- 5.308 + // the next work-unit in the receivePr's trace will have ownership. 5.309 + VMS__add_sem_request( reqData, sendPr ); 5.310 + VMS__suspend_procr( sendPr ); //will suspend then resume and continue 5.311 + 5.312 + //When come back from suspend, no longer own data reachable from msg 5.313 + //TODO: release ownership here 5.314 } 5.315 5.316 void 5.317 -VMSHW__create_processor( ) 5.318 - { 5.319 - firstWorkUnit = firstVirtProcr->latestWorkUnit; 5.320 +VMSHW__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr ) 5.321 + { VMSHWSemReq *reqData; 5.322 5.323 - writePrivQ( firstWorkUnit, semanticEnv->readyWorkUnitsQ ); 5.324 + //hash on the receiver, 'cause always know it, but sometimes want to 5.325 + // receive from anonymous sender 5.326 5.327 - return firstVirtProcr; 5.328 + reqData = malloc( sizeof(VMSHWSemReq) ); 5.329 + reqData->receivePr = receivePr; 5.330 + reqData->sendPr = sendPr; 5.331 + reqData->reqType = send_from_to; 5.332 + reqData->msg = msg; 5.333 + 5.334 + //On ownership -- remove inside the send and let ownership sit in limbo 5.335 + // as a potential in an entry in the hash table, when this receive msg 5.336 + // gets paired to a send, the ownership gets added to the receivePr -- 5.337 + // the next work-unit in the receivePr's trace will have ownership. 5.338 + VMS__add_sem_request( reqData, sendPr ); 5.339 + VMS__suspend_procr( sendPr ); //will suspend then resume and continue 5.340 + 5.341 + //When come back from suspend, no longer own data reachable from msg 5.342 + //TODO: release ownership here 5.343 } 5.344 5.345 -VMSHWProcrFnPtr 5.346 - VMSHWProcr * VMSHW__create_processor( &calcVector, vectParams ); 5.347 - void * VMSHW__malloc( sizeof( VectorParams ) ); 5.348 - VMSHW__transfer_to_outside( resultMatrix ); 5.349 - VMSHW__dissipate_self(); //all processors have to dissipate self at end 5.350 - VMSHW__send( result, resultPr ); 5.351 - resultsParams->dividerPr = VMSHW__self(); 5.352 - VMSHW__start_then_wait_until_work_done(); 5.353 - VMSHW__create_seed_processor( ÷IntoVectors, dividerParams ); 5.354 -VMSHWProcr 5.355 5.356 - void * VMSHW__receive_from( self, resultPr ); 5.357 - void * VMSHW__receive_from_any_but( self, dividerPr ); 5.358 - void * VMSHW__receive_on_port( self, VECTOR_PORT ); 5.359 - 5.360 - VMSHW__transfer_ownership_from_to( resultMatrix, self, dividerPr ); 5.361 +//=========================================================================== 5.362 5.363 void * 5.364 -VMSHW__receive_from( VMSHWProcr *callingPr, VMSHWProcr *sendingPr ) 5.365 - { VMSRequest *req; 5.366 - VMSHWReq reqPayload; 5.367 +VMSHW__receive_any_to( VirtProcr *receivePr ) 5.368 + { 5.369 5.370 - //hash on the caller, 'cause always know it, but sometimes want to 5.371 - // receive from anonymous sender 5.372 - //Q: what happens if no "receive" is outstanding for one sender, but 5.373 - // do have an outstanding for a different sender? 5.374 - //need to treat each "from" as a separate port in the hash table 5.375 - 5.376 - reqPayload = malloc( sizeof(VMSHWReq) ); 5.377 - reqPayload->type = receive_from; 5.378 - reqPayload->key = callingPr->ID ^ sendingPr->ID << 16; //65K max procrs 5.379 - reqPayload->procr = callingPr; 5.380 - 5.381 - req = VMS__create_request( reqPayload ); 5.382 - VMS__add_request_to_slave( req, callingPr ); 5.383 - VMS__save_ret_and_jump_to_CoreLoop( callingPr ); 5.384 } 5.385 5.386 +void * 5.387 +VMSHW__receive_type_to( const int type, VirtProcr *receivePr ) 5.388 + { void *msg; 5.389 + VMSHWSemReq *reqData; 5.390 + 5.391 + reqData = malloc( sizeof(VMSHWSemReq) ); 5.392 + reqData->receivePr = receivePr; 5.393 + reqData->reqType = receive_type; 5.394 + reqData->msgType = type; 5.395 + 5.396 + VMS__add_sem_request( reqData, receivePr ); 5.397 + VMS__suspend_procr( receivePr ); 5.398 + msg = receivePr->semanticData; 5.399 + return msg; 5.400 + } 5.401 + 5.402 + 5.403 + 5.404 +/*Call this at point receiving virt pr wants in-coming data. 5.405 + * 5.406 + *The reason receivePr must call this is that it modifies the receivPr 5.407 + * loc structure directly -- and the VMS rules state a virtual processor 5.408 + * loc structure can only be modified by itself. 5.409 + */ 5.410 +void * 5.411 +VMSHW__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ) 5.412 + { VMSHWSemReq *reqData; 5.413 + 5.414 + //hash on the receiver, 'cause always know it, but sometimes want to 5.415 + // receive from anonymous sender 5.416 + 5.417 + reqData = malloc( sizeof(VMSHWSemReq) ); 5.418 + reqData->receivePr = receivePr; 5.419 + reqData->sendPr = sendPr; 5.420 + reqData->reqType = receive_from_to; 5.421 + 5.422 + //On ownership -- remove inside the send after receive successful. 5.423 + // Below, add ownership when come back from suspend 5.424 + //Reason: Thinking of impl ownership mech such that it automatically 5.425 + // frees any data has no owners -- so have to add receiver before 5.426 + // remove sender 5.427 + VMS__add_sem_request( reqData, receivePr ); 5.428 + //TODO: add ownership of locs reachable from msg inside reqst handler 5.429 + VMS__suspend_procr( receivePr ); //will suspend then resume and continue 5.430 + 5.431 + //When come back from suspend, the msg data is in receivePr->semData 5.432 + return receivePr->semanticData; 5.433 + } 5.434 5.435 5.436 //=========================================================================== 5.437 - void 5.438 -freeParamStruc( ParamStruc * param ) 5.439 - { if( param->type == STRING_PARAM_TYPE ) free( param->strValue ); 5.440 - free( param ); 5.441 + 5.442 +/*Just thin wrapper for now -- semantic request is still a simple thing 5.443 + * (July 3, 2010) 5.444 + */ 5.445 +inline void 5.446 +VMSHW__free_semantic_request( VMSHWSemReq *semReq ) 5.447 + { 5.448 + free( semReq ); 5.449 } 5.450 5.451 - 5.452 - ParamStruc * 5.453 -makeParamStruc() 5.454 - { ParamStruc *retStruc; 5.455 - retStruc = malloc( sizeof( ParamStruc ) ); 5.456 - retStruc->floatValue = 0.0; 5.457 - retStruc->intValue = 0; 5.458 - retStruc->strValue = NULL; 5.459 - } 5.460 - 5.461 - ParamStruc * 5.462 -makeParamFromStrs( char * type, char *value ) 5.463 - { ParamStruc *retParam; 5.464 - retParam = makeParamStruc(); 5.465 - switch(*type) 5.466 - { case 'i': 5.467 - { retParam->type = INT_PARAM_TYPE; 5.468 - retParam->intValue = atoi( value ); 5.469 - } break; 5.470 - case 's': 5.471 - { retParam->type = STRING_PARAM_TYPE; 5.472 - retParam->strValue = malloc( strlen(value) + 1); 5.473 - strcpy( retParam->strValue, value ); 5.474 - } break; 5.475 - case 'f': 5.476 - { retParam->type = FLOAT_PARAM_TYPE; 5.477 - retParam->floatValue = atof( value ); 5.478 - } break; 5.479 - } 5.480 - return retParam; 5.481 - }
