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( &divideIntoVectors, 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 - }