static void receiveCapabilityMessage(TransformerCapabilityMessage *message) { EMBX_ERROR err; EMBX_PORT replyPort; MMEReceiverFactory *factory; message->result = MME_NOMEM; /* preliminary result */ /* connect to the reply port */ if (EMBX_SUCCESS != EMBX_Connect(manager->transportHandle, message->portName, &replyPort)) { MME_Assert(0); /* cannot recover */ return; } /* TODO: no lock on this list */ for (factory = manager->factoryList; factory; factory = factory->next) { if (0 == strcmp(factory->transformerType, message->transformerType)) { break; } } message->capability.TransformerInfo_p = (void *) (message->capability.TransformerInfoSize ? message + 1 : 0); message->result = (factory ? factory->getTransformerCapabilityFunc(&message->capability) : MME_UNKNOWN_TRANSFORMER); /* post the reply back again */ err = EMBX_SendMessage(replyPort, message, message->messageSize); MME_Assert(EMBX_SUCCESS == err); /* cannot recover */ err = EMBX_ClosePort(replyPort); MME_Assert(EMBX_SUCCESS == err); /* cannot recover */ }
static MME_ERROR RemoteTransformer_KillCommand(Transformer_t* transformer, MME_CommandId_t commandId) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; MME_ERROR result; EMBX_ERROR err; CommandSlot_t *slot; EMBX_VOID *buffer; TransformerTransformMessage *message; EMBX_PORT replyPort; /* TODO: shouldn't this be asserted! */ if (!remoteTransformer->sendPort.valid) { MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "MME port does not exist\n")); return MME_DRIVER_NOT_INITIALIZED; } /* confirm that the command is actually pending on the companion before we * issue the abort */ slot = &(remoteTransformer->commandSlots[MME_CMDID_GET_COMMAND(commandId)]); if (slot->status != MME_RUNNING || commandId != slot->command->CmdStatus.CmdId) { return MME_INVALID_ARGUMENT; } /* mark the command as complete */ slot->command->CmdStatus.Error = MME_COMMAND_ABORTED; slot->command->CmdStatus.State = MME_COMMAND_FAILED; /* fake up a completed transform request */ result = createTransformMessage(remoteTransformer, slot->command, &buffer); if (result != MME_SUCCESS) { return result; } /* connect to our own reply port */ err = EMBX_Connect(remoteTransformer->super.info->handle, remoteTransformer->replyPort.name, &replyPort); if (EMBX_SUCCESS != err) { return MME_EMBX_ERROR; } /* send the message */ message = (TransformerTransformMessage *) buffer; err = EMBX_SendMessage(replyPort, message, message->messageSize); if (EMBX_SUCCESS != err) { return MME_EMBX_ERROR; } EMBX_ClosePort(replyPort); return MME_SUCCESS; }
static MME_ERROR RemoteTransformer_AbortCommand(Transformer_t* transformer, MME_CommandId_t commandId) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_ERROR err; EMBX_VOID *buffer; TransformerAbortMessage *message; CommandSlot_t *slot; /* TODO: shouldn't this be asserted! */ if (!remoteTransformer->sendPort.valid) { MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "MME port does not exist\n")); return MME_DRIVER_NOT_INITIALIZED; } /* confirm that the command is actually pending on the companion before we * issue the abort */ slot = &(remoteTransformer->commandSlots[MME_CMDID_GET_COMMAND(commandId)]); if (slot->status != MME_RUNNING || commandId != slot->command->CmdStatus.CmdId) { return MME_INVALID_ARGUMENT; } /* Allocate an abort message and send it to the companion side, which disposes the buffer */ buffer = allocBuffer(remoteTransformer, sizeof(TransformerAbortMessage)); if (0 == buffer) { return MME_NOMEM; } /* initialize the message */ message = (TransformerAbortMessage *) buffer; message->id = TMESSID_ABORT; message->messageSize = sizeof(TransformerAbortMessage); message->commandId = commandId; /* post the message */ err = EMBX_SendMessage(remoteTransformer->sendPort.port, message, message->messageSize); if (err != EMBX_SUCCESS) { /* If sending the message did not work, there is nothing we can do. */ MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "EMBX_SendMessage(TransformerAbortMessage) failed, error=%d\n", err)); freeBuffer(remoteTransformer, buffer); return MME_NOMEM; } /* success does not indicate the command has been aborted only * that the request has been sent */ return MME_SUCCESS; }
static void receiveIsAliveMessage(TransformerIsAliveMessage * message) { EMBX_PORT replyPort = EMBX_INVALID_HANDLE_VALUE; EMBX_ERROR err; MMEReceiver **prev = NULL, *receiver = NULL; int id; /* Search each receiver list for a matching handle */ for (id=0; id<MME_NUM_EXECUTION_LOOPS; id++) { if (manager->loopTasksRunning[id]) { EMBX_OS_MUTEX_TAKE(&(manager->receiverListMutexes[id])); /* iterate of the receiver list keeping track of the linkage pointer */ for (prev = &(manager->receiverLists[id]), receiver = *prev; NULL != receiver; prev = &(receiver->next), receiver = *prev) { if (receiver == (void *) (message->mmeHandle)) { /* even Java lets you use labelled jumps to do this ... */ goto double_break; } } EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id])); } else { MME_Assert(0 == manager->loopTasks[id]); MME_Assert(0 == manager->receiverLists[id]); } } double_break: /* WARNING: if receiver is non-NULL we still own receiverListMutexes[id] */ if (NULL != receiver) { replyPort = MME_Receiver_GetReplyPort(receiver); EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id])); /* send the message back to the host */ err = EMBX_SendMessage(replyPort, message, message->messageSize); MME_Assert(EMBX_SUCCESS == err); /* cannot recover */ } else { MME_Info(MME_INFO_MANAGER, ("receiveIsAliveMessage could not find receiver, no reply port available!\n")); } }
void send_thread(void *param) { EMBX_PORT port = (EMBX_PORT)param; EMBX_ERROR res; EMBX_VOID *buffer; EMBX_OS_Delay(5000); EMBX_Alloc(tp,BUFFER_SIZE,&buffer); res = EMBX_SendMessage(port,buffer,BUFFER_SIZE); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("port_thread failed, res = %s\n",error_strings[res])); return; } }
static void receiveTransformerRegisteredMessage(TransformerRegisteredMessage* message) { EMBX_PORT replyPort; EMBX_ERROR embxError; MMEReceiverFactory* factory; message->result = MME_SUCCESS; /* preliminary result */ /* Connect to the reply port. */ embxError = EMBX_ConnectBlock(manager->transportHandle, message->portName, &replyPort); if (EMBX_SUCCESS != embxError) { /* ??? This is a bit of a problem. We cannot connect to the port that we should now send the error message to. */ MME_Info(MME_INFO_MANAGER, ("EMBX_ConnectBlock() to reply port failed, error=%d\n", embxError)); return; } /* Need a lock on this list */ /* Find the right receiver factory. */ factory = manager->factoryList; while (factory && factory->transformerType && strcmp(factory->transformerType, message->transformerType) != 0) { factory = factory->next; } if (factory == NULL) { /* No such factory available. */ MME_Info(MME_INFO_MANAGER, ("No receiver found for %s\n", message->transformerType)); message->result = MME_UNKNOWN_TRANSFORMER; } /* Send the message back with the updated result field */ embxError = EMBX_SendMessage(replyPort, message, message->messageSize); if (EMBX_SUCCESS != embxError) { MME_Info(MME_INFO_MANAGER, ("EMBX_SendMessage() to reply port failed, error=%d\n", embxError)); return; } EMBX_ClosePort(replyPort); }
static MME_ERROR issueTerminateMMEMessages(TransportInfo_t* tpInfo) { EMBX_ERROR err; MME_ERROR res; int i; MME_Assert(manager); MME_Assert(tpInfo); for (i=0; i<4; i++) { char adminPortName[] = "MMECompanionAdmin#0"; EMBX_PORT adminPort; TransformerTerminateMMEMessage *message = NULL; /* Generate the port name we want to examine */ adminPortName[sizeof(adminPortName) - 2] = '0' + i; /* Attempt to connect to the admin port */ err = EMBX_Connect(tpInfo->handle, adminPortName, &adminPort); if (EMBX_PORT_NOT_BIND == err) { continue; }; MME_Assert(EMBX_SUCCESS == err); /* no recovery possible */ /* Allocate the terminate message */ res = createTerminateMMEMessage(tpInfo, &message); MME_Assert(MME_SUCCESS == res); /* no recovery possible */ /* Send the request and disconnect */ err = EMBX_SendMessage(adminPort, message, message->messageSize); MME_Assert(MME_SUCCESS == res); /* no recovery possible */ /* Close the admin port */ err = EMBX_ClosePort(adminPort); MME_Assert(MME_SUCCESS == res); /* no recovery possible */ } return MME_SUCCESS; }
int main() { EMBX_TRANSPORT hTrans; EMBX_PORT bufferpool, consumer, mypoolconnection; EMBX_ERROR err; int i; embxRuntimeInit(); err = EMBX_OpenTransport("shm", &hTrans); assert(EMBX_SUCCESS == err); /* Create the port which will hold the pool of work buffers */ err = EMBX_CreatePort(hTrans, "bufferpool", &bufferpool); assert(EMBX_SUCCESS == err); /* Make a connection to the port we just created so we can inject * empty buffers onto the port's queue as part of the initialization */ err = EMBX_Connect(hTrans, "bufferpool", &mypoolconnection); assert(EMBX_SUCCESS == err); /* Now wait for the consumer port to come into existence and * make a connection to it. */ err = EMBX_ConnectBlock(hTrans, "consumer", &consumer); assert(EMBX_SUCCESS == err); /* Inject empty buffers into the buffer pool */ for(i=0;i<BUFFER_POOL_SIZE;i++) { EMBX_VOID *buffer; err = EMBX_Alloc(hTrans, BUFFER_SIZE, &buffer); assert(EMBX_SUCCESS == err); /* Send empty buffer to the buffer pool port */ err = EMBX_SendMessage(mypoolconnection, buffer, 0); assert(EMBX_SUCCESS == err); } /* We don't need our connection to the buffer pool anymore * so close it down. */ EMBX_ClosePort(mypoolconnection); for(i=0;i<100;i++) { EMBX_RECEIVE_EVENT ev; EMBX_UINT buffersize; /* Jabber ... */ printf("producer: Issuing message %d of 100\n", i+1); /* Get an empty buffer from the pool */ err = EMBX_ReceiveBlock(bufferpool, &ev); assert(EMBX_SUCCESS == err); /* The event size field does not represent the actual * size of the buffer in this case, hence if you need * to find that out use the following. However in this * case where all the buffers are the same known size * it wouldn't be necessary expect as self checking debug. */ err = EMBX_GetBufferSize(ev.data, &buffersize); assert(EMBX_SUCCESS == err); /* Do something to fill the buffer with stuff to be used * by the consumer...... use your imagination ...... */ /* Now send the buffer to the consumer with the real amount * of data in the buffer as the size argument (this can be * less than the buffer size). For this example we assume * the whole buffer contains valid data. */ err = EMBX_SendMessage(consumer, ev.data, buffersize); assert(EMBX_SUCCESS == err); } /* Shut the communication system down. This has the side effect * of causing the consumer to also close down, almost certainly * before outstanding messages have been processed. */ EMBX_ClosePort(bufferpool); EMBX_ClosePort(consumer); EMBX_CloseTransport(hTrans); EMBX_Deinit(); return 0; }
int run_test(void) { EMBX_ERROR res; EMBX_TPINFO tpinfo1; EMBX_BOOL bFailed; EMBX_TRANSPORT tp; EMBX_PORT localPort,remotePort; EMBX_VOID *buffer1,*buffer2; EMBX_FACTORY factory; bFailed = EMBX_FALSE; tp = EMBX_INVALID_HANDLE_VALUE; buffer1 = buffer2 = 0; /* Test 1 */ res = EMBX_SendMessage(EMBX_INVALID_HANDLE_VALUE, buffer1, 0); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test1 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } res = EMBX_RegisterTransport(EMBXLB_loopback_factory,&loopback_config,sizeof(EMBXLB_Config_t),&factory); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Transport Registration failed, res = %s, exiting\n",error_strings[res])); goto skip_remaining_tests; } /* Test 2 */ res = EMBX_Init(); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test2 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 3 */ res = EMBX_GetFirstTransport(&tpinfo1); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test3 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 4 */ res = EMBX_OpenTransport(tpinfo1.name, &tp); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test4 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 5 */ res = EMBX_CreatePort(tp, "testport", &localPort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test5 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 6 */ res = EMBX_Connect(tp, "testport", &remotePort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test6 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 7 */ res = EMBX_Alloc(tp, BUFFER_SIZE, &buffer1); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test7 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 8 */ res = EMBX_SendMessage(tp, buffer1, 0); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test8 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 9 */ res = EMBX_SendMessage(localPort, buffer1, 0); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test9 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 10 */ res = EMBX_SendMessage(remotePort, 0, 0); if(res != EMBX_INVALID_ARGUMENT) { EMBX_Info(EMBX_TRUE, ("Test10 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 11 */ res = EMBX_SendMessage(remotePort, buffer1, BUFFER_SIZE+1); if(res != EMBX_INVALID_ARGUMENT) { EMBX_Info(EMBX_TRUE, ("Test11 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 12 */ res = EMBX_SendMessage(remotePort, buffer1, BUFFER_SIZE); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test12 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 13 - Ensure this allocation happens before buffer1 gets free'd * when the port is closed, so buffer1 and buffer2 will not point to * the same memory which is important for later tests. */ res = EMBX_Alloc(tp, BUFFER_SIZE, &buffer2); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test13 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 14 */ res = EMBX_ClosePort(localPort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test14 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 15 - buffer1 has been freed by test14 so should be garbage */ res = EMBX_SendMessage(remotePort, buffer1, 0); if(res != EMBX_INVALID_ARGUMENT) { EMBX_Info(EMBX_TRUE, ("Test15 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 16 */ res = EMBX_SendMessage(remotePort, buffer2, BUFFER_SIZE); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test16 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 17 */ res = EMBX_ClosePort(remotePort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test17 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 18 */ res = EMBX_CloseTransport(tp); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test18 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 19 */ res = EMBX_Deinit(); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test19 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* These test a different code path to the identical tests done before * EMBX_Init. */ /* Test 20 - Depends on buffer2 not having been freed so we get through * to checking the state of the driver. */ res = EMBX_SendMessage(remotePort, buffer2, 0); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test20 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 21 */ res = EMBX_UnregisterTransport(factory); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test21 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } return bFailed?-1:0; skip_remaining_tests: EMBX_Info(EMBX_TRUE, ("Skipping Remaining Tests\n")); return -1; }
int run_test(void) { EMBX_UINT i; EMBX_ERROR res; EMBX_TPINFO tpinfo1; EMBX_BOOL bFailed; EMBX_PORT localPort,remotePort; EMBX_VOID *buffer1; EMBX_FACTORY factory; EMBX_RECEIVE_EVENT ev; bFailed = EMBX_FALSE; buffer1 = 0; /* Test 1 */ res = EMBX_ReceiveBlock(EMBX_INVALID_HANDLE_VALUE, &ev); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test1 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } res = EMBX_RegisterTransport(EMBXLB_loopback_factory, &loopback_config, sizeof(EMBXLB_Config_t), &factory); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Transport Registration failed, res = %s, exiting\n",error_strings[res])); goto skip_remaining_tests; } /* Test 2 */ res = EMBX_Init(); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test2 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 3 */ res = EMBX_GetFirstTransport(&tpinfo1); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test3 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 4 */ res = EMBX_OpenTransport(tpinfo1.name, &tp); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test4 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 5 */ res = EMBX_CreatePort(tp, "testport", &localPort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test5 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 6 */ res = EMBX_Connect(tp, "testport", &remotePort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test6 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 7 */ res = EMBX_ReceiveBlock(tp, &ev); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test7 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 8 */ res = EMBX_ReceiveBlock(remotePort, &ev); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test8 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 9 */ res = EMBX_ReceiveBlock(localPort, 0); if(res != EMBX_INVALID_ARGUMENT) { EMBX_Info(EMBX_TRUE, ("Test9 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 10 */ res = EMBX_Alloc(tp, BUFFER_SIZE, &buffer1); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test10 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } for(i=0;i<BUFFER_SIZE;i++) { ((unsigned char *)buffer1)[i] = (unsigned char)i; } /* Test 11 */ res = EMBX_SendMessage(remotePort, buffer1, BUFFER_SIZE); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test11 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 12 */ res = EMBX_ReceiveBlock(localPort, &ev); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test12 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } if(ev.handle != EMBX_INVALID_HANDLE_VALUE || ev.offset != 0 || ev.type != EMBX_REC_MESSAGE || ev.size != BUFFER_SIZE) { EMBX_Info(EMBX_TRUE, ("Test13 failed, event structure incorrect\n")); goto skip_remaining_tests; } for(i=0;i<ev.size;i++) { if( ((unsigned char *)ev.data)[i] != (unsigned char)i ) { EMBX_Info(EMBX_TRUE, ("Test13 failed, buffer contents incorrect\n")); bFailed = EMBX_TRUE; break; } } /* Test 13 */ res = EMBX_Free(ev.data); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test13 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } if(!EMBX_OS_ThreadCreate(send_thread, (void *)remotePort, EMBX_DEFAULT_THREAD_PRIORITY, "send")) { EMBX_Info(EMBX_TRUE, ("Unable to create thread\n")); goto skip_remaining_tests; } /* Test 14 */ res = EMBX_ReceiveBlock(localPort, &ev); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test14 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } if(ev.handle != EMBX_INVALID_HANDLE_VALUE || ev.offset != 0 || ev.type != EMBX_REC_MESSAGE || ev.size != BUFFER_SIZE) { EMBX_Info(EMBX_TRUE, ("Test15 failed, event structure incorrect\n")); goto skip_remaining_tests; } /* Test 15 */ res = EMBX_Free(ev.data); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test15 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 16 */ res = EMBX_ClosePort(remotePort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test16 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 17 */ res = EMBX_ClosePort(localPort); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test17 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 18 */ res = EMBX_CloseTransport(tp); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test18 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* Test 19 */ res = EMBX_Deinit(); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test19 failed, res = %s\n",error_strings[res])); goto skip_remaining_tests; } /* These test a different code path to the identical tests done before * EMBX_Init */ /* Test 20 */ res = EMBX_ReceiveBlock(localPort, &ev); if(res != EMBX_INVALID_PORT) { EMBX_Info(EMBX_TRUE, ("Test20 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } /* Test 21 */ res = EMBX_UnregisterTransport(factory); if(res != EMBX_SUCCESS) { EMBX_Info(EMBX_TRUE, ("Test21 failed, res = %s\n",error_strings[res])); bFailed = EMBX_TRUE; } return bFailed?-1:0; skip_remaining_tests: EMBX_Info(EMBX_TRUE, ("Skipping Remaining Tests\n")); return -1; }
static MME_ERROR RemoteTransformer_SendCommand(Transformer_t* transformer, MME_Command_t * commandInfo, CommandSlot_t** slot) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_VOID *buffer; EMBX_ERROR err; MME_CommandStatus_t *status; TransformerTransformMessage *message; MME_ERROR result; int i; MME_CommandCode_t cmdCode = commandInfo->CmdCode; int newCommandIndex; if (!remoteTransformer->sendPort.valid) { MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "MME port does not exist\n")); return MME_INVALID_ARGUMENT; } status = (MME_CommandStatus_t*) &(commandInfo->CmdStatus); MME_Assert(cmdCode == MME_TRANSFORM || cmdCode == MME_SEND_BUFFERS || cmdCode == MME_SET_GLOBAL_TRANSFORM_PARAMS); /* Acquire lock on the transformer's command slots */ EMBX_OS_MUTEX_TAKE(&remoteTransformer->commandSlotLock); if (remoteTransformer->numCommandSlots >= remoteTransformer->maxCommandSlots) { /* no free slot */ EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock); MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "SendCommand: maxCommandSlots overflow\n")); return MME_NOMEM; } /* Find a free command slot so we can memorize parameters */ for (i = 0; i < remoteTransformer->maxCommandSlots && remoteTransformer->commandSlots[remoteTransformer->commandIndex].status != MME_COMMAND_COMPLETED_EVT; i++) { MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "RemoteTransformer: SendCommand: CommandIndex %d is already used\n", remoteTransformer->commandIndex)); remoteTransformer->commandIndex++; if (remoteTransformer->commandIndex >= remoteTransformer->maxCommandSlots) { remoteTransformer->commandIndex = 0; } } if (i >= remoteTransformer->maxCommandSlots) { EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock); MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "SendCommand error: No free command slot found!\n")); return MME_NOMEM; } newCommandIndex = remoteTransformer->commandIndex; /* Generate a unique command ID per transformer */ status->CmdId = MME_CMDID_PACK( (remoteTransformer->super.handle)-MME_TRANSFORMER_HANDLE_PREFIX, newCommandIndex, &(remoteTransformer->commandIDCounter)); MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "RemoteTransformer: SendCommand: code=%d ID=%d slot=%d\n", cmdCode, status->CmdId, newCommandIndex)); /* In order to avoid sending buffers, but then being unable to allocate the transform message, we create and fill in the transform message first */ result = createTransformMessage(remoteTransformer, commandInfo, &buffer); if (result != MME_SUCCESS) { EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock); MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "CreateTransformMsg() failed, result=%d\n", result)); return MME_NOMEM; } /* Setting the command state to FAILED allows us to identify incomplete SendCommand()s at our receiver task. */ status->State = MME_COMMAND_FAILED; /* New command slot entry. Initially, assume that the transform message can't be sent */ status->Error = MME_SUCCESS; remoteTransformer->commandSlots[newCommandIndex].endType = commandInfo->CmdEnd; /* In the moment that the status is not zero, the receiver task regards it as valid */ remoteTransformer->commandSlots[newCommandIndex].command = commandInfo; remoteTransformer->commandSlots[newCommandIndex].waitor = NULL; remoteTransformer->commandSlots[newCommandIndex].status = MME_RUNNING; remoteTransformer->numCommandSlots++; EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock); /* TODO: Should we move the state here or on the companion once the command is * scheduled - I think the latter */ status->State = MME_COMMAND_EXECUTING; message = (TransformerTransformMessage *) buffer; /* Send the message */ err = EMBX_SendMessage(remoteTransformer->sendPort.port, message, message->messageSize); if (err != EMBX_SUCCESS) { /* The message could not be sent. Mark the command slot as incomplete */ MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "EMBX_SendMessage() failed, error=%d\n", err)); /* Mark incomplete command */ status->State = MME_COMMAND_FAILED; freeBuffer(remoteTransformer, buffer); return MME_NOMEM; } else { /* Lost ownership */ buffer = NULL; } *slot = &(remoteTransformer->commandSlots[newCommandIndex]); return MME_SUCCESS; }
static MME_ERROR RemoteTransformer_GetTransformerCapability( Transformer_t *transformer, const char *name, MME_TransformerCapability_t * capability) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; MME_ERROR res = MME_NOMEM; EMBX_TRANSPORT hdl; EMBX_PORT replyPort; int n, messageSize; TransformerCapabilityMessage *message; EMBX_RECEIVE_EVENT event; MME_Assert(remoteTransformer); MME_Assert(name); MME_Assert(capability); hdl = remoteTransformer->super.info->handle; MME_Assert(hdl); /* calculate the size of the capability message */ messageSize = sizeof(*message) + capability->TransformerInfoSize; /* allocate somewhere to store the message we are about to send */ message = allocBuffer(remoteTransformer, messageSize); if (0 == message) { return MME_NOMEM; } /* create a port to be used to reply to this message */ n = sprintf(message->portName, "MMECapability_0x%x", (unsigned) message); MME_Assert(n < EMBX_MAX_PORT_NAME); if (EMBX_SUCCESS != EMBX_CreatePort(hdl, message->portName, &replyPort)) { goto error_recovery_alloc; } /* populate the rest of the message */ message->id = TMESSID_CAPABILITY; message->messageSize = messageSize; strncpy(message->transformerType, name, MME_MAX_TRANSFORMER_NAME); message->transformerType[MME_MAX_TRANSFORMER_NAME - 1] = '\0'; message->capability = *capability; /* send the message and wait for a reply */ if (EMBX_SUCCESS != EMBX_SendMessage(remoteTransformer->adminPort, message, sizeof(*message)) || EMBX_SUCCESS != EMBX_ReceiveBlock(replyPort, &event)) { goto error_recovery_createport; } message = event.data; MME_Assert(event.type == EMBX_REC_MESSAGE); MME_Assert(event.size >= messageSize); MME_Assert(message->id == TMESSID_CAPABILITY); MME_Assert(message->messageSize == messageSize); /* fill in the rest of the message */ res = message->result; message->capability.TransformerInfo_p = capability->TransformerInfo_p; *capability = message->capability; memcpy(capability->TransformerInfo_p, message+1, capability->TransformerInfoSize); /* fall into the clean up code */ error_recovery_createport: (void) EMBX_ClosePort(replyPort); error_recovery_alloc: (void) freeBuffer(remoteTransformer, message); return res; }
static MME_ERROR RemoteTransformer_TermOrKill(Transformer_t* transformer, int doKill) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_ERROR err; EMBX_VOID *buffer; TransformerTerminateMessage *message; MME_ERROR result, res; result = MME_NOMEM; if (!remoteTransformer->sendPort.valid) { DP("MME port does not exist\n"); return MME_INVALID_ARGUMENT; } /* No command must be pending on the companion side */ if (remoteTransformer->numCommandSlots > 0) { DP("RemoteTransformer::Terminate() failed, commands pending\n"); return MME_COMMAND_STILL_EXECUTING; } res = createTerminateMessage(remoteTransformer, 0, &buffer); if (res != MME_SUCCESS) { DP("CreateTerminateMsg() failed, error=%d\n", res); return res; } /* Send the message */ message = (TransformerTerminateMessage *) buffer; DP("Sending %s message @$%08x...\n", message, (doKill ? "kill" : "terminate")); if (doKill) { EMBX_PORT replyPort; /* connect to our own reply port */ err = EMBX_Connect(remoteTransformer->super.info->handle, remoteTransformer->replyPort.name, &replyPort); if (EMBX_SUCCESS != err) { DP("RemoteTransformer_Term(): failed to connect to self\n"); cleanupTerminateMessage(remoteTransformer, message); return MME_EMBX_ERROR; } err = EMBX_SendMessage(replyPort, message, message->messageSize); if (EMBX_SUCCESS != err) { DP("RemoteTransformer_Term(): failed to send message to self\n"); cleanupTerminateMessage(remoteTransformer, message); return MME_EMBX_ERROR; } EMBX_ClosePort(replyPort); } else { err = EMBX_SendMessage(remoteTransformer->adminPort, message, message->messageSize); if (EMBX_SUCCESS != err) { DP("RemoteTransformer_Term(): failed to send message to coprocessor\n"); cleanupTerminateMessage(remoteTransformer, message); return MME_EMBX_ERROR; } } /* lost ownership */ message = NULL; /* Wait for ReceiverThread to terminate itself after receiving the reply message */ DP("Waiting for ReceiverThread to terminate itself...\n"); DP("terminateWasReplied 0x%08x\n", remoteTransformer->terminateWasReplied); EMBX_OS_EVENT_WAIT(&remoteTransformer->terminateWasReplied); if (remoteTransformer->terminationResult != MME_SUCCESS) { DP("Failed to terminate receiver thread properly\n"); return MME_INTERNAL_ERROR; } err = EMBX_OS_ThreadDelete(remoteTransformer->receiverThread); if (err != EMBX_SUCCESS) { DP("EMBX_OS_ThreadDelete() failed, error=d\n", err); } remoteTransformer->receiverThread = NULL; /* Close the MME port */ DP("Close mmePort...\n"); err = EMBX_ClosePort(remoteTransformer->sendPort.port); if (err != EMBX_SUCCESS) { DP("EMBX_ClosePort(mmePort) failed, error=d\n", err); } /* Close the reply port */ DP("Invalidate replyPort...\n"); err = EMBX_InvalidatePort(remoteTransformer->replyPort.port); if (err != EMBX_SUCCESS) { DP("EMBX_InvalidatePort(replyPort) failed, error=%d\n", err); } DP("Close replyPort...\n"); err = EMBX_ClosePort(remoteTransformer->replyPort.port); if (err != EMBX_SUCCESS) { DP("EMBX_ClosePort(replyPort) failed, error=%d\n", err); } remoteTransformer->replyPort.valid = EMBX_FALSE; return MME_SUCCESS; }
static MME_ERROR RemoteTransformer_Init(Transformer_t* transformer, const char* name, MME_TransformerInitParams_t * params, MME_TransformerHandle_t handle, EMBX_BOOL createThread) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_ERROR err; EMBX_RECEIVE_EVENT event; TransformerInitMessage *message = NULL; char receiverThreadName[EMBX_MAX_PORT_NAME+1]; int messageSize,n; MME_ERROR result, res; result = MME_NOMEM; remoteTransformer->super.handle = handle; /* TODO: We should take a copy of our (transformer specific) parameters. These might * be deallocated once the transformer is initialized. */ remoteTransformer->super.initParams = *params; MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: initialising '%s'\n", name)); /* Create the reply port. We use the unique handle to create a unique reply port name.*/ n = sprintf(remoteTransformer->replyPort.name, "MMEReply_0x%x", handle); MME_Assert(n < EMBX_MAX_PORT_NAME); err = EMBX_CreatePort(remoteTransformer->super.info->handle, remoteTransformer->replyPort.name, &remoteTransformer->replyPort.port); if (EMBX_SUCCESS != err) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot create port '%s'\n", remoteTransformer->replyPort.name)); goto embx_error_recovery; } remoteTransformer->replyPort.valid = 1; MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Created port '%s', port 0x%08x\n", remoteTransformer->replyPort.name, (unsigned) remoteTransformer->replyPort.port)); /* Create the init message */ res = createInitMessage(remoteTransformer, name, params, (EMBX_VOID **) &message); if (MME_SUCCESS != res) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot create initialisation message\n")); goto error_recovery; } /* Remember size for check of reply message */ messageSize = message->messageSize; /* Send the message */ err = EMBX_SendMessage(remoteTransformer->adminPort, message, messageSize); if (err != EMBX_SUCCESS) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot set initialisation message\n")); goto embx_error_recovery; } /* Record ownership tranfer (see error_recovery) */ message = NULL; MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Waiting for initialisation reply\n")); /* Wait for an answer from the companion */ err = EMBX_ReceiveBlock(remoteTransformer->replyPort.port, &event); if (EMBX_SUCCESS != err) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Error while waiting for initialisation reply\n")); goto embx_error_recovery; } /* Check if the message is as expected */ message = (TransformerInitMessage *) event.data; MME_Assert(EMBX_REC_MESSAGE == event.type); MME_Assert(event.size >= messageSize); MME_Assert(message && message->id == TMESSID_INIT); if (MME_SUCCESS != message->result) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Error initialising remote transformer\n")); res = message->result; goto error_recovery; } /* The MME successfully created its transformer */ strncpy(remoteTransformer->sendPort.name, message->portName, EMBX_MAX_PORT_NAME); remoteTransformer->sendPort.name[EMBX_MAX_PORT_NAME] = '\0'; remoteTransformer->mmeHandle = message->mmeHandle; MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Connecting to transformer port '%s'\n", remoteTransformer->sendPort.name)); /* Connect to the MME port */ err = EMBX_ConnectBlock(remoteTransformer->super.info->handle, remoteTransformer->sendPort.name, &remoteTransformer->sendPort.port); if (EMBX_SUCCESS != err) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot connect to port '%s'\n", remoteTransformer->sendPort.name)); goto embx_error_recovery; } remoteTransformer->sendPort.valid = 1; MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Connected to port '%s', port 0x%08x\n", remoteTransformer->sendPort.name, (unsigned) remoteTransformer->sendPort.port)); if (createThread) { /* Create our receiver task for the reply port */ sprintf(receiverThreadName, "HostRec%x", handle); MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Creating receiver thread '%s'\n", receiverThreadName)); /* TODO: think about whether we want all the receiver threads to have the same priority */ remoteTransformer->receiverThread = EMBX_OS_ThreadCreate(receiverThread, (void *) remoteTransformer, RECEIVER_TASK_PRIORITY, receiverThreadName); if (EMBX_INVALID_THREAD == remoteTransformer->receiverThread) { MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot create receiver thread '%s'\n", receiverThreadName)); res = MME_NOMEM; goto error_recovery; } MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Created receiver thread '%s', thread 0x%08x\n", receiverThreadName, (unsigned) remoteTransformer->receiverThread)); } /* Cleanup and exit */ cleanupInitMessage(remoteTransformer, message); MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: SUCCESS\n")); return MME_SUCCESS; embx_error_recovery: /* As normal error recovery but map the EMBX error code to a MME error code first */ res = (EMBX_NOMEM == err ? MME_NOMEM : MME_EMBX_ERROR); error_recovery: if (remoteTransformer->mmeHandle) { MME_Assert(message); message->id = TMESSID_TERMINATE; err = EMBX_SendMessage(remoteTransformer->adminPort, message, message->messageSize); if (EMBX_SUCCESS == err) { /* TODO: is blocking really a good idea during error recovery? */ err = EMBX_ReceiveBlock(remoteTransformer->replyPort.port, &event); message = (EMBX_SUCCESS == err ? event.data : NULL); } remoteTransformer->mmeHandle = 0; } if (remoteTransformer->sendPort.valid) { EMBX_ClosePort(remoteTransformer->sendPort.port); remoteTransformer->sendPort.valid = 0; } if (remoteTransformer->replyPort.valid) { EMBX_ClosePort(remoteTransformer->replyPort.port); remoteTransformer->replyPort.valid = 0; } if (message) { cleanupInitMessage(remoteTransformer, message); } return res; }
static MME_ERROR findTransformerWithinTransport(TransportInfo_t *tpInfo, const char *name, EMBX_PORT *adminPort_p) { MME_ERROR res; EMBX_ERROR err; TransformerRegisteredMessage *msg = 0; EMBX_PORT adminPort = 0; MME_UINT i; MME_Assert(manager); MME_Assert(name); MME_Assert(tpInfo); res = createRegisteredMessage(tpInfo, name, &msg); if (MME_SUCCESS != res) { return res; } for (i=0; i<4; i++) { char adminPortName[] = "MMECompanionAdmin#0"; EMBX_RECEIVE_EVENT event; /* generate the port name we want to examine */ adminPortName[sizeof(adminPortName) - 2] = '0' + i; /* attempt to connect to the admin port */ err = EMBX_Connect(tpInfo->handle, adminPortName, &adminPort); if (EMBX_PORT_NOT_BIND == err) { continue; } else if (EMBX_SUCCESS != err) { goto error_recovery; } /* send the request and disconnect from the port */ err = EMBX_SendMessage(adminPort, msg, sizeof(*msg)); if (EMBX_SUCCESS != err) { goto error_recovery; } msg = 0; /* wait for the reply */ /* TIMEOUT SUPPORT: Allow the receive to timeout */ err = EMBX_ReceiveBlockTimeout(tpInfo->replyPort, &event, MME_TRANSFORMER_TIMEOUT); if (EMBX_SUCCESS != err) { goto error_recovery; } MME_Assert(event.type == EMBX_REC_MESSAGE); MME_Assert(event.size == sizeof(*msg)); /* interpret said reply */ msg = event.data; MME_Assert(msg->messageSize == sizeof(*msg)); if (MME_SUCCESS == msg->result) { break; } err = EMBX_ClosePort(adminPort); if (EMBX_SUCCESS != err) { goto error_recovery; } adminPort = 0; } cleanupRegisteredMessage(tpInfo, msg); if (i < 4) { *adminPort_p = adminPort; return MME_SUCCESS; } else { return MME_UNKNOWN_TRANSFORMER; } error_recovery: /* TIMEOUT SUPPORT: Return MME_TRANSFORMER_NOT_RESPONDING if timeout occurs */ res = (EMBX_NOMEM == err ? MME_NOMEM : (EMBX_SYSTEM_TIMEOUT == err ? MME_TRANSFORMER_NOT_RESPONDING : MME_EMBX_ERROR)); if (adminPort) { err = EMBX_ClosePort(adminPort); MME_Assert(EMBX_SUCCESS == err); } if (msg) { cleanupRegisteredMessage(tpInfo, msg); } return res; }
static void receiveInitMessage(TransformerInitMessage * message) { EMBX_ERROR err; EMBX_PORT replyPort; MMEReceiverFactory *factory; MMEReceiver *receiver; MME_ERROR res; message->result = MME_NOMEM; /* preliminary result */ /* Connect to the reply port. */ err = EMBX_ConnectBlock(manager->transportHandle, message->portName, &replyPort); if (err != EMBX_SUCCESS) { /* ??? This is a bit of a problem. We cannot connect to the port that we should now send the error message to. */ MME_Info(MME_INFO_MANAGER, ("EMBX_ConnectBlock() to reply port failed, error=%d\n", err)); return; } /* Need a lock on this list */ /* Find the right receiver factory. */ factory = manager->factoryList; while (factory != NULL && strcmp(factory->transformerType, message->transformerType) != 0) { factory = factory->next; } if (factory == NULL) { /* No such factory available. */ MME_Info(MME_INFO_MANAGER, ("No receiver factory found\n")); res = MME_UNKNOWN_TRANSFORMER; } else { /* Create a receiver object. This will result in the constructors being called as well. */ res = MME_Receiver_Create(factory, &receiver); if (MME_SUCCESS == res) { int id = MME_PRIORITY_TO_ID(message->priority); res = createExecutionLoop(manager, id); assert(MME_SUCCESS == res); /* TODO: proper error handling */ /* Initialize the receiver. */ /* This call will also fail if an existing transformer does not support multi-instantiation. */ res = MME_Receiver_Init(receiver, manager, manager->transportHandle, message, replyPort, &(manager->commandEvents[id])); if (res == MME_SUCCESS) { /* Add the new receiver to the list. */ EMBX_OS_MUTEX_TAKE(&(manager->receiverListMutexes[id])); receiver->next = manager->receiverLists[id]; manager->receiverLists[id] = receiver; EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id])); /* We are successfully done. */ message->result = res; EMBX_SendMessage(replyPort, message, message->messageSize); return; } /* Could not initialize receiver. Clean up and return error. */ MME_Receiver_Destroy(receiver); } } /* Send the message back to the host with an error. */ message->result = res; EMBX_SendMessage(replyPort, message, message->messageSize); EMBX_ClosePort(replyPort); }
int main() { EMBX_TRANSPORT hTrans; EMBX_PORT consumer, bufferpool; EMBX_ERROR err; embxRuntimeInit(); err = EMBX_OpenTransport("shm", &hTrans); assert(err == EMBX_SUCCESS); /* Create the port which the consumer will receive work * messages on. */ err = EMBX_CreatePort(hTrans, "consumer", &consumer); assert(err == EMBX_SUCCESS); /* Connect to the buffer pool on the producer, we will send * back finished message buffers to this so the producer can * re-use them. */ err = EMBX_ConnectBlock(hTrans, "bufferpool", &bufferpool); assert(err == EMBX_SUCCESS); while(1) { EMBX_RECEIVE_EVENT ev; /* Wait for some work to do */ err = EMBX_ReceiveBlock(consumer, &ev); if(err != EMBX_SUCCESS) { /* Assume, for the purposes of this example * that this means the producer wants to close * down. Hence clean up the transport and close * down EMBX. */ EMBX_ClosePort(bufferpool); EMBX_ClosePort(consumer); EMBX_CloseTransport(hTrans); EMBX_Deinit(); exit(1); } /* Do some work with the received message data here */ printf("consumer: Processing message\n"); /* Now send the message buffer back, note the zero size * for the message length, this will prevent any data copying * on a non shared memory transport. */ err = EMBX_SendMessage(bufferpool, ev.data, 0); if(err != EMBX_SUCCESS) { EMBX_ClosePort(bufferpool); EMBX_ClosePort(consumer); EMBX_CloseTransport(hTrans); EMBX_Deinit(); exit(1); } } return 0; }