/// <summary> /// Sends the payload message from the current thread to the thread /// with the destination rank. See MPI_Isend in the MPI2 API. /// </summary> /// <param name="destRank">The destination</param> /// <param name="payload">The message being sent</param> /// <param name="eager"> /// When true, the instructions is automatically marked as complete when /// issued. Thus an MpiWait on the handle returned will be a no-op. /// </param> /// <returns> /// A handle on the send instruction that can be used with a function call /// to <see cref="Wait(SendHandle)" />. /// </returns> public SendHandle SendAsync(int destRank, string payload, bool eager) { ValidateRankArgument("destRank", destRank); AssertProcessCanAccessMpiApi(); Runtime.DetectCollectiveAbort(); // Rule: P_S var instr = new AsyncSendInstruction(Process, Process.GetNextInstructionID(), destRank, payload, eager); Process.AddInstructionToHistory(instr); // Rule: R_SB - Eager (buffered) sends should automatically complete // as soon as the runtime has had an opportunity to do the buffering. // In this case, no actual buffering is needed for string data // in .net so just set the instructions to being completed // Note: Setting these sends to being completed is different than // setting it as matched. This instruction is not yet matched. The // runtime is responsible for deciding which receive to match this // send with. if (eager) { instr.IsCompleted = true; } AddInstructionToPendingQueue(instr); Runtime.NotifyStateChanged(); return(new SendHandle(instr)); }
/// <summary> /// Receives a message from the source process. /// See MPI_Irecv in the MPI2 API. /// </summary> /// <param name="srcRank">The source of the message. Null specifies a "wildcard receive.</param> /// <returns> /// A handle on the receive instruction that can be used with a function call /// to <see cref="Wait(ReceiveHandle)" />. /// </returns> public ReceiveHandle ReceiveAsync(int?srcRank) { if (srcRank.HasValue) { ValidateRankArgument("srcRank", srcRank.Value); } AssertProcessCanAccessMpiApi(); Runtime.DetectCollectiveAbort(); var instr = new AsyncReceiveInstruction(Process, Process.GetNextInstructionID(), srcRank); Process.AddInstructionToHistory(instr); AddInstructionToPendingQueue(instr); Runtime.NotifyStateChanged(); return(new ReceiveHandle(instr)); }
/// <summary>Performs an MPI wait for a matching MpiReceiveAsync call.</summary> private void Wait_impl(Handle handle) { if (handle == null) { throw new ArgumentNullException("handle"); } // Only if they're passing data between processes should this be // possible if (handle.Instruction.Owner != Process) { throw new ArgumentException("handle", "Handle owned by a different process."); } AssertProcessCanAccessMpiApi(); Runtime.DetectCollectiveAbort(); // Rule: P_W var instr = new WaitInstruction(Process, Process.GetNextInstructionID(), handle); Process.AddInstructionToHistory(instr); AddInstructionToPendingQueue(instr); #if SHOW_STORE_BUFFER_VULNERABILITY_BUG // JAM: I originally had this condition here to possibly speed things up // but it ended up causing a Store Buffer Vulnerability race condition. // It's here so that it can be shown as an example // If already finished, lets not bother waiting // Checking this here, even though it's volatile if (!handle.Instruction.IsCompleted) #endif BlockProcessOnInstruction(instr); Runtime.DetectCollectiveAbort(); // Check again after we've been unblocked //Runtime.NotifyStateChanged(); }