/* 
  This file contains the routines to handle receiving a message

  Because we don't know the length of messages (at least the long ones with
  tag MPID_PT2PT2_TAG(src) tags), we never post a receive.  Rather, we have
  a MPID_CH_check_incoming routine that looks for headers.  Note that
  messages sent from a source to destination with the MPID_PT2PT2_TAG(src)
  are ordered (we assume that the message-passing system preserves order).

  Possible Improvements:
  This current system does not "prepost" Irecv's, and so, on systems with
  aggressive delivery (like the Paragon), can suffer performance penalties.
  Obvious places for improvements are
     On blocking receives for long messages, post the irecv FIRST.
     If the message is actually short, cancel the receive.
         (potential problem - if the next message from the same source is
         long, it might match (incorrectly) with the posted irecv.  
         Possible fix: use sequence number for each processor pair, with
         the sequence numbers incremented for each message, short or long, 
         and place the sequence number into the tag field)

     For tags/sources/contexts in a specified range, post the irecv with
     at tag synthesized from all of the tag/source/context(/sequence number)
     May need to use cancel if the message is shorter than expected.
     This can be done with both blocking and non-blocking messages.

     Another approach is to generate "go-ahead" messages, to be handled in 
     chsend.c, perhaps by an interrupt-driven receive.  
 */

This is the description of chget's algorithm
/*
    This code provides routines for performing get-operation copies.
    This code allows partial data to be returned; the packet is returned
    to the sender when the transfer is completed (as a control packet).

    A receive get happens in two parts.
    If the recv_id field in the packet is null, then this is the first
    time we've seen this packet.  Otherwise, the recv_id gives us the
    address of the matching receive handle.  

    The address is the address to get from; len_avail is the amount to
    copy.  When the copy is complete, the mode is changed to MPID_PKT_DONE_GET
    and sent back the the sender.

    It turns out that to send the same packet back in the case where the 
    packets are dynamically allocated is a bit too tricky for the current
    implementation.  One possibility is an "in_use" bit; this requires that
    any packet that is returned eventually comes back.  Another is to keep
    track of whether the packet should be free; perhaps by inlining the 
    "DO_GET" code (then we can use the MPID_PKT_RECV_CLR(pkt) call).
    Left as an exercise for the reader.

    Details:
    Short messsages are sent in the usual way, by putting them into the 
    packet itself.  The packet is returned to the sender's avail stack
    with the macro MPID_PKT_SEND_FREE.  

    Long messages are sent in parts.  In the simplest situation, 
    Sender                            Receiver
    (xxx_post_send_long)
    MPID_PKT_DO_GET
    Increment MPID_n_pending
                                      (MPID_xx_do_get, do_get_mem)
                                      receives, processes. 
				      Always return an MPID_PKT_DONE_GET
                                      (even if not done, i.e., in the
				      case of a partial send).  We
				      put the address of the dmpi_recv_handle
				      into the packet (recv_id field).
    (MPID_xx_done_get)				     
    If all of the data has not been
       sent, setup the next bunch of
       data and send an MPID_PKT_CONT_GET
       packet.  
    else
       decrement MPID_n_pending
                                      (MPID_xxx_cont_get) 
				      (if needed)
				      Copy the data, send a 
				      MPID_PKT_DONE_GET message pack
				      with updated info how much
				      data has been copied.

    There are some ways to reduce the number of messages that are sent; 
    for now, we're assuming that the long messages are long enough to
    hide the overhead.  This isn't actually a good assumption, but
    we need to simplify some of the receive code before we can 
    cleanly handle a leaner protocol.

    Note on MPID_CMPL_RECV_GET (completer for get's)
    This is simply a blocking loop over check_incoming until the completer
    field is set to clear (0), since completion happens by receiving 
    additional packets.

    Note the while it might seem unnecessary in the two-copy case (copy into
    and out of shared memory) to send an "I'm done" message to the sender, 
    this will allow us to have the sender maintain their own memory pool and
    to do the return without any shared locks (in the memory pool).
 */
