void ROUTE_THROUGH_LI_CHANNEL_OUT_CLASS::push(UMF_MESSAGE &outMesg) { // Software expects encoding in terms of bytes while the credit scheme speaks in terms of chunks UINT32 messageLengthBytes = outMesg->GetLength(); UINT32 messageLengthChunks = 1 + ((outMesg->GetLength()) / sizeof(UMF_CHUNK)); // Each chunk takes a header plus one bit for encoding? if (DEBUG_CHANNELIO) { debugLog << endl << "****Outbound Channel "<< this->name << " Sends message " << endl; debugLog << endl << "Base Message length "<< dec << (UINT32) (outMesg->GetLength()) << endl; debugLog << "UMF_CHUNK (bytes) " << sizeof(UMF_CHUNK) << endl; debugLog << "Message Length (bytes) "<< dec << messageLengthBytes << endl; debugLog << "Message Credits (chunks) "<< dec << messageLengthChunks << endl; debugLog << "Channel ID "<< dec << this->channelID << endl; } // For now we will allow the system to deadlock here. What is really needed is an // means of back pressure all the way to the incoming route through. // TODO: Fix this deadlock with better backpressure cooperation among threads acquireCredits(messageLengthChunks); // Recode message for the outbound link and send { outMesg->SetServiceID(this->channelID); outputQ->push(outMesg); } if(DEBUG_CHANNELIO) { debugLog << endl << "****Outbound Route-through Channel "<< this->name << " message complete" << endl; } }
// write void PHYSICAL_CHANNEL_CLASS::Write(UMF_MESSAGE message){ // construct header unsigned char header[UMF_CHUNK_BYTES]; message->EncodeHeader(header); msg_count_out++; fprintf(errfd,"attempting to write msg %d of length %d: %x\n", msg_count_out,message->GetLength(),*header); //write header to pipe serial_port->write((const char *)header, UMF_CHUNK_BYTES); // write message data to pipe // NOTE: hardware demarshaller expects chunk pattern to start from most // significant chunk and end at least significant chunk, so we will // send chunks in reverse order message->StartReverseExtract(); while (message->CanReverseExtract()){ UMF_CHUNK chunk = message->ReverseExtractChunk(); fprintf(errfd,"attempting to write %x\n",chunk); serial_port->write((const char*)&chunk, sizeof(UMF_CHUNK)); } // de-allocate message delete message; fflush(errfd); }
void * QA_PHYSICAL_CHANNEL_CLASS::WriterThread(void *argv) { void ** args = (void**) argv; QA_PHYSICAL_CHANNEL physicalChannel = (QA_PHYSICAL_CHANNEL) args[1]; tbb::concurrent_bounded_queue<UMF_MESSAGE> *incomingQ = &(physicalChannel->writeQ); QA_DEVICE_WRAPPER qaDevice = (QA_DEVICE_WRAPPER) args[0]; while (1) { UMF_MESSAGE message; incomingQ->pop(message); // Check to see if we're being torn down -- this is // done by passing a special message through the writeQ if (message == NULL) { if (!physicalChannel->uninitialized) { cerr << "QA_PHYSICAL_CHANNEL got an unexpected NULL value" << endl; } pthread_exit(0); } // The FPGA side detects NULLs inserted for alignment by looking at the // length field. Having a length of 0 would break the protocol. ASSERTX(message->GetLength() != 0); // construct header UMF_CHUNK header = 0; message->EncodeHeader((unsigned char *)&header); qaDevice->Write(&header, sizeof(header)); size_t n_bytes = message->ExtractBytesLeft(); // Round up to multiple of UMF_CHUNK size n_bytes = (n_bytes + sizeof(UMF_CHUNK) - 1) & ~(sizeof(UMF_CHUNK) - 1); qaDevice->Write(message->ExtractGetRawPtr(), n_bytes); message->ExtractUpdateRawPtr(n_bytes); // de-allocate message delete message; // Flush output channel if there isn't another message ready. if (incomingQ->empty()) { qaDevice->Flush(); } } }
void ROUTE_THROUGH_LI_CHANNEL_IN_CLASS::pushUMF(UMF_MESSAGE &inMesg) { // Software expects encoding in terms of bytes while the credit scheme speaks in terms of chunks UINT32 messageLengthBytes = inMesg->GetLength(); // Length of message already framed in bytes UINT32 messageLengthChunks = 1 + ((inMesg->GetLength()) / sizeof(UMF_CHUNK)); // Each chunk takes a header plus one bit for encoding? if(DEBUG_CHANNELIO) { debugLog << "Channel " << this->name << " is " << this << endl; inMesg->Print(debugLog); debugLog << this->name << " route through acquiring credit " << messageLengthChunks << endl; } // This technically frees our credits. // We need to push the message directly to the the outbound queue. // If the outbound queue doesn't have credit, in theory this push // will block. Currently this case is unhandled, potentially // leading to deadlocks, since the main handler threads are the // ones getting blocked. A better solution needs to check // channelPartner's status and store messages that will be unsent. msgBuffer.push(inMesg); if(DEBUG_CHANNELIO) { debugLog << "****In Route-through Channel " << this->name << " message is complete" << endl; } // Unlike the marshalled LI channels, we do not delete the // outbound message. channelPartner owns the message and is // responsible for deletion. }