# HG changeset patch # User Me # Date 1283357696 25200 # Node ID 9172ea309065cfab9b08c5a94e8b2a457325df75 # Parent 7fd2b56b5694fdda3aa6f8ce9355fce604323ae5 Changed name of SingleMaster branch to SSR also diff -r 7fd2b56b5694 -r 9172ea309065 SSR.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SSR.h Wed Sep 01 09:14:56 2010 -0700 @@ -0,0 +1,125 @@ +/* + * Copyright 2009 OpenSourceStewardshipFoundation.org + * Licensed under GNU General Public License version 2 + * + * Author: seanhalle@yahoo.com + * + */ + +#ifndef _SSR_H +#define _SSR_H + +#include "VMS/Queue_impl/PrivateQueue.h" +#include "VMS/Hash_impl/PrivateHash.h" +#include "VMS/VMS.h" + +/*This header defines everything specific to the SSR semantic plug-in + */ +typedef struct _SSRSemReq SSRSemReq; + + +/*Semantic layer-specific data sent inside a request from lib called in app + * to request handler called in MasterLoop + */ +enum SSRReqType + { + send_type = 1, + send_from_to, + receive_any, //order and grouping matter -- send before receive + receive_type, // and receive_any first of the receives -- Handlers + receive_from_to,// rely upon this ordering of enum + transfer_to, + transfer_out + }; + +struct _SSRSemReq + { enum SSRReqType reqType; + VirtProcr *sendPr; + VirtProcr *receivePr; + int32 msgType; + void *msg; + SSRSemReq *nextReqInHashEntry; + } +/* SSRSemReq */; + +typedef struct + { + PrivQueueStruc *readyVirtProcrQ; + HashTable *commHashTbl; + int numVirtPr; + } +SSRSemEnv; + + +//=========================================================================== + +void +SSR__create_seed_procr_and_do_work( VirtProcrFnPtr fn, void *initData ); + +//======================= + +void +SSR__init(); + +void +SSR__cleanup_after_shutdown(); + +//======================= + +inline VirtProcr * +SSR__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, + VirtProcr *creatingPr ); + +void +SSR__dissipate_procr( VirtProcr *procrToDissipate ); + +//======================= +void * +SSR__malloc_size_to( int numBytes, VirtProcr *ownerPr ); + +void +SSR__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, + VirtProcr *newOwnerPr ); + +void +SSR__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ); + +void +SSR__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ); + +void +SSR__transfer_ownership_to_outside( void *dataToTransferOwnershipOf ); + + + +//======================= +void +SSR__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, + VirtProcr *receivePr); + +void +SSR__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr); + +void * +SSR__receive_type_to( const int type, VirtProcr *receivePr ); + +void * +SSR__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ); + + +//======================= + +void +SSR__free_semantic_request( SSRSemReq *semReq ); + + +//========================= Internal use only ============================= +void +SSR__Request_Handler( VirtProcr *requestingPr, void *_semEnv ); + +VirtProcr * +SSR__schedule_virt_procr( void *_semEnv ); + + +#endif /* _SSR_H */ + diff -r 7fd2b56b5694 -r 9172ea309065 SSR_PluginFns.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SSR_PluginFns.c Wed Sep 01 09:14:56 2010 -0700 @@ -0,0 +1,113 @@ +/* + * Copyright 2010 OpenSourceCodeStewardshipFoundation + * + * Licensed under BSD + */ + +#include +#include +#include + +#include "VMS/Queue_impl/PrivateQueue.h" +#include "SSR.h" +#include "SSR_Request_Handlers.h" + + +/*Will get requests to send, to receive, and to create new processors. + * Upon send, check the hash to see if a receive is waiting. + * Upon receive, check hash to see if a send has already happened. + * When other is not there, put in. When other is there, the comm. + * completes, which means the receiver P gets scheduled and + * picks up right after the receive request. So make the work-unit + * and put it into the queue of work-units ready to go. + * Other request is create a new Processor, with the function to run in the + * Processor, and initial data. + */ +void +SSR__Request_Handler( VirtProcr *requestingPr, void *_semEnv ) + { SSRSemEnv *semEnv; + VMSReqst *req; + SSRSemReq *semReq; + + semEnv = (SSRSemEnv *)_semEnv; + + req = VMS__take_top_request_from( requestingPr ); + + while( req != NULL ) + { + if( VMS__isSemanticReqst( req ) ) + { + semReq = VMS__take_sem_reqst_from( req ); + if( semReq == NULL ) goto DoneHandlingReqst; + switch( semReq->reqType ) + { + case send_type: handleSendType( semReq, semEnv); + break; + case send_from_to: handleSendFromTo( semReq, semEnv); + break; + case receive_type: handleReceiveType( semReq, semEnv); + break; + case receive_from_to: handleReceiveFromTo(semReq, semEnv); + break; + case transfer_to: handleTransferTo( semReq, semEnv); + SSR__free_semantic_request( semReq ); + break; + case transfer_out: handleTransferOut( semReq, semEnv); + SSR__free_semantic_request( semReq ); + break; + } + //NOTE: freeing semantic request data strucs handled inside these + } + else if( VMS__isCreateReqst( req ) ) //only plugin can add to ready Q + { VirtProcr * + newPr = (VirtProcr *)req->semReqData; + semEnv->numVirtPr += 1; + + //resume procr asked for registration & start new pr + writePrivQ( requestingPr, semEnv->readyVirtProcrQ ); + writePrivQ( newPr, semEnv->readyVirtProcrQ ); + } + else if( VMS__isDissipateReqst( req ) ) + { + //free any semantic data allocated to the virt procr + + //Now, call VMS to free_all AppVP state -- stack and so on + VMS__handle_dissipate_reqst( requestingPr ); + + semEnv->numVirtPr -= 1; + if( semEnv->numVirtPr == 0 ) + { //no more work, so shutdown + VMS__handle_shutdown_reqst( requestingPr ); + } + } + + DoneHandlingReqst: + //Free VMS portion of request, no matter what -- sem request data + // struc instances may still be around.. VMS__free_request doesn't + // affect the semantic request that was carried by it + req = VMS__free_top_and_give_next_request_from( requestingPr ); + } //while( req != NULL ) + } + +//=========================================================================== + + +/*For SSR, scheduling a slave simply takes the next work-unit off the + * ready-to-go work-unit queue and assigns it to the slaveToSched. + *If the ready-to-go work-unit queue is empty, then nothing to schedule + * to the slave -- return FALSE to let Master loop know scheduling that + * slave failed. + */ +VirtProcr * +SSR__schedule_virt_procr( void *_semEnv ) + { VirtProcr *schedPr; + SSRSemEnv *semEnv; + + semEnv = (SSRSemEnv *)_semEnv; + + schedPr = readPrivQ( semEnv->readyVirtProcrQ ); + //Note, using a non-blocking queue -- it returns NULL if queue empty + + return( schedPr ); + } + diff -r 7fd2b56b5694 -r 9172ea309065 SSR_Request_Handlers.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SSR_Request_Handlers.c Wed Sep 01 09:14:56 2010 -0700 @@ -0,0 +1,328 @@ +/* + * Copyright 2010 OpenSourceCodeStewardshipFoundation + * + * Licensed under BSD + */ + +#include +#include +#include + +#include "VMS/VMS.h" +#include "VMS/Queue_impl/PrivateQueue.h" +#include "VMS/Hash_impl/PrivateHash.h" +#include "SSR.h" + + + +//=========================================================================== +// Helpers + +HashEntry * +giveEntryElseInsertReqst( char *key, SSRSemReq *semReq, + HashTable *commHashTbl ) + { HashEntry *entry; + SSRSemReq *waitingReq; + + entry = getEntryFromTable( (char *)key, commHashTbl ); + if( entry == NULL ) + { //no waiting sends or receives, so add this request and exit + addValueIntoTable( key, semReq, commHashTbl ); + return NULL; + } + waitingReq = (SSRSemReq *)entry->content; + if( waitingReq == NULL ) //might happen when last waiting gets paired + { //no waiting sends or receives, so add this request and exit + entry->content = semReq; + return NULL; + } + return entry; + } + + + + +//=========================================================================== +/*The semantic request has the receiving processor and the message type + * + *Note one value in this approach: without the extra VMS layer, + * the send and receive would happen in real time instead of virtual time, + * which would waste real time while one of them waited for other + * + *When successfully pair-up, transfer ownership of the sent data + * to the receiving processor + * + *Messages of a given Type have to be kept separate.. so need a separate + * entry in the hash table for each pair: receivePr, msgType + * + *Also, if same sender sends multiple before any get received, then need to + * stack the sends up -- even if a send waits until it's paired, several + * separate processors can send to the same receiver, and hashing on the + * receive processor, so they will stack up. + */ +void +handleSendType( SSRSemReq *semReq, SSRSemEnv *semEnv ) + { VirtProcr *sendPr, *receivePr; + int key[] = {0,0,0}; + SSRSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; + + receivePr = semReq->receivePr; //For "send", know both send & recv procrs + sendPr = semReq->sendPr; + + //TODO: handle transfer of msg-locs ownership + //TODO: hash table implemented such that using "addEntry" or + // "addValue" to table causes the *value* in old entry to be + // *freed* -- this is bad. Want to stack up values in a linked + // list when multiple have the same key. + + //TODO: use a faster hash function -- see notes in intelligence gather + key[0] = (int)receivePr; + key[1] = (int)(semReq->msgType); + //key[2] acts as the 0 that terminates the string + + entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); + if( entry == NULL ) return; //was just inserted + + waitingReq = (SSRSemReq *)entry->content; + + //At this point, know have waiting request(s) -- either sends or recv + //Note, can only have max of one receive waiting, and cannot have both + // sends and receives waiting (they would have paired off) + // but can have multiple send_type requests waiting (from diff senders) + if( waitingReq->reqType == send_type ) + { //waiting request is another send, so stack this up on list + semReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry; + waitingReq->nextReqInHashEntry = semReq; + //printf("linked requests: %d, %d | ", semReq, waitingReq ); + //printf("type: %d, %d\n", semReq->reqType, waitingReq->reqType ); + return; + } + else + { //waiting request is a receive, so pair it to this send + //first, remove the waiting receive request from the list in entry + entry->content = waitingReq->nextReqInHashEntry; + if( entry->content == NULL ) + { //TODO: mod hash table to double-link, so can delete entry from + // table without hashing the key and looking it up again + deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too + } + + //attach msg that's in this send request to receiving procr + // when comes back from suspend, will have msg in semanticData + receivePr->semanticData = semReq->msg; + + //bring both processors back from suspend + writePrivQ( sendPr, semEnv->readyVirtProcrQ ); + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); + + //don't need semReq anymore -- free it + SSR__free_semantic_request( waitingReq ); + SSR__free_semantic_request( semReq ); + return; + } + } + + +/*Looks like can make single handler for both sends.. + */ +//TODO: combine both send handlers into single handler +void +handleSendFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv) + { VirtProcr *sendPr, *receivePr; + int key[] = {0,0,0}; + SSRSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; + + receivePr = semReq->receivePr; //For "send", know both send & recv procrs + sendPr = semReq->sendPr; + + key[0] = (int)receivePr; + key[1] = (int)sendPr; + //key[2] acts at the 0 that terminates the string + + entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); + if( entry == NULL ) return; //was just inserted + + waitingReq = (SSRSemReq *)entry->content; + + //At this point, know have waiting request(s) -- either sends or recv + if( waitingReq->reqType == send_from_to ) + { printf("\n ERROR: shouldn't be two send from-tos waiting \n"); + } + else + { //waiting request is a receive, so it completes pair with this send + + //remove the waiting receive request from the entry + entry->content = waitingReq->nextReqInHashEntry; + //can only be one waiting req for "from-to" semantics + if( entry->content != NULL ) + { + printf("\nERROR in handleSendFromTo\n"); + printf("waitReq: %d | next req: %d\n", waitingReq, entry->content); + } + deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too + + //attach msg that's in this send request to receiving procr + // when comes back from suspend, will have msg in semanticData + receivePr->semanticData = semReq->msg; + + //bring both processors back from suspend + writePrivQ( sendPr, semEnv->readyVirtProcrQ ); + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); + + //done with requests, so free them + SSR__free_semantic_request( waitingReq ); + SSR__free_semantic_request( semReq ); + return; + } + } + + + +//======================================================= + +/*Removed this one for now, because forces either a search or going to a + * two-level hash table, where one level the key is the receivePr, in the + * other level, the key is the type. + *So, each dest procr that either does a receive_type or that a send_type + * targets it, would have a hash table created just for it and placed + * into the first-level hash table entry for that receive procr. + *Then, doing a receive_type first looks up entry for receive procr in first + * table, gets the type-table out of that entry, and does a second lookup + * in the type-table. + *Doing a receive from-to looks up in the first table, gets the second table + * hashed on "from" procr. + *Doing a receive_any looks up in the first table, then looks to see if + * either of the hash tables have any entries -- would then have to do a + * linear search through the hash-table's array for the first non-empty + * spot + *Yuck. + * + *Alternatively, could keep two hash tables updated all the time -- one that + * does the receive_type and receive_from_to and a second that does + * receive_any -- would only hash the second table by the receive procr. + * When remove from one table, keep back-links to both tables, so can also + * quickly remove from other table. + *Cost is doing two hash-table lookups for every insert. + * If ever add receive_any, looking like this second option easier and even + * less costly. + */ +void +handleReceiveAny( SSRSemReq *semReq, SSRSemEnv *semEnv) + { + + } + + +void +handleReceiveType( SSRSemReq *semReq, SSRSemEnv *semEnv) + { VirtProcr *sendPr, *receivePr; + int key[] = {0,0,0}; + SSRSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; + + receivePr = semReq->receivePr; + + key[0] = (int)receivePr; + key[1] = (int)(semReq->msgType); + //key[2] acts at the 0 that terminates the string + + + entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); + if( entry == NULL ) return; //was just inserted + + waitingReq = (SSRSemReq *)entry->content; + + //At this point, know have waiting request(s) -- should be send(s) + if( waitingReq->reqType == send_type ) + { //waiting request is a send, so pair it with this receive + //first, remove the waiting send request from the list in entry + entry->content = waitingReq->nextReqInHashEntry; + if( entry->content == NULL ) + { deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too + } + + //attach msg that's in the send request to receiving procr + // when comes back from suspend, will have msg in semanticData + receivePr->semanticData = waitingReq->msg; + + //bring both processors back from suspend + writePrivQ( waitingReq->sendPr, semEnv->readyVirtProcrQ ); + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); + + //done with requests, so free them + SSR__free_semantic_request( waitingReq ); + SSR__free_semantic_request( semReq ); + return; + } + printf("\nLang Impl Error: Should never be two waiting receives!\n"); + } + + +/* + */ +void +handleReceiveFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv) + { VirtProcr *sendPr, *receivePr; + int key[] = {0,0,0}; + SSRSemReq *waitingReq; + HashEntry *entry; + HashTable *commHashTbl = semEnv->commHashTbl; + + receivePr = semReq->receivePr; + sendPr = semReq->sendPr; //for receive from-to, know send procr + + key[0] = (int)receivePr; + key[1] = (int)sendPr; + //key[2] acts at the 0 that terminates the string + + entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); + if( entry == NULL ) return; //was just inserted + + waitingReq = (SSRSemReq *)entry->content; + + //At this point, know have waiting request(s) -- should be send(s) + if( waitingReq->reqType == send_from_to ) + { //waiting request is a send, so pair it with this receive + + //For from-to, should only ever be a single reqst waiting tobe paird + entry->content = waitingReq->nextReqInHashEntry; + if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n"); + deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too + + //attach msg that's in the send request to receiving procr + // when comes back from suspend, will have msg in semanticData + receivePr->semanticData = waitingReq->msg; + + //bring both processors back from suspend + writePrivQ( waitingReq->sendPr, semEnv->readyVirtProcrQ ); + writePrivQ( receivePr, semEnv->readyVirtProcrQ ); + + //done with requests, so free them + SSR__free_semantic_request( waitingReq ); + SSR__free_semantic_request( semReq ); + return; + } + printf("\nLang Impl Error: Should never be two waiting receives!\n"); + } + + + +//=============================================== +void +handleTransferTo( SSRSemReq *semReq, SSRSemEnv *semEnv) + { + + } + +void +handleTransferOut( SSRSemReq *semReq, SSRSemEnv *semEnv) + { + + } + + diff -r 7fd2b56b5694 -r 9172ea309065 SSR_Request_Handlers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SSR_Request_Handlers.h Wed Sep 01 09:14:56 2010 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright 2009 OpenSourceStewardshipFoundation.org + * Licensed under GNU General Public License version 2 + * + * Author: seanhalle@yahoo.com + * + */ + +#ifndef _SSR_REQ_H +#define _SSR_REQ_H + +#include "SSR.h" + +/*This header defines everything specific to the SSR semantic plug-in + */ + +void +handleSendType( SSRSemReq *semReq, SSRSemEnv *semEnv); +void +handleSendFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv); +void +handleReceiveAny( SSRSemReq *semReq, SSRSemEnv *semEnv); +void +handleReceiveType( SSRSemReq *semReq, SSRSemEnv *semEnv); +void +handleReceiveFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv); +void +handleTransferTo( SSRSemReq *semReq, SSRSemEnv *semEnv); +void +handleTransferOut( SSRSemReq *semReq, SSRSemEnv *semEnv); + +#endif /* _SSR_REQ_H */ + diff -r 7fd2b56b5694 -r 9172ea309065 SSR_lib.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SSR_lib.c Wed Sep 01 09:14:56 2010 -0700 @@ -0,0 +1,391 @@ +/* + * Copyright 2010 OpenSourceCodeStewardshipFoundation + * + * Licensed under BSD + */ + +#include +#include +#include + +#include "VMS/VMS.h" +#include "SSR.h" +#include "VMS/Queue_impl/PrivateQueue.h" +#include "VMS/Hash_impl/PrivateHash.h" + + +//========================================================================== + +void +SSR__init(); + +void +SSR__init_Seq(); + +void +SSR__init_Helper(); +//========================================================================== + + +/*TODO: Q: dealing with library f()s and DKU vs WT vs FoR + * (still want to do FoR, with time-lines as syntax, could be super cool) + * A: thinking pin the coreLoops for all of BLIS -- let Master arbitrate + * among library, DKU, WT, FoR -- all the patterns in terms of virtual + * processors (or equivalently work-units), so Master picks which virt procr + * from which portions of app (DKU, WT, FoR) onto which sched slots + *Might even do hierarchy of masters -- group of sched slots for each core + * has its own master, that keeps generated work local + * single-reader-single-writer sync everywhere -- no atomic primitives + * Might have the different schedulers talk to each other, to negotiate + * larger-grain sharing of resources, according to predicted critical + * path, and expansion of work + */ + + + +//=========================================================================== + + +/*These are the library functions *called in the application* + * + *There's a pattern for the outside sequential code to interact with the + * VMS_HW code. + *The VMS_HW system is inside a boundary.. every SSR system is in its + * own directory that contains the functions for each of the processor types. + * One of the processor types is the "seed" processor that starts the + * cascade of creating all the processors that do the work. + *So, in the directory is a file called "EntryPoint.c" that contains the + * function, named appropriately to the work performed, that the outside + * sequential code calls. This function follows a pattern: + *1) it calls SSR__init() + *2) it creates the initial data for the seed processor, which is passed + * in to the function + *3) it creates the seed SSR processor, with the data to start it with. + *4) it calls startSSRThenWaitUntilWorkDone + *5) it gets the returnValue from the transfer struc and returns that + * from the function + * + *For now, a new SSR system has to be created via SSR__init every + * time an entry point function is called -- later, might add letting the + * SSR system be created once, and let all the entry points just reuse + * it -- want to be as simple as possible now, and see by using what makes + * sense for later.. + */ + + + +//=========================================================================== + +/*This is the "border crossing" function -- the thing that crosses from the + * outside world, into the VMS_HW world. It initializes and starts up the + * VMS system, then creates one processor from the specified function and + * puts it into the readyQ. From that point, that one function is resp. + * for creating all the other processors, that then create others, and so + * forth. + *When all the processors, including the seed, have dissipated, then this + * function returns. The results will have been written by side-effect via + * pointers read from, or written into initData. + * + *NOTE: no Threads should exist in the outside program that might touch + * any of the data reachable from initData passed in to here + */ +void +SSR__create_seed_procr_and_do_work( VirtProcrFnPtr fnPtr, void *initData ) + { SSRSemEnv *semEnv; + VirtProcr *seedProcr; + + SSR__init(); //uncomment to do multi-thd +// SSR__init_Seq(); //uncomment to debug + + semEnv = _VMSMasterEnv->semanticEnv; + + //SSR starts with one processor, which is put into initial environ, + // and which then calls create() to create more, thereby expanding work + seedProcr = VMS__create_procr( fnPtr, initData ); + + writePrivQ( seedProcr, semEnv->readyVirtProcrQ ); + semEnv->numVirtPr = 1; + + VMS__start_the_work_then_wait_until_done(); //uncomment to do multi-thd +// VMS__start_the_work_then_wait_until_done_Seq(); //uncomment to debug + + SSR__cleanup_after_shutdown(); + } + + +//=========================================================================== + +/*Initializes all the data-structures for a SSR system -- but doesn't + * start it running yet! + * + * + *This sets up the semantic layer over the VMS system + * + *First, calls VMS_Setup, then creates own environment, making it ready + * for creating the seed processor and then starting the work. + */ +void +SSR__init() + { + VMS__init(); + //masterEnv, a global var, now is partially set up by init_VMS + + SSR__init_Helper(); + } + +void +SSR__init_Seq() + { + VMS__init_Seq(); + //masterEnv, a global var, now is partially set up by init_VMS + + SSR__init_Helper(); + } + +void +SSR__init_Helper() + { SSRSemEnv *semanticEnv; + + //Hook up the semantic layer's plug-ins to the Master virt procr + _VMSMasterEnv->requestHandler = &SSR__Request_Handler; + _VMSMasterEnv->slaveScheduler = &SSR__schedule_virt_procr; + + //create the semantic layer's environment (all its data) and add to + // the master environment + semanticEnv = malloc( sizeof( SSRSemEnv ) ); + _VMSMasterEnv->semanticEnv = semanticEnv; + + //create the ready queue, hash tables used for pairing send to receive + // and so forth + //TODO: add hash tables for pairing sends with receives, and + // initialize the data ownership system + semanticEnv->readyVirtProcrQ = makePrivQ(); + semanticEnv->commHashTbl = makeHashTable( 1<<16, NULL ); //start big + } + + +/*Frees any memory allocated by SSR__init() then calls VMS__shutdown + */ +void +SSR__cleanup_after_shutdown() + { SSRSemEnv *semanticEnv; + + semanticEnv = _VMSMasterEnv->semanticEnv; + +//TODO: double check all sem env locations freed + free( semanticEnv->readyVirtProcrQ->startOfData ); + free( semanticEnv->readyVirtProcrQ ); + freeHashTable( semanticEnv->commHashTbl ); + free( _VMSMasterEnv->semanticEnv ); + VMS__cleanup_after_shutdown(); + } + + +//=========================================================================== + +/* + */ +inline VirtProcr * +SSR__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, + VirtProcr *creatingPr ) + { VirtProcr *newPr; + + newPr = VMS__create_procr( fnPtr, initData ); + + //After create, have to send request to plugin for any sem env + // modifications -- such as putting the new procr into the ready Q + //Need a processor to "animate" the creation -- it's one the register + // request is attached to, and one suspended in order to send req + // to plugin + VMS__send_register_new_procr_request( newPr, creatingPr ); + + return newPr; + } + + +inline void +SSR__dissipate_procr( VirtProcr *procrToDissipate ) + { + VMS__dissipate_procr( procrToDissipate ); + } + + +//=========================================================================== + +void * +SSR__malloc_size_to( int numBytes, VirtProcr *ownerPr ) + { +//TODO: Put in the ownership system from DKU -- have it working, just adapt +// it to here + return malloc( numBytes ); + } + + +void +SSR__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, + VirtProcr *newOwnerPr ) + { + + } + + +void +SSR__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ) + { + + } + + +void +SSR__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ) + { + + } + + +/*Causes the SSR system to remove internal ownership, so data won't be + * freed when SSR shuts down, and will persist in the external program. + * + *Must be called from the processor that currently owns the data. + * + *IMPL: Transferring ownership touches two different virtual processor's + * state -- which means it has to be done carefully -- the VMS rules for + * semantic layers say that a work-unit is only allowed to touch the + * virtual processor it is part of, and that only a single work-unit per + * virtual processor be scheduled to a slave at a time. So, this has to + * modify the virtual processor that owns the work-unit that called this + * function, then create a request to have the other processor modified. + *However, in this case, the TO processor is the outside, and transfers + * are only allowed to be called by the giver-upper, so can mark caller of + * this function as no longer owner, and return -- done. + */ +void +SSR__transfer_ownership_to_outside( void *data ) + { + //TODO: removeAllOwnersFrom( data ); + } + + +//=========================================================================== + +void +SSR__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, + VirtProcr *receivePr) + { SSRSemReq *reqData; + + reqData = malloc( sizeof(SSRSemReq) ); + reqData->receivePr = receivePr; + reqData->sendPr = sendPr; + reqData->reqType = send_type; + reqData->msgType = type; + reqData->msg = msg; + reqData->nextReqInHashEntry = NULL; + + //On ownership -- remove inside the send and let ownership sit in limbo + // as a potential in an entry in the hash table, when this receive msg + // gets paired to a send, the ownership gets added to the receivePr -- + // the next work-unit in the receivePr's trace will have ownership. + VMS__add_sem_request( reqData, sendPr ); + VMS__suspend_procr( sendPr ); //will suspend then resume and continue + + //When come back from suspend, no longer own data reachable from msg + //TODO: release ownership here + } + +void +SSR__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr ) + { SSRSemReq *reqData; + + //hash on the receiver, 'cause always know it, but sometimes want to + // receive from anonymous sender + + reqData = malloc( sizeof(SSRSemReq) ); + reqData->receivePr = receivePr; + reqData->sendPr = sendPr; + reqData->reqType = send_from_to; + reqData->msg = msg; + reqData->nextReqInHashEntry = NULL; + + //On ownership -- remove inside the send and let ownership sit in limbo + // as a potential in an entry in the hash table, when this receive msg + // gets paired to a send, the ownership gets added to the receivePr -- + // the next work-unit in the receivePr's trace will have ownership. + VMS__add_sem_request( reqData, sendPr ); + VMS__suspend_procr( sendPr ); //will suspend then resume and continue + + //When come back from suspend, no longer own data reachable from msg + //TODO: release ownership here + } + + +//=========================================================================== + +void * +SSR__receive_any_to( VirtProcr *receivePr ) + { + + } + +void * +SSR__receive_type_to( const int type, VirtProcr *receivePr ) + { void *msg; + SSRSemReq *reqData; + + reqData = malloc( sizeof(SSRSemReq) ); + reqData->receivePr = receivePr; + reqData->reqType = receive_type; + reqData->msgType = type; + reqData->nextReqInHashEntry = NULL; + + VMS__add_sem_request( reqData, receivePr ); + VMS__suspend_procr( receivePr ); + msg = receivePr->semanticData; + return msg; + } + + + +/*Call this at point receiving virt pr wants in-coming data. + * + *The reason receivePr must call this is that it modifies the receivPr + * loc structure directly -- and the VMS rules state a virtual processor + * loc structure can only be modified by itself. + */ +void * +SSR__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ) + { SSRSemReq *reqData; + + //hash on the receiver, 'cause always know it, but sometimes want to + // receive from anonymous sender + + reqData = malloc( sizeof(SSRSemReq) ); + reqData->receivePr = receivePr; + reqData->sendPr = sendPr; + reqData->reqType = receive_from_to; + reqData->nextReqInHashEntry = NULL; + + //On ownership -- remove inside the send after receive successful. + // Below, add ownership when come back from suspend + //Reason: Thinking of impl ownership mech such that it automatically + // frees any data has no owners -- so have to add receiver before + // remove sender + VMS__add_sem_request( reqData, receivePr ); + //TODO: add ownership of locs reachable from msg inside reqst handler + VMS__suspend_procr( receivePr ); //will suspend then resume and continue + + //When come back from suspend, the msg data is in receivePr->semData + return receivePr->semanticData; + } + + +//=========================================================================== + +/*Just thin wrapper for now -- semantic request is still a simple thing + * (July 3, 2010) + */ +inline void +SSR__free_semantic_request( SSRSemReq *semReq ) + { + free( semReq ); + } + diff -r 7fd2b56b5694 -r 9172ea309065 VMSHW.h --- a/VMSHW.h Wed Sep 01 08:34:48 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * Copyright 2009 OpenSourceStewardshipFoundation.org - * Licensed under GNU General Public License version 2 - * - * Author: seanhalle@yahoo.com - * - */ - -#ifndef _VMSHW_H -#define _VMSHW_H - -#include "VMS/Queue_impl/PrivateQueue.h" -#include "VMS/Hash_impl/PrivateHash.h" -#include "VMS/VMS.h" - -/*This header defines everything specific to the VMSHW semantic plug-in - */ -typedef struct _VMSHWSemReq VMSHWSemReq; - - -/*Semantic layer-specific data sent inside a request from lib called in app - * to request handler called in MasterLoop - */ -enum VMSHWReqType - { - send_type = 1, - send_from_to, - receive_any, //order and grouping matter -- send before receive - receive_type, // and receive_any first of the receives -- Handlers - receive_from_to,// rely upon this ordering of enum - transfer_to, - transfer_out - }; - -struct _VMSHWSemReq - { enum VMSHWReqType reqType; - VirtProcr *sendPr; - VirtProcr *receivePr; - int32 msgType; - void *msg; - VMSHWSemReq *nextReqInHashEntry; - } -/* VMSHWSemReq */; - -typedef struct - { - PrivQueueStruc *readyVirtProcrQ; - HashTable *commHashTbl; - int numVirtPr; - } -VMSHWSemEnv; - - -//=========================================================================== - -void -VMSHW__create_seed_procr_and_do_work( VirtProcrFnPtr fn, void *initData ); - -//======================= - -void -VMSHW__init(); - -void -VMSHW__cleanup_after_shutdown(); - -//======================= - -inline VirtProcr * -VMSHW__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, - VirtProcr *creatingPr ); - -void -VMSHW__dissipate_procr( VirtProcr *procrToDissipate ); - -//======================= -void * -VMSHW__malloc_size_to( int numBytes, VirtProcr *ownerPr ); - -void -VMSHW__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, - VirtProcr *newOwnerPr ); - -void -VMSHW__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ); - -void -VMSHW__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ); - -void -VMSHW__transfer_ownership_to_outside( void *dataToTransferOwnershipOf ); - - - -//======================= -void -VMSHW__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, - VirtProcr *receivePr); - -void -VMSHW__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr); - -void * -VMSHW__receive_type_to( const int type, VirtProcr *receivePr ); - -void * -VMSHW__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ); - - -//======================= - -void -VMSHW__free_semantic_request( VMSHWSemReq *semReq ); - - -//========================= Internal use only ============================= -void -VMSHW__Request_Handler( VirtProcr *requestingPr, void *_semEnv ); - -VirtProcr * -VMSHW__schedule_virt_procr( void *_semEnv ); - - -#endif /* _VMSHW_H */ - diff -r 7fd2b56b5694 -r 9172ea309065 VMSHW_PluginFns.c --- a/VMSHW_PluginFns.c Wed Sep 01 08:34:48 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * Copyright 2010 OpenSourceCodeStewardshipFoundation - * - * Licensed under BSD - */ - -#include -#include -#include - -#include "VMS/Queue_impl/PrivateQueue.h" -#include "VMSHW.h" -#include "VMSHW_Request_Handlers.h" - - -/*Will get requests to send, to receive, and to create new processors. - * Upon send, check the hash to see if a receive is waiting. - * Upon receive, check hash to see if a send has already happened. - * When other is not there, put in. When other is there, the comm. - * completes, which means the receiver P gets scheduled and - * picks up right after the receive request. So make the work-unit - * and put it into the queue of work-units ready to go. - * Other request is create a new Processor, with the function to run in the - * Processor, and initial data. - */ -void -VMSHW__Request_Handler( VirtProcr *requestingPr, void *_semEnv ) - { VMSHWSemEnv *semEnv; - VMSReqst *req; - VMSHWSemReq *semReq; - - semEnv = (VMSHWSemEnv *)_semEnv; - - req = VMS__take_top_request_from( requestingPr ); - - while( req != NULL ) - { - if( VMS__isSemanticReqst( req ) ) - { - semReq = VMS__take_sem_reqst_from( req ); - if( semReq == NULL ) goto DoneHandlingReqst; - switch( semReq->reqType ) - { - case send_type: handleSendType( semReq, semEnv); - break; - case send_from_to: handleSendFromTo( semReq, semEnv); - break; - case receive_type: handleReceiveType( semReq, semEnv); - break; - case receive_from_to: handleReceiveFromTo(semReq, semEnv); - break; - case transfer_to: handleTransferTo( semReq, semEnv); - VMSHW__free_semantic_request( semReq ); - break; - case transfer_out: handleTransferOut( semReq, semEnv); - VMSHW__free_semantic_request( semReq ); - break; - } - //NOTE: freeing semantic request data strucs handled inside these - } - else if( VMS__isCreateReqst( req ) ) //only plugin can add to ready Q - { VirtProcr * - newPr = (VirtProcr *)req->semReqData; - semEnv->numVirtPr += 1; - - //resume procr asked for registration & start new pr - writePrivQ( requestingPr, semEnv->readyVirtProcrQ ); - writePrivQ( newPr, semEnv->readyVirtProcrQ ); - } - else if( VMS__isDissipateReqst( req ) ) - { - //free any semantic data allocated to the virt procr - - //Now, call VMS to free_all AppVP state -- stack and so on - VMS__handle_dissipate_reqst( requestingPr ); - - semEnv->numVirtPr -= 1; - if( semEnv->numVirtPr == 0 ) - { //no more work, so shutdown - VMS__handle_shutdown_reqst( requestingPr ); - } - } - - DoneHandlingReqst: - //Free VMS portion of request, no matter what -- sem request data - // struc instances may still be around.. VMS__free_request doesn't - // affect the semantic request that was carried by it - req = VMS__free_top_and_give_next_request_from( requestingPr ); - } //while( req != NULL ) - } - -//=========================================================================== - - -/*For VMSHW, scheduling a slave simply takes the next work-unit off the - * ready-to-go work-unit queue and assigns it to the slaveToSched. - *If the ready-to-go work-unit queue is empty, then nothing to schedule - * to the slave -- return FALSE to let Master loop know scheduling that - * slave failed. - */ -VirtProcr * -VMSHW__schedule_virt_procr( void *_semEnv ) - { VirtProcr *schedPr; - VMSHWSemEnv *semEnv; - - semEnv = (VMSHWSemEnv *)_semEnv; - - schedPr = readPrivQ( semEnv->readyVirtProcrQ ); - //Note, using a non-blocking queue -- it returns NULL if queue empty - - return( schedPr ); - } - diff -r 7fd2b56b5694 -r 9172ea309065 VMSHW_Request_Handlers.c --- a/VMSHW_Request_Handlers.c Wed Sep 01 08:34:48 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ -/* - * Copyright 2010 OpenSourceCodeStewardshipFoundation - * - * Licensed under BSD - */ - -#include -#include -#include - -#include "VMS/VMS.h" -#include "VMS/Queue_impl/PrivateQueue.h" -#include "VMS/Hash_impl/PrivateHash.h" -#include "VMSHW.h" - - - -//=========================================================================== -// Helpers - -HashEntry * -giveEntryElseInsertReqst( char *key, VMSHWSemReq *semReq, - HashTable *commHashTbl ) - { HashEntry *entry; - VMSHWSemReq *waitingReq; - - entry = getEntryFromTable( (char *)key, commHashTbl ); - if( entry == NULL ) - { //no waiting sends or receives, so add this request and exit - addValueIntoTable( key, semReq, commHashTbl ); - return NULL; - } - waitingReq = (VMSHWSemReq *)entry->content; - if( waitingReq == NULL ) //might happen when last waiting gets paired - { //no waiting sends or receives, so add this request and exit - entry->content = semReq; - return NULL; - } - return entry; - } - - - - -//=========================================================================== -/*The semantic request has the receiving processor and the message type - * - *Note one value in this approach: without the extra VMS layer, - * the send and receive would happen in real time instead of virtual time, - * which would waste real time while one of them waited for other - * - *When successfully pair-up, transfer ownership of the sent data - * to the receiving processor - * - *Messages of a given Type have to be kept separate.. so need a separate - * entry in the hash table for each pair: receivePr, msgType - * - *Also, if same sender sends multiple before any get received, then need to - * stack the sends up -- even if a send waits until it's paired, several - * separate processors can send to the same receiver, and hashing on the - * receive processor, so they will stack up. - */ -void -handleSendType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv ) - { VirtProcr *sendPr, *receivePr; - int key[] = {0,0,0}; - VMSHWSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - receivePr = semReq->receivePr; //For "send", know both send & recv procrs - sendPr = semReq->sendPr; - - //TODO: handle transfer of msg-locs ownership - //TODO: hash table implemented such that using "addEntry" or - // "addValue" to table causes the *value* in old entry to be - // *freed* -- this is bad. Want to stack up values in a linked - // list when multiple have the same key. - - //TODO: use a faster hash function -- see notes in intelligence gather - key[0] = (int)receivePr; - key[1] = (int)(semReq->msgType); - //key[2] acts as the 0 that terminates the string - - entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VMSHWSemReq *)entry->content; - - //At this point, know have waiting request(s) -- either sends or recv - //Note, can only have max of one receive waiting, and cannot have both - // sends and receives waiting (they would have paired off) - // but can have multiple send_type requests waiting (from diff senders) - if( waitingReq->reqType == send_type ) - { //waiting request is another send, so stack this up on list - semReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry; - waitingReq->nextReqInHashEntry = semReq; - //printf("linked requests: %d, %d | ", semReq, waitingReq ); - //printf("type: %d, %d\n", semReq->reqType, waitingReq->reqType ); - return; - } - else - { //waiting request is a receive, so pair it to this send - //first, remove the waiting receive request from the list in entry - entry->content = waitingReq->nextReqInHashEntry; - if( entry->content == NULL ) - { //TODO: mod hash table to double-link, so can delete entry from - // table without hashing the key and looking it up again - deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too - } - - //attach msg that's in this send request to receiving procr - // when comes back from suspend, will have msg in semanticData - receivePr->semanticData = semReq->msg; - - //bring both processors back from suspend - writePrivQ( sendPr, semEnv->readyVirtProcrQ ); - writePrivQ( receivePr, semEnv->readyVirtProcrQ ); - - //don't need semReq anymore -- free it - VMSHW__free_semantic_request( waitingReq ); - VMSHW__free_semantic_request( semReq ); - return; - } - } - - -/*Looks like can make single handler for both sends.. - */ -//TODO: combine both send handlers into single handler -void -handleSendFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) - { VirtProcr *sendPr, *receivePr; - int key[] = {0,0,0}; - VMSHWSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - receivePr = semReq->receivePr; //For "send", know both send & recv procrs - sendPr = semReq->sendPr; - - key[0] = (int)receivePr; - key[1] = (int)sendPr; - //key[2] acts at the 0 that terminates the string - - entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VMSHWSemReq *)entry->content; - - //At this point, know have waiting request(s) -- either sends or recv - if( waitingReq->reqType == send_from_to ) - { printf("\n ERROR: shouldn't be two send from-tos waiting \n"); - } - else - { //waiting request is a receive, so it completes pair with this send - - //remove the waiting receive request from the entry - entry->content = waitingReq->nextReqInHashEntry; - //can only be one waiting req for "from-to" semantics - if( entry->content != NULL ) - { - printf("\nERROR in handleSendFromTo\n"); - printf("waitReq: %d | next req: %d\n", waitingReq, entry->content); - } - deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too - - //attach msg that's in this send request to receiving procr - // when comes back from suspend, will have msg in semanticData - receivePr->semanticData = semReq->msg; - - //bring both processors back from suspend - writePrivQ( sendPr, semEnv->readyVirtProcrQ ); - writePrivQ( receivePr, semEnv->readyVirtProcrQ ); - - //done with requests, so free them - VMSHW__free_semantic_request( waitingReq ); - VMSHW__free_semantic_request( semReq ); - return; - } - } - - - -//======================================================= - -/*Removed this one for now, because forces either a search or going to a - * two-level hash table, where one level the key is the receivePr, in the - * other level, the key is the type. - *So, each dest procr that either does a receive_type or that a send_type - * targets it, would have a hash table created just for it and placed - * into the first-level hash table entry for that receive procr. - *Then, doing a receive_type first looks up entry for receive procr in first - * table, gets the type-table out of that entry, and does a second lookup - * in the type-table. - *Doing a receive from-to looks up in the first table, gets the second table - * hashed on "from" procr. - *Doing a receive_any looks up in the first table, then looks to see if - * either of the hash tables have any entries -- would then have to do a - * linear search through the hash-table's array for the first non-empty - * spot - *Yuck. - * - *Alternatively, could keep two hash tables updated all the time -- one that - * does the receive_type and receive_from_to and a second that does - * receive_any -- would only hash the second table by the receive procr. - * When remove from one table, keep back-links to both tables, so can also - * quickly remove from other table. - *Cost is doing two hash-table lookups for every insert. - * If ever add receive_any, looking like this second option easier and even - * less costly. - */ -void -handleReceiveAny( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) - { - - } - - -void -handleReceiveType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) - { VirtProcr *sendPr, *receivePr; - int key[] = {0,0,0}; - VMSHWSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - receivePr = semReq->receivePr; - - key[0] = (int)receivePr; - key[1] = (int)(semReq->msgType); - //key[2] acts at the 0 that terminates the string - - - entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VMSHWSemReq *)entry->content; - - //At this point, know have waiting request(s) -- should be send(s) - if( waitingReq->reqType == send_type ) - { //waiting request is a send, so pair it with this receive - //first, remove the waiting send request from the list in entry - entry->content = waitingReq->nextReqInHashEntry; - if( entry->content == NULL ) - { deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too - } - - //attach msg that's in the send request to receiving procr - // when comes back from suspend, will have msg in semanticData - receivePr->semanticData = waitingReq->msg; - - //bring both processors back from suspend - writePrivQ( waitingReq->sendPr, semEnv->readyVirtProcrQ ); - writePrivQ( receivePr, semEnv->readyVirtProcrQ ); - - //done with requests, so free them - VMSHW__free_semantic_request( waitingReq ); - VMSHW__free_semantic_request( semReq ); - return; - } - printf("\nLang Impl Error: Should never be two waiting receives!\n"); - } - - -/* - */ -void -handleReceiveFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) - { VirtProcr *sendPr, *receivePr; - int key[] = {0,0,0}; - VMSHWSemReq *waitingReq; - HashEntry *entry; - HashTable *commHashTbl = semEnv->commHashTbl; - - receivePr = semReq->receivePr; - sendPr = semReq->sendPr; //for receive from-to, know send procr - - key[0] = (int)receivePr; - key[1] = (int)sendPr; - //key[2] acts at the 0 that terminates the string - - entry = giveEntryElseInsertReqst( key, semReq, commHashTbl); - if( entry == NULL ) return; //was just inserted - - waitingReq = (VMSHWSemReq *)entry->content; - - //At this point, know have waiting request(s) -- should be send(s) - if( waitingReq->reqType == send_from_to ) - { //waiting request is a send, so pair it with this receive - - //For from-to, should only ever be a single reqst waiting tobe paird - entry->content = waitingReq->nextReqInHashEntry; - if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n"); - deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too - - //attach msg that's in the send request to receiving procr - // when comes back from suspend, will have msg in semanticData - receivePr->semanticData = waitingReq->msg; - - //bring both processors back from suspend - writePrivQ( waitingReq->sendPr, semEnv->readyVirtProcrQ ); - writePrivQ( receivePr, semEnv->readyVirtProcrQ ); - - //done with requests, so free them - VMSHW__free_semantic_request( waitingReq ); - VMSHW__free_semantic_request( semReq ); - return; - } - printf("\nLang Impl Error: Should never be two waiting receives!\n"); - } - - - -//=============================================== -void -handleTransferTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) - { - - } - -void -handleTransferOut( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv) - { - - } - - diff -r 7fd2b56b5694 -r 9172ea309065 VMSHW_Request_Handlers.h --- a/VMSHW_Request_Handlers.h Wed Sep 01 08:34:48 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright 2009 OpenSourceStewardshipFoundation.org - * Licensed under GNU General Public License version 2 - * - * Author: seanhalle@yahoo.com - * - */ - -#ifndef _VMSHW_REQ_H -#define _VMSHW_REQ_H - -#include "VMSHW.h" - -/*This header defines everything specific to the VMSHW semantic plug-in - */ - -void -handleSendType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); -void -handleSendFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); -void -handleReceiveAny( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); -void -handleReceiveType( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); -void -handleReceiveFromTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); -void -handleTransferTo( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); -void -handleTransferOut( VMSHWSemReq *semReq, VMSHWSemEnv *semEnv); - -#endif /* _VMSHW_REQ_H */ - diff -r 7fd2b56b5694 -r 9172ea309065 VMSHW_lib.c --- a/VMSHW_lib.c Wed Sep 01 08:34:48 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,391 +0,0 @@ -/* - * Copyright 2010 OpenSourceCodeStewardshipFoundation - * - * Licensed under BSD - */ - -#include -#include -#include - -#include "VMS/VMS.h" -#include "VMSHW.h" -#include "VMS/Queue_impl/PrivateQueue.h" -#include "VMS/Hash_impl/PrivateHash.h" - - -//========================================================================== - -void -VMSHW__init(); - -void -VMSHW__init_Seq(); - -void -VMSHW__init_Helper(); -//========================================================================== - - -/*TODO: Q: dealing with library f()s and DKU vs WT vs FoR - * (still want to do FoR, with time-lines as syntax, could be super cool) - * A: thinking pin the coreLoops for all of BLIS -- let Master arbitrate - * among library, DKU, WT, FoR -- all the patterns in terms of virtual - * processors (or equivalently work-units), so Master picks which virt procr - * from which portions of app (DKU, WT, FoR) onto which sched slots - *Might even do hierarchy of masters -- group of sched slots for each core - * has its own master, that keeps generated work local - * single-reader-single-writer sync everywhere -- no atomic primitives - * Might have the different schedulers talk to each other, to negotiate - * larger-grain sharing of resources, according to predicted critical - * path, and expansion of work - */ - - - -//=========================================================================== - - -/*These are the library functions *called in the application* - * - *There's a pattern for the outside sequential code to interact with the - * VMS_HW code. - *The VMS_HW system is inside a boundary.. every VMSHW system is in its - * own directory that contains the functions for each of the processor types. - * One of the processor types is the "seed" processor that starts the - * cascade of creating all the processors that do the work. - *So, in the directory is a file called "EntryPoint.c" that contains the - * function, named appropriately to the work performed, that the outside - * sequential code calls. This function follows a pattern: - *1) it calls VMSHW__init() - *2) it creates the initial data for the seed processor, which is passed - * in to the function - *3) it creates the seed VMSHW processor, with the data to start it with. - *4) it calls startVMSHWThenWaitUntilWorkDone - *5) it gets the returnValue from the transfer struc and returns that - * from the function - * - *For now, a new VMSHW system has to be created via VMSHW__init every - * time an entry point function is called -- later, might add letting the - * VMSHW system be created once, and let all the entry points just reuse - * it -- want to be as simple as possible now, and see by using what makes - * sense for later.. - */ - - - -//=========================================================================== - -/*This is the "border crossing" function -- the thing that crosses from the - * outside world, into the VMS_HW world. It initializes and starts up the - * VMS system, then creates one processor from the specified function and - * puts it into the readyQ. From that point, that one function is resp. - * for creating all the other processors, that then create others, and so - * forth. - *When all the processors, including the seed, have dissipated, then this - * function returns. The results will have been written by side-effect via - * pointers read from, or written into initData. - * - *NOTE: no Threads should exist in the outside program that might touch - * any of the data reachable from initData passed in to here - */ -void -VMSHW__create_seed_procr_and_do_work( VirtProcrFnPtr fnPtr, void *initData ) - { VMSHWSemEnv *semEnv; - VirtProcr *seedProcr; - - VMSHW__init(); //uncomment to do multi-thd -// VMSHW__init_Seq(); //uncomment to debug - - semEnv = _VMSMasterEnv->semanticEnv; - - //VMSHW starts with one processor, which is put into initial environ, - // and which then calls create() to create more, thereby expanding work - seedProcr = VMS__create_procr( fnPtr, initData ); - - writePrivQ( seedProcr, semEnv->readyVirtProcrQ ); - semEnv->numVirtPr = 1; - - VMS__start_the_work_then_wait_until_done(); //uncomment to do multi-thd -// VMS__start_the_work_then_wait_until_done_Seq(); //uncomment to debug - - VMSHW__cleanup_after_shutdown(); - } - - -//=========================================================================== - -/*Initializes all the data-structures for a VMSHW system -- but doesn't - * start it running yet! - * - * - *This sets up the semantic layer over the VMS system - * - *First, calls VMS_Setup, then creates own environment, making it ready - * for creating the seed processor and then starting the work. - */ -void -VMSHW__init() - { - VMS__init(); - //masterEnv, a global var, now is partially set up by init_VMS - - VMSHW__init_Helper(); - } - -void -VMSHW__init_Seq() - { - VMS__init_Seq(); - //masterEnv, a global var, now is partially set up by init_VMS - - VMSHW__init_Helper(); - } - -void -VMSHW__init_Helper() - { VMSHWSemEnv *semanticEnv; - - //Hook up the semantic layer's plug-ins to the Master virt procr - _VMSMasterEnv->requestHandler = &VMSHW__Request_Handler; - _VMSMasterEnv->slaveScheduler = &VMSHW__schedule_virt_procr; - - //create the semantic layer's environment (all its data) and add to - // the master environment - semanticEnv = malloc( sizeof( VMSHWSemEnv ) ); - _VMSMasterEnv->semanticEnv = semanticEnv; - - //create the ready queue, hash tables used for pairing send to receive - // and so forth - //TODO: add hash tables for pairing sends with receives, and - // initialize the data ownership system - semanticEnv->readyVirtProcrQ = makePrivQ(); - semanticEnv->commHashTbl = makeHashTable( 1<<16, NULL ); //start big - } - - -/*Frees any memory allocated by VMSHW__init() then calls VMS__shutdown - */ -void -VMSHW__cleanup_after_shutdown() - { VMSHWSemEnv *semanticEnv; - - semanticEnv = _VMSMasterEnv->semanticEnv; - -//TODO: double check all sem env locations freed - free( semanticEnv->readyVirtProcrQ->startOfData ); - free( semanticEnv->readyVirtProcrQ ); - freeHashTable( semanticEnv->commHashTbl ); - free( _VMSMasterEnv->semanticEnv ); - VMS__cleanup_after_shutdown(); - } - - -//=========================================================================== - -/* - */ -inline VirtProcr * -VMSHW__create_procr_with( VirtProcrFnPtr fnPtr, void *initData, - VirtProcr *creatingPr ) - { VirtProcr *newPr; - - newPr = VMS__create_procr( fnPtr, initData ); - - //After create, have to send request to plugin for any sem env - // modifications -- such as putting the new procr into the ready Q - //Need a processor to "animate" the creation -- it's one the register - // request is attached to, and one suspended in order to send req - // to plugin - VMS__send_register_new_procr_request( newPr, creatingPr ); - - return newPr; - } - - -inline void -VMSHW__dissipate_procr( VirtProcr *procrToDissipate ) - { - VMS__dissipate_procr( procrToDissipate ); - } - - -//=========================================================================== - -void * -VMSHW__malloc_size_to( int numBytes, VirtProcr *ownerPr ) - { -//TODO: Put in the ownership system from DKU -- have it working, just adapt -// it to here - return malloc( numBytes ); - } - - -void -VMSHW__transfer_ownership_of_from_to( void *data, VirtProcr *oldOwnerPr, - VirtProcr *newOwnerPr ) - { - - } - - -void -VMSHW__add_ownership_by_to( VirtProcr *newOwnerPr, void *data ) - { - - } - - -void -VMSHW__remove_ownership_by_from( VirtProcr *loserPr, void *dataLosing ) - { - - } - - -/*Causes the VMSHW system to remove internal ownership, so data won't be - * freed when VMSHW shuts down, and will persist in the external program. - * - *Must be called from the processor that currently owns the data. - * - *IMPL: Transferring ownership touches two different virtual processor's - * state -- which means it has to be done carefully -- the VMS rules for - * semantic layers say that a work-unit is only allowed to touch the - * virtual processor it is part of, and that only a single work-unit per - * virtual processor be scheduled to a slave at a time. So, this has to - * modify the virtual processor that owns the work-unit that called this - * function, then create a request to have the other processor modified. - *However, in this case, the TO processor is the outside, and transfers - * are only allowed to be called by the giver-upper, so can mark caller of - * this function as no longer owner, and return -- done. - */ -void -VMSHW__transfer_ownership_to_outside( void *data ) - { - //TODO: removeAllOwnersFrom( data ); - } - - -//=========================================================================== - -void -VMSHW__send_of_type_to( VirtProcr *sendPr, void *msg, const int type, - VirtProcr *receivePr) - { VMSHWSemReq *reqData; - - reqData = malloc( sizeof(VMSHWSemReq) ); - reqData->receivePr = receivePr; - reqData->sendPr = sendPr; - reqData->reqType = send_type; - reqData->msgType = type; - reqData->msg = msg; - reqData->nextReqInHashEntry = NULL; - - //On ownership -- remove inside the send and let ownership sit in limbo - // as a potential in an entry in the hash table, when this receive msg - // gets paired to a send, the ownership gets added to the receivePr -- - // the next work-unit in the receivePr's trace will have ownership. - VMS__add_sem_request( reqData, sendPr ); - VMS__suspend_procr( sendPr ); //will suspend then resume and continue - - //When come back from suspend, no longer own data reachable from msg - //TODO: release ownership here - } - -void -VMSHW__send_from_to( void *msg, VirtProcr *sendPr, VirtProcr *receivePr ) - { VMSHWSemReq *reqData; - - //hash on the receiver, 'cause always know it, but sometimes want to - // receive from anonymous sender - - reqData = malloc( sizeof(VMSHWSemReq) ); - reqData->receivePr = receivePr; - reqData->sendPr = sendPr; - reqData->reqType = send_from_to; - reqData->msg = msg; - reqData->nextReqInHashEntry = NULL; - - //On ownership -- remove inside the send and let ownership sit in limbo - // as a potential in an entry in the hash table, when this receive msg - // gets paired to a send, the ownership gets added to the receivePr -- - // the next work-unit in the receivePr's trace will have ownership. - VMS__add_sem_request( reqData, sendPr ); - VMS__suspend_procr( sendPr ); //will suspend then resume and continue - - //When come back from suspend, no longer own data reachable from msg - //TODO: release ownership here - } - - -//=========================================================================== - -void * -VMSHW__receive_any_to( VirtProcr *receivePr ) - { - - } - -void * -VMSHW__receive_type_to( const int type, VirtProcr *receivePr ) - { void *msg; - VMSHWSemReq *reqData; - - reqData = malloc( sizeof(VMSHWSemReq) ); - reqData->receivePr = receivePr; - reqData->reqType = receive_type; - reqData->msgType = type; - reqData->nextReqInHashEntry = NULL; - - VMS__add_sem_request( reqData, receivePr ); - VMS__suspend_procr( receivePr ); - msg = receivePr->semanticData; - return msg; - } - - - -/*Call this at point receiving virt pr wants in-coming data. - * - *The reason receivePr must call this is that it modifies the receivPr - * loc structure directly -- and the VMS rules state a virtual processor - * loc structure can only be modified by itself. - */ -void * -VMSHW__receive_from_to( VirtProcr *sendPr, VirtProcr *receivePr ) - { VMSHWSemReq *reqData; - - //hash on the receiver, 'cause always know it, but sometimes want to - // receive from anonymous sender - - reqData = malloc( sizeof(VMSHWSemReq) ); - reqData->receivePr = receivePr; - reqData->sendPr = sendPr; - reqData->reqType = receive_from_to; - reqData->nextReqInHashEntry = NULL; - - //On ownership -- remove inside the send after receive successful. - // Below, add ownership when come back from suspend - //Reason: Thinking of impl ownership mech such that it automatically - // frees any data has no owners -- so have to add receiver before - // remove sender - VMS__add_sem_request( reqData, receivePr ); - //TODO: add ownership of locs reachable from msg inside reqst handler - VMS__suspend_procr( receivePr ); //will suspend then resume and continue - - //When come back from suspend, the msg data is in receivePr->semData - return receivePr->semanticData; - } - - -//=========================================================================== - -/*Just thin wrapper for now -- semantic request is still a simple thing - * (July 3, 2010) - */ -inline void -VMSHW__free_semantic_request( VMSHWSemReq *semReq ) - { - free( semReq ); - } -