static void RemoteTransformer_Destroy(Transformer_t* transformer) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_ERROR err; remoteTransformer->super.info->referenceCount--; /* clean up the buffer cache (allocated during execution) */ while (remoteTransformer->bufferCache) { void *buf = allocBuffer(remoteTransformer, 1); if (buf) { EMBX_ERROR err; err = EMBX_Free(buf); MME_Assert(EMBX_SUCCESS == err); } } if (remoteTransformer->adminPort) { err = EMBX_ClosePort(remoteTransformer->adminPort); MME_Assert(EMBX_SUCCESS == err); /* no recovery possible */ } EMBX_OS_EVENT_DESTROY(&remoteTransformer->terminateWasReplied); EMBX_OS_MUTEX_DESTROY(&remoteTransformer->commandSlotLock); EMBX_OS_MemFree(remoteTransformer->commandSlots); EMBX_OS_MemFree(remoteTransformer); }
MME_ERROR MME_LookupTable_Insert(MMELookupTable_t *tbl, void *data, int *id) { int i; MME_Assert(tbl); MME_Assert(data); i = tbl->insertAt; do { MME_Assert(i <= tbl->maxEntries); if (NULL == tbl->lookup[i]) { tbl->lookup[i] = data; *id = i; i++; tbl->insertAt = (i == tbl->maxEntries)?0:i; return MME_SUCCESS; } if (++i == tbl->maxEntries) { i = 0; } } while (i != tbl->insertAt); return MME_NOMEM; }
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 */ }
MME_ERROR MME_MessageQueue_RemoveAll(MMEMessageQueue * msgQ) { MMEMessageQueueEntry **prev; int i; MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_RemoveAll(0x%08x)\n", (unsigned) msgQ)); MME_Assert(msgQ); MME_Assert(msgQ->maxEntries > 0); EMBX_OS_MUTEX_TAKE(&msgQ->queueLock); /* initialize the free list */ for (prev = &(msgQ->free_list), i=0; i < msgQ->maxEntries; prev = &(msgQ->queue[i].next), i++) { *prev = &(msgQ->queue[i]); } *prev = NULL; msgQ->sorted_front = 0; msgQ->unsorted_front = 0; EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_RemoveAll = MME_SUCCESS\n")); return MME_SUCCESS; }
/* This code forms a small cache of pre-allocated blocks that can be allocated by * the host without using (comparitively slow) spinlocks and semaphores. additionally * block coalescing does not take place which saves a number of uncached reads */ static void *allocBuffer(RemoteTransformer_t *remoteTransformer, MME_UINT sz) { EMBX_ERROR err; EMBX_VOID *ptr; if (sz <= 4096) { EMBX_OS_INTERRUPT_LOCK(); if (remoteTransformer->bufferCache) { ptr = remoteTransformer->bufferCache; remoteTransformer->bufferCache = *remoteTransformer->bufferCache; EMBX_OS_INTERRUPT_UNLOCK(); /* this assert technically has side effects (alters sz) so have a * care if altering this function */ MME_Assert(EMBX_SUCCESS == EMBX_GetBufferSize(ptr, &sz)); MME_Assert(4096 == sz); return ptr; } sz = 4096; EMBX_OS_INTERRUPT_UNLOCK(); } err = EMBX_Alloc(remoteTransformer->super.info->handle, sz, &ptr); return (EMBX_SUCCESS == err ? ptr : 0); }
static MME_ERROR createTransformerInstance(const char *name, Transformer_t **tfp) { MME_ERROR res; MME_ERROR res2 = MME_UNKNOWN_TRANSFORMER; RegisteredLocalTransformer_t *rlt; Transformer_t *tf; TransportInfo_t *tpInfo; MME_Assert(manager); MME_Assert(name); #ifndef MULTIHOST /* first check whether this is a locally registered transformer (because this is much * faster than querying the companions) */ res = findTransformerOnHost(name, &rlt); if (MME_SUCCESS == res) { tf = MME_LocalTransformer_Create(manager, rlt); if (tf) { *tfp = tf; return MME_SUCCESS; } else { return MME_NOMEM; } } #endif /* !MULTIHOST */ /* now start looking for the named transformer in each of the registered transports */ for (tpInfo = manager->transportList; tpInfo; tpInfo = tpInfo->next) { EMBX_PORT adminPort; res = findTransformerWithinTransport(tpInfo, name, &adminPort); if (MME_SUCCESS == res) { /* RemoteTransformer_Create will update tpInfo's reference count and * keep a reference to it. adminPort is transfered outright to the * transformer */ tf = MME_RemoteTransformer_Create(manager, tpInfo, adminPort); if (tf) { *tfp = tf; return MME_SUCCESS; } else { return MME_NOMEM; } } /* TIMEOUT SUPPORT: Remember res if we see a timeout from any of the transports */ else if (res == MME_TRANSFORMER_NOT_RESPONDING) res2 = res; } MME_Assert(res2 == MME_UNKNOWN_TRANSFORMER || res2 == MME_TRANSFORMER_NOT_RESPONDING); /* TIMEOUT SUPPORT: Returns MME_TRANSFORMER_NOT_RESPONDING if we failed * to communicate with any of the transformers. MME_UNKNOWN_TRANSFORMER otherwise */ return res2; }
static MME_ERROR cleanupTransformMessage(RemoteTransformer_t* remoteTransformer, EMBX_VOID * buffer) { union { TransformerTransformMessage *message; MME_DataBuffer_t *buffer; MME_ScatterPage_t *page; EMBX_HANDLE *hdl; char *ch; int i; void *p; void **pp; } p; MME_Command_t *cmd; EMBX_ERROR err; unsigned int i, j; p.p = buffer; MME_Assert(p.message->numInputBuffers == p.message->hostCommand->NumberInputBuffers); MME_Assert(p.message->numOutputBuffers == p.message->hostCommand->NumberOutputBuffers); cmd = p.message->hostCommand; p.message += 1; p.buffer += cmd->NumberInputBuffers + cmd->NumberOutputBuffers; p.pp += cmd->NumberInputBuffers + cmd->NumberOutputBuffers; for (i = 0; i < (cmd->NumberInputBuffers + cmd->NumberOutputBuffers); i++) { MME_DataBuffer_t *buf = cmd->DataBuffers_p[i]; MME_ScatterPage_t *pages = p.page; p.page += buf->NumberOfScatterPages; for (j=0; j < buf->NumberOfScatterPages; j++) { if (i >= cmd->NumberInputBuffers) { buf->ScatterPages_p[j].BytesUsed = pages[j].BytesUsed; buf->ScatterPages_p[j].FlagsOut = pages[j].FlagsOut; } if (0xf0000000 & p.hdl[j]) { err = EMBX_DeregisterObject( remoteTransformer->super.info->handle, p.hdl[j]); MME_Assert(EMBX_SUCCESS == err); /* no error recovery possible */ } } p.hdl += buf->NumberOfScatterPages; } /* Deal with status transformer paramters */ if (cmd->CmdStatus.AdditionalInfoSize > 0) { memcpy(cmd->CmdStatus.AdditionalInfo_p, p.p, cmd->CmdStatus.AdditionalInfoSize); } return MME_SUCCESS; }
MME_ERROR MME_LookupTable_Find(MMELookupTable_t *tbl, int id, void **data) { MME_Assert(tbl); MME_Assert(data); if (id < 0 || id >= tbl->maxEntries) { return MME_INVALID_HANDLE; } *data = tbl->lookup[id]; return (*data ? MME_SUCCESS : MME_INVALID_HANDLE); }
static void deregisterTransformerInstance(MME_TransformerHandle_t handle) { MME_ERROR res; MME_Assert(manager); /* clear the prefix */ handle -= MME_TRANSFORMER_HANDLE_PREFIX; res = MME_LookupTable_Remove(manager->transformerInstances, handle); MME_Assert(MME_SUCCESS == res); }
static MME_ERROR createExecutionLoop(MMEManager_t *manager, int id) { const struct { MME_UINT priority; const char *name; } lookup[MME_NUM_EXECUTION_LOOPS] = { { MME_TUNEABLE_EXECUTION_LOOP_LOWEST_PRIORITY, "ExecutionLoopLowest" }, { MME_TUNEABLE_EXECUTION_LOOP_BELOW_NORMAL_PRIORITY, "ExecutionLoopBelowNormal" }, { MME_TUNEABLE_EXECUTION_LOOP_NORMAL_PRIORITY, "ExecutionLoopNormal" }, { MME_TUNEABLE_EXECUTION_LOOP_ABOVE_NORMAL_PRIORITY, "ExecutionLoopAboveNormal" }, { MME_TUNEABLE_EXECUTION_LOOP_HIGHEST_PRIORITY, "ExecutionLoopHighest" }, }; MME_Assert(manager); MME_Assert(id < MME_NUM_EXECUTION_LOOPS); if (manager->loopTasksRunning[id]) { return MME_SUCCESS; } MME_Assert(0 == manager->loopTasks[id]); MME_Assert(0 == manager->receiverLists[id]); /* this code can only be called from the manager thread and therefore needs * no thread protection. */ if (!EMBX_OS_MUTEX_INIT(&(manager->receiverListMutexes[id]))) { return MME_NOMEM; } if (!EMBX_OS_EVENT_INIT(&(manager->commandEvents[id]))) { goto cleanup_mutex; } /* spawn the worker thread */ manager->loopTasks[id] = EMBX_OS_ThreadCreate((void(*)()) executionLoopTask, (void *) id, MME_GetTuneable(lookup[id].priority), lookup[id].name); if (0 == manager->loopTasks[id]) { goto cleanup_event; } /* mark the task as running */ manager->loopTasksRunning[id] = 1; return MME_SUCCESS; cleanup_event: EMBX_OS_EVENT_DESTROY(&(manager->commandEvents[id])); cleanup_mutex: EMBX_OS_MUTEX_DESTROY(&(manager->receiverListMutexes[id])); return MME_NOMEM; }
static void sortMessageQueue(MMEMessageQueue *msgQ) { MMEMessageQueueEntry *entry; /* take the unsorted list and merge it with the sorted list. * this code is optimized for FIFO operations and the time * comparisions allow time to wrap. they do not directly * compare values but subtract with overflow wrap and compare * against 0. note ANSI C only guarantees overflow wrap for * unsigned values (which is why the priority member is unsigned). */ EMBX_OS_MUTEX_TAKE(&msgQ->queueLock); entry = msgQ->unsorted_front; while (entry) { msgQ->unsorted_front = entry->next; if (NULL == msgQ->sorted_front) { /* empty list short circuit */ entry->next = NULL; msgQ->sorted_front = entry; msgQ->sorted_back = entry; } else if (0 >= (int) (msgQ->sorted_back->priority - entry->priority)) { /* FIFO ordered queue short circuit */ entry->next = NULL; msgQ->sorted_back->next = entry; msgQ->sorted_back = entry; } else { /* search the queue until we find a entry with a (strictly) more * distant due date */ MMEMessageQueueEntry **prev, *cur; /* search the queue until we find our insertion point. we know * we cannot run off the end otherwise we would have taken one * of the short circuits above. */ for (prev = &(msgQ->sorted_front), cur = *prev; MME_Assert(cur), 0 >= (int) (cur->priority - entry->priority); prev = &(cur->next), cur = *prev) {} entry->next = cur; *prev = entry; MME_Assert(*prev != msgQ->sorted_back); } entry = msgQ->unsorted_front; } EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); }
MME_ERROR MME_MessageQueue_Init(MMEMessageQueue * msgQ, int maxEntries) { MME_ERROR err; int size = maxEntries * sizeof(MMEMessageQueueEntry); MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Init(0x%08x, %d)\n", (unsigned) msgQ, maxEntries)); msgQ->maxEntries = maxEntries; msgQ->queue = (MMEMessageQueueEntry*) EMBX_OS_MemAlloc(size); if (msgQ->queue == NULL) { MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Init = MME_NOMEM\n")); return MME_NOMEM; } memset(msgQ->queue, 0, size); if (!EMBX_OS_MUTEX_INIT(&msgQ->queueLock)) { MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Init = MME_NOMEM\n")); return MME_NOMEM; } err = MME_MessageQueue_RemoveAll(msgQ); MME_Assert(MME_SUCCESS == err); /* currently has no failure path */ MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Init = MME_SUCCESS\n")); return MME_SUCCESS; }
MME_ERROR MME_WaitForMessage(Transformer_t* transformer, MME_Event_t* eventPtr, MME_Command_t** commandPtr) { MME_Assert(transformer->vtable->waitForMessage); /* this is not an external visible API so invalid arguments are an * internal error. */ MME_Assert(transformer); MME_Assert(eventPtr); MME_Assert(commandPtr); return transformer->vtable->waitForMessage( transformer, eventPtr, commandPtr); }
static void cleanupTerminateMMEMessage(TransportInfo_t *tpInfo, TransformerTerminateMMEMessage* buffer) { EMBX_ERROR err; err = EMBX_Free(buffer); MME_Assert(EMBX_SUCCESS == err); }
static void cleanupRegisteredMessage(TransportInfo_t *tpInfo, TransformerRegisteredMessage *msg) { EMBX_ERROR err; err = EMBX_Free(msg); MME_Assert(EMBX_SUCCESS == err); }
static MME_ERROR findTransformerInstance(MME_TransformerHandle_t handle, Transformer_t** transformer) { void *p; MME_ERROR res; MME_Assert(manager); MME_Assert(transformer); handle -= MME_TRANSFORMER_HANDLE_PREFIX; res = MME_LookupTable_Find(manager->transformerInstances, handle, &p); if (MME_SUCCESS == res) { *transformer = (Transformer_t *) p; } return res; }
static MME_ERROR registerTransformerInstance(Transformer_t* transformer, MME_TransformerHandle_t * handle) { MME_ERROR res; int id; MME_Assert(manager); MME_Assert(transformer); MME_Assert(handle); res = MME_LookupTable_Insert(manager->transformerInstances, transformer, &id); if (MME_SUCCESS == res) { *handle = MME_TRANSFORMER_HANDLE_PREFIX + id; } return res; }
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")); } }
MME_ERROR MME_LookupTable_Remove(MMELookupTable_t *tbl, int id) { MME_Assert(tbl); MME_Assert(id < tbl->maxEntries); if (id < 0 || id >= tbl->maxEntries) { return MME_INVALID_HANDLE; } tbl->lookup[id] = NULL; if (!tbl->temporallyUnique) { /* improves locality of reference at bit */ tbl->insertAt = id; } return MME_SUCCESS; }
static MME_ERROR createTransportInfo(const char *name, TransportInfo_t **tpInfo_p) { const char portName[] = "MMEHostReplyPort#0"; TransportInfo_t *tpInfo; EMBX_ERROR err; /* Allocate space for the transport descriptor */ tpInfo = EMBX_OS_MemAlloc(sizeof(TransportInfo_t)); if (!tpInfo) { return MME_NOMEM; } memset(tpInfo, 0, sizeof(TransportInfo_t)); /* Open a transport handle */ err = EMBX_OpenTransport(name, &tpInfo->handle); if (EMBX_SUCCESS != err) { goto error_recovery; } /* Create the reply port. */ memcpy(tpInfo->replyPortName, portName, sizeof(portName)); /* MULTIHOST support */ do { MME_Info(MME_INFO_MANAGER, (" EMBX_CreatePort(), port name <%s>...\n", tpInfo->replyPortName)); /* Create the reply port. This port is purely synchronous (it only receives * messages that are replies to outstanding messages) and as such does not * need its own management thread. */ err = EMBX_CreatePort(tpInfo->handle, tpInfo->replyPortName, &tpInfo->replyPort); } while (EMBX_ALREADY_BIND == err && tpInfo->replyPortName[sizeof(portName)-2]++ < '9'); if (EMBX_SUCCESS != err) { goto error_recovery; } *tpInfo_p = tpInfo; return MME_SUCCESS; error_recovery: if (tpInfo->handle) { err = EMBX_CloseTransport(tpInfo->handle); MME_Assert(EMBX_SUCCESS == err); } EMBX_OS_MemFree(tpInfo); return MME_EMBX_ERROR; }
MMELookupTable_t * MME_LookupTable_Create(int max, int temporal) { MMELookupTable_t *tbl; int size = sizeof(MMELookupTable_t) + (max-1) * sizeof(void *); MME_Assert(max > 0); MME_Assert(0 == temporal || 1 == temporal); /* allocation */ tbl = EMBX_OS_MemAlloc(size); if (!tbl) { return NULL; } memset(tbl, 0, size); tbl->maxEntries = max; tbl->temporallyUnique = temporal; return tbl; }
static MME_ERROR RemoteTransformer_WaitForMessage(Transformer_t* transformer, MME_Event_t* eventPtr, MME_Command_t** commandPtr) { EMBX_RECEIVE_EVENT event; RemoteTransformer_t* remoteTransformer = (RemoteTransformer_t*)transformer; EMBX_ERROR err; MME_Assert(transformer); MME_Assert(eventPtr); MME_Assert(commandPtr); err = EMBX_ReceiveBlock(remoteTransformer->replyPort.port, &event); if (EMBX_SUCCESS != err) { *eventPtr = MME_COMMAND_COMPLETED_EVT; *commandPtr = NULL; return (err == EMBX_SYSTEM_INTERRUPT ? MME_SYSTEM_INTERRUPT : MME_TRANSFORMER_NOT_RESPONDING); } MME_Assert(event.data); MME_Assert(event.type == EMBX_REC_MESSAGE); /* received message. */ switch (((MME_UINT *) event.data)[0]) { case TMESSID_TRANSFORM: receiveTransformMessage(remoteTransformer, (TransformerTransformMessage *) event.data, eventPtr, commandPtr); freeBuffer(remoteTransformer, event.data); return MME_SUCCESS; case TMESSID_STARVATION: { receiveStavationMessage(remoteTransformer, (TransformerStarvationMessage *) event.data, eventPtr, commandPtr); freeBuffer(remoteTransformer, event.data); return MME_SUCCESS; } case TMESSID_TERMINATE: { /* A Terminate message returned */ remoteTransformer->terminationResult = ((TransformerTerminateMessage *) event.data)->result; MME_Assert(MME_SUCCESS == remoteTransformer->terminationResult); cleanupTerminateMessage(remoteTransformer, (TransformerTerminateMessage *) event.data); *eventPtr = MME_COMMAND_COMPLETED_EVT; *commandPtr = NULL; EMBX_OS_EVENT_POST(&remoteTransformer->terminateWasReplied); return MME_TRANSFORMER_NOT_RESPONDING; } default: MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "Unexpected message: %x\n", (unsigned) ((MME_UINT *) event.data)[0])); MME_Assert(0); } return MME_INTERNAL_ERROR; }
MME_ERROR MME_HostDeregisterTransport(const char* name) #endif { EMBX_ERROR err; TransportInfo_t *tpInfo, **prev; MME_ERROR res; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "MME not initialized\n")); return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } if (name == NULL) { MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Transport name NULL\n")); return MME_INVALID_ARGUMENT; } #endif EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "Looking for transport %s\n", name)); /* search the transport list for the appropriate transport */ for (tpInfo = *(prev = &manager->transportList); tpInfo; tpInfo = *(prev = &tpInfo->next)) { EMBX_TPINFO embxTpInfo; err = EMBX_GetTransportInfo(tpInfo->handle, &embxTpInfo); MME_Assert(EMBX_SUCCESS == err); if (0 == strcmp(name, embxTpInfo.name)) { break; } } if (!tpInfo) { MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Transport not found\n")); res = MME_INVALID_ARGUMENT; } else if (0 != tpInfo->referenceCount) { MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Handles still open\n")); res = MME_HANDLES_STILL_OPEN; } else { res = MME_SUCCESS; MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "Removing transport\n")); /* remove the transport information from the list and cleanup */ *prev = tpInfo->next; destroyTransportInfo(tpInfo); } EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "<<<< (%d)\n", res)); return res; }
/* The list management here is extremely vulnerable to duplicate frees. this * will make the buffer list cyclic resulting either in the buffer release * code in RemoteTransformer_Term() looping forever or (worse) memory * being allocated twice. */ static void freeBuffer(RemoteTransformer_t *remoteTransformer, EMBX_VOID *ptr) { EMBX_UINT sz; EMBX_ERROR err; err = EMBX_GetBufferSize(ptr, &sz); MME_Assert(EMBX_SUCCESS == err); if (sz == 4096) { EMBX_VOID **p = ptr; MME_Assert(ptr != remoteTransformer->bufferCache); EMBX_OS_INTERRUPT_LOCK(); *p = remoteTransformer->bufferCache; remoteTransformer->bufferCache = p; EMBX_OS_INTERRUPT_UNLOCK(); } else { EMBX_ERROR err = EMBX_Free(ptr); MME_Assert(EMBX_SUCCESS == err); } }
static void destroyTransportInfo(TransportInfo_t *tpInfo) { MME_ERROR res; EMBX_ERROR err; MME_Assert(manager); MME_Assert(tpInfo); #ifndef MULTIHOST res = issueTerminateMMEMessages(tpInfo); MME_Assert(MME_SUCCESS == res); #endif err = EMBX_ClosePort(tpInfo->replyPort); MME_Assert(EMBX_SUCCESS == err); err = EMBX_CloseTransport(tpInfo->handle); MME_Assert(EMBX_SUCCESS == err); EMBX_OS_MemFree(tpInfo); }
/* Construct a one-way message requesting complete termination of our partner CPU. */ static MME_ERROR createTerminateMMEMessage(TransportInfo_t *tpInfo, TransformerTerminateMMEMessage** buffer) { TransformerTerminateMMEMessage *message; EMBX_ERROR err; MME_Assert(manager); MME_Assert(tpInfo); MME_Assert(buffer); err = EMBX_Alloc(tpInfo->handle, sizeof(*message), (EMBX_VOID **) &message); if (EMBX_SUCCESS == err) { message->id = TMESSID_TERMINATE_MME; message->messageSize = sizeof(*message); message->result = MME_SUCCESS; *buffer = message; } /* map the EMBX error to an MME one */ return EMBX_SUCCESS == err ? MME_SUCCESS : EMBX_NOMEM == err ? MME_NOMEM : MME_EMBX_ERROR; }
static void receiverThread(void* ctx) { RemoteTransformer_t* remoteTransformer = (RemoteTransformer_t*) ctx; MME_ERROR res; MME_Assert(remoteTransformer); MME_Assert(remoteTransformer->replyPort.valid); while (1) { MME_Event_t evt; MME_Command_t *cmd; /* wait for a transformer message (callback) to be received */ res = RemoteTransformer_WaitForMessage( (Transformer_t *) remoteTransformer, &evt, &cmd); if (MME_SUCCESS != res) { break; } MME_Assert(cmd); /* perform the callback if this has been requested */ if (MME_COMMAND_COMPLETED_EVT != evt || MME_COMMAND_END_RETURN_NOTIFY == cmd->CmdEnd) { /* it would really make more sense to assert Callback and make it illegal to send * commands with MME_COMMAND_END_RETURN_NOTIFY fail if Callback is NULL. However this * would mean changing the behavior of the API. */ if (remoteTransformer->super.initParams.Callback) { remoteTransformer->super.initParams.Callback(evt, cmd, remoteTransformer->super.initParams.CallbackUserData); } } } MME_Info(MME_INFO_TRANSFORMER, ("receiverThread: terminating due (res = %d)\n", res)); }
int MME_LookupTable_IsEmpty(MMELookupTable_t *tbl) { int i; MME_Assert(tbl); for (i=0; i<tbl->maxEntries; i++) { if (tbl->lookup[i]) { return 0; } } return 1; }
MME_ERROR MME_HostRegisterTransport(const char *name) #endif { MME_ERROR res; EMBX_ERROR err; TransportInfo_t *tpInfo = 0; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "MME not initialized\n")); return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } if (name == NULL) { MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Name not valid\n")); return MME_INVALID_ARGUMENT; } #endif EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); #ifndef MME_LEAN_AND_MEAN /* prevent duplicate transport registrations */ for (tpInfo = manager->transportList; tpInfo; tpInfo = tpInfo->next) { EMBX_TPINFO embxTpInfo; err = EMBX_GetTransportInfo(tpInfo->handle, &embxTpInfo); MME_Assert(EMBX_SUCCESS == err); if (0 == strcmp(name, embxTpInfo.name)) { EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Transport already registered\n")); return MME_INVALID_ARGUMENT; } } #endif /* allocate space for the transport descriptor */ res = createTransportInfo(name, &tpInfo); if (MME_SUCCESS == res) { /* update the lists with in the manager */ tpInfo->next = manager->transportList; manager->transportList = tpInfo; } EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "<<<< (%d)\n", res)); return res; }
static MME_ERROR createInitMessage(RemoteTransformer_t* remoteTransformer, const char* name, MME_TransformerInitParams_t* params, EMBX_VOID** buffer) { TransformerInitMessage *message; unsigned paramsSize; int messageSize; MME_Assert(params->StructSize == sizeof(MME_TransformerInitParams_t)); messageSize = sizeof(TransformerInitMessage); paramsSize = params->TransformerInitParamsSize; messageSize += paramsSize; message = allocBuffer(remoteTransformer, messageSize); if (0 == message ) { return MME_NOMEM; } message->id = TMESSID_INIT; message->messageSize = messageSize; message->priority = params->Priority; message->result = MME_SUCCESS; MME_Assert(strlen(name) < MME_MAX_TRANSFORMER_NAME); strcpy(message->transformerType, name); MME_Assert(strlen(remoteTransformer->replyPort.name) < EMBX_MAX_PORT_NAME); strcpy(message->portName, remoteTransformer->replyPort.name); /* Copy TransformerInitParams data */ /* TODO: these should be byte swapped on a big endian machine */ memcpy((void *) (message + 1), params->TransformerInitParams_p, paramsSize); *buffer = message; return MME_SUCCESS; }