MME_ERROR MME_GetTransformerCapability(const char *name, MME_TransformerCapability_t * capability) { MME_ERROR res; Transformer_t *transformer; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } if (NULL == name || NULL == capability || capability->StructSize != sizeof(MME_TransformerCapability_t)) { return MME_INVALID_ARGUMENT; } #endif /* protect access */ EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); /* Find a registered transformer (registered with MME_RegisterTransformer) */ res = createTransformerInstance(name, &transformer); if (MME_SUCCESS == res) { EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); res = transformer->vtable->getTransformerCapability(transformer, name, capability); EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); transformer->vtable->destroy(transformer); } EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return res; }
MME_ERROR MME_KillTransformer(MME_TransformerHandle_t handle) { Transformer_t *transformer; MME_ERROR res; #ifndef MME_LEAN_AND_MEAN if (NULL == manager) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Driver not initialized\n")); return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } #endif EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); /* Find the transformer */ res = findTransformerInstance(handle, &transformer); if (res != MME_SUCCESS) { EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Failed to find transformer instance\n")); return MME_INVALID_HANDLE; } res = transformer->vtable->kill(transformer); if (MME_SUCCESS == res) { deregisterTransformerInstance(handle); transformer->vtable->destroy(transformer); } EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return res; }
MME_ERROR MME_MessageQueue_Dequeue(MMEMessageQueue * msgQ, void **message) { MMEMessageQueueEntry *entry; MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Dequeue(0x%08x, ...)\n", (unsigned) msgQ)); sortMessageQueue(msgQ); EMBX_OS_MUTEX_TAKE(&msgQ->queueLock); /* dequeue the first message */ entry = msgQ->sorted_front; if (NULL == entry) { *message = NULL; MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Dequeue(..., 0x%08x) = MME_INVALID_HANDLE\n", (unsigned) *message)); EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); return MME_INVALID_HANDLE; } msgQ->sorted_front = entry->next; /* push it onto the free list */ entry->next = msgQ->free_list; msgQ->free_list = entry; *message = entry->message; MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Dequeue(..., 0x%08x) = MME_SUCCESS\n", (unsigned) *message)); EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); return MME_SUCCESS; }
MME_ERROR MME_DeregisterTransformer(const char *name) { RegisteredLocalTransformer_t *elem, **prev; #ifndef MME_LEAN_AND_MEAN if (NULL == manager) { return MME_DRIVER_NOT_INITIALIZED; } if (NULL == name) { return MME_INVALID_ARGUMENT; } #endif EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); for (elem = *(prev = &manager->localTransformerList); elem; elem = *(prev = &elem->next)) { if (0 == strcmp(name, elem->name)) { break; } } if (elem && 0 == elem->inUseCount) { *prev = elem->next; EMBX_OS_MemFree(elem); EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return MME_SUCCESS; } EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return MME_INVALID_ARGUMENT; }
MME_ERROR MME_RegisterTransformer(const char *name, MME_AbortCommand_t abortCommand, MME_GetTransformerCapability_t getTransformerCapability, MME_InitTransformer_t initTransformer, MME_ProcessCommand_t processCommand, MME_TermTransformer_t termTransformer) { RegisteredLocalTransformer_t *elem; #ifndef MME_LEAN_AND_MEAN if (NULL == manager) { return MME_DRIVER_NOT_INITIALIZED; } if (NULL == name) { return MME_INVALID_ARGUMENT; } #endif EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); /* check for multiple registrations */ for (elem = manager->localTransformerList; elem; elem = elem->next) { if (0 == strcmp(name, elem->name)) { EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return MME_INVALID_ARGUMENT; } } /* register the transformer */ elem = EMBX_OS_MemAlloc(sizeof(*elem) + strlen(name) + 1); /* populate and enqueue the structure */ elem->name = (char *) (elem + 1); strcpy(elem->name, name); elem->vtable.AbortCommand = abortCommand; elem->vtable.GetTransformerCapability = getTransformerCapability; elem->vtable.InitTransformer = initTransformer; elem->vtable.ProcessCommand = processCommand; elem->vtable.TermTransformer = termTransformer; elem->inUseCount = 0; elem->next = manager->localTransformerList; manager->localTransformerList = elem; EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return MME_SUCCESS; }
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 void executionLoopTask(void *params) { int id = (int) params; for (EMBX_OS_EVENT_WAIT(&(manager->commandEvents[id])); manager->loopTasksRunning[id]; EMBX_OS_EVENT_WAIT(&(manager->commandEvents[id]))) { MMEReceiver *receiver; MMEReceiver *lowestReceiver; MME_Time_t dueTime, lowestDueTime; int found = 0; EMBX_OS_MUTEX_TAKE(&(manager->receiverListMutexes[id])); EMBX_OS_MUTEX_TAKE(&(manager->abortMutex)); /* Find the receiver with the lowest dueTime. */ lowestReceiver = manager->receiverLists[id]; lowestDueTime = MME_MaxTime_c; for (receiver = lowestReceiver; receiver; receiver = receiver->next) { if (MME_SUCCESS == MME_Receiver_NextDueTime(receiver, &dueTime)) { if (dueTime < lowestDueTime) { found = 1; lowestReceiver = receiver; lowestDueTime = dueTime; } } } /* TODO: Note that if we support the bufferQueue, we need to serve it here */ if (found) { EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id])); /* Execute this receiver's command. */ /* Mutex will be released once the message is dequeued - otherwise an abort requiest may come take the message off the queue but leave the receiver in the executing state */ MME_Receiver_ProcessCommand(lowestReceiver); } else { /* Nothing is pending. We could waste some time. */ MME_Info(MME_INFO_MANAGER, ("Execution loop error: Semaphore signalled but no command found!\n")); EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id])); EMBX_OS_MUTEX_RELEASE(&(manager->abortMutex)); } } }
MME_ERROR MME_KillCommandAll(MME_TransformerHandle_t handle) { Transformer_t *transformer; MME_ERROR result; #ifndef MME_LEAN_AND_MEAN if (NULL == manager) { return MME_DRIVER_NOT_INITIALIZED; } #endif /* protect access */ EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); result = findTransformerInstance(handle, &transformer); if (result != MME_SUCCESS) { /* cannot find transformer for this handle */ result = MME_INVALID_HANDLE; goto EXIT; } result = transformer->vtable->killCommandAll(transformer); if (result != MME_SUCCESS) { result = MME_INVALID_ARGUMENT; goto EXIT; } result = MME_SUCCESS; EXIT: EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return result; }
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; }
MME_ERROR MME_DeregisterTransformer(const char *name) { MME_ERROR result = MME_INVALID_ARGUMENT; MMEReceiverFactory *factory, **prev; if (NULL == manager) { return MME_DRIVER_NOT_INITIALIZED; } if (NULL == name) { return MME_INVALID_ARGUMENT; } /* iterate over the (singly linked) factory list until we find * a factory or reach the end */ EMBX_OS_MUTEX_TAKE(&(manager->factoryListMutex)); for (prev = &(manager->factoryList), factory = *prev; NULL != factory; prev = &(factory->next), factory = *prev) { if (0 == strcmp(factory->transformerType, name)) { /* unlink and free the node */ *prev = factory->next; free(factory); result = MME_SUCCESS; break; } } EMBX_OS_MUTEX_RELEASE(&(manager->factoryListMutex)); return result; }
EMBX_ERROR EMBX_RemoveProcessor(EMBX_TRANSPORT htp, EMBX_UINT cpuID) { EMBX_ERROR res = EMBX_INVALID_TRANSPORT; EMBX_Info(EMBX_INFO_TRANSPORT, (">>>>EMBX_RemoveProcessor(htp=0x%08lx,cpu=%d)\n",(unsigned long)htp, cpuID)); EMBX_DebugOn(EMBX_INFO_TRANSPORT); if(!_embx_dvr_ctx.isLockInitialized) { EMBX_DebugMessage((_driver_uninit_error)); goto exit; } if(!EMBX_HANDLE_ISTYPEOF(htp, EMBX_HANDLE_TYPE_TRANSPORT)) { res = EMBX_INVALID_TRANSPORT; goto exit; } EMBX_OS_MUTEX_TAKE(&_embx_dvr_ctx.lock); if(_embx_dvr_ctx.state != EMBX_DVR_INITIALIZED && _embx_dvr_ctx.state != EMBX_DVR_IN_SHUTDOWN ) { EMBX_DebugMessage((_driver_uninit_error)); res = EMBX_INVALID_TRANSPORT; } else { EMBX_TransportHandle_t *tph; tph = (EMBX_TransportHandle_t *)EMBX_HANDLE_GETOBJ(&_embx_handle_manager, htp); if( (tph == 0) || (tph->state != EMBX_HANDLE_VALID) ) { EMBX_DebugMessage(("Failed 'transport handle is not valid'\n")); res = EMBX_INVALID_TRANSPORT; } else { EMBX_Transport_t *tp = tph->transport; EMBX_Assert(tp); EMBX_Assert(tp->methods->remove_processor); /* Call the transport specific removal function */ res = tp->methods->remove_processor(tp, cpuID); } } EMBX_OS_MUTEX_RELEASE(&_embx_dvr_ctx.lock); exit: EMBX_DebugOff(EMBX_INFO_TRANSPORT); EMBX_Info(EMBX_INFO_TRANSPORT, ("<<<<EMBX_RemoveProcessor(htp=0x%08lx,cpu=%d) = %d\n", (unsigned long)htp, cpuID, res)); 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_FindTransformerInstance(MME_TransformerHandle_t handle, Transformer_t** transformer) { MME_ERROR error; /* protect access */ EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); error = findTransformerInstance(handle, transformer); EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); return error; }
EMBX_ERROR EMBX_FindTransport(const EMBX_CHAR *name, EMBX_TPINFO *tpinfo) { EMBX_ERROR res; EMBX_Info(EMBX_INFO_TRANSPORT, (">>>>EMBX_FindTransport(%s)\n",(name==0?"(NULL)":name))); EMBX_DebugOn(EMBX_INFO_TRANSPORT); if(!_embx_dvr_ctx.isLockInitialized) { EMBX_DebugMessage((_driver_uninit_error)); res = EMBX_DRIVER_NOT_INITIALIZED; goto exit; } if((name == 0) || (tpinfo == 0)) { res = EMBX_INVALID_ARGUMENT; goto exit; } EMBX_OS_MUTEX_TAKE(&_embx_dvr_ctx.lock); if(_embx_dvr_ctx.state != EMBX_DVR_INITIALIZED) { EMBX_DebugMessage((_driver_uninit_error)); res = EMBX_DRIVER_NOT_INITIALIZED; } else { EMBX_TransportList_t *tpl; tpl = EMBX_find_transport_entry(name); if(tpl != 0) { EMBX_Info(EMBX_INFO_TRANSPORT,("Found transport\n")); *tpinfo = tpl->transport->transportInfo; res = EMBX_SUCCESS; } else { EMBX_Info(EMBX_INFO_TRANSPORT,("Could not find transport\n")); res = EMBX_INVALID_TRANSPORT; } } EMBX_OS_MUTEX_RELEASE(&_embx_dvr_ctx.lock); exit: EMBX_DebugOff(EMBX_INFO_TRANSPORT); EMBX_Info(EMBX_INFO_TRANSPORT, ("<<<<EMBX_FindTransport(%s) = %d\n",(name==0?"(NULL)":name), res)); return res; }
EMBX_EVENT EMBX_OS_EventCreate(void) { EMBX_EVENT ev = NULL; /* This is not multithread safe - perhaps use an atomic test&set ? */ if (!cacheInitialised) { cacheInitialised = 1; (void) EMBX_OS_MUTEX_INIT(&cacheLock); } EMBX_OS_MUTEX_TAKE(&cacheLock); if ((ev = cacheHead) != NULL) { cacheHead = cacheHead->next; /* Mark desc as being in use */ ev->next = (EMBX_EVENT) EMBX_HANDLE_VALID; EMBX_OS_MUTEX_RELEASE(&cacheLock); } else { EMBX_OS_MUTEX_RELEASE(&cacheLock); /* Dynamically allocate a new cache container * and initialise the event inside it */ ev = EMBX_OS_MemAlloc(sizeof(*ev)); if (ev) { /* Mark desc as being in use */ ev->next = (EMBX_EVENT) EMBX_HANDLE_VALID; ev->event = semaphore_create_fifo(0); } } return ev; }
EMBX_ERROR EMBX_GetTransportInfo(EMBX_TRANSPORT htp, EMBX_TPINFO *tpinfo) { EMBX_ERROR res = EMBX_INVALID_TRANSPORT; EMBX_Info(EMBX_INFO_TRANSPORT, (">>>>EMBX_GetTransportInfo(htp=0x%08lx)\n",(unsigned long)htp)); EMBX_DebugOn(EMBX_INFO_TRANSPORT); if(!_embx_dvr_ctx.isLockInitialized) { EMBX_DebugMessage((_driver_uninit_error)); goto exit; } if(tpinfo == 0) { res = EMBX_INVALID_ARGUMENT; goto exit; } if(!EMBX_HANDLE_ISTYPEOF(htp, EMBX_HANDLE_TYPE_TRANSPORT)) { goto exit; } EMBX_OS_MUTEX_TAKE(&_embx_dvr_ctx.lock); if(_embx_dvr_ctx.state != EMBX_DVR_INITIALIZED) { EMBX_DebugMessage((_driver_uninit_error)); } else { EMBX_TransportHandle_t *tph; tph = (EMBX_TransportHandle_t *)EMBX_HANDLE_GETOBJ(&_embx_handle_manager, htp); if( (tph != 0) && (tph->state == EMBX_HANDLE_VALID) ) { *tpinfo = tph->transport->transportInfo; EMBX_Info(EMBX_INFO_TRANSPORT, ("Returning transport '%s'\n",tpinfo->name)); res = EMBX_SUCCESS; } } EMBX_OS_MUTEX_RELEASE(&_embx_dvr_ctx.lock); exit: EMBX_DebugOff(EMBX_INFO_TRANSPORT); EMBX_Info(EMBX_INFO_TRANSPORT, ("<<<<EMBX_GetTransportInfo(htp=0x%08lx) = %d\n",(unsigned long)htp, res)); return res; }
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; }
/* Peek does not dequeue the entry. */ MME_ERROR MME_MessageQueue_Peek(MMEMessageQueue * msgQ, void **message) { MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Peek(0x%08x, ...)\n", (unsigned) msgQ)); sortMessageQueue(msgQ); EMBX_OS_MUTEX_TAKE(&msgQ->queueLock); if (NULL == msgQ->sorted_front) { *message = NULL; MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Peek(..., 0) = MME_INVALID_HANDLE\n")); EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); return MME_INVALID_HANDLE; } *message = msgQ->sorted_front->message; EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Peek(..., 0x%08x) = MME_SUCCESS\n", (unsigned) *message)); return MME_SUCCESS; }
static MME_ERROR RemoteTransformer_ReleaseCommandSlot(Transformer_t* transformer, CommandSlot_t* slot) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_OS_MUTEX_TAKE(&remoteTransformer->commandSlotLock); remoteTransformer->numCommandSlots--; slot->status = MME_COMMAND_COMPLETED_EVT; EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock); return MME_SUCCESS; }
EMBX_ERROR EMBX_GetFirstTransport(EMBX_TPINFO *tpinfo) { EMBX_ERROR res; EMBX_Info(EMBX_INFO_TRANSPORT, (">>>>EMBX_GetFirstTransport\n")); EMBX_DebugOn(EMBX_INFO_TRANSPORT); if(!_embx_dvr_ctx.isLockInitialized) { EMBX_DebugMessage((_driver_uninit_error)); res = EMBX_DRIVER_NOT_INITIALIZED; goto exit; } if(tpinfo == 0) { res = EMBX_INVALID_ARGUMENT; goto exit; } EMBX_OS_MUTEX_TAKE(&_embx_dvr_ctx.lock); if(_embx_dvr_ctx.state != EMBX_DVR_INITIALIZED) { EMBX_DebugMessage((_driver_uninit_error)); res = EMBX_DRIVER_NOT_INITIALIZED; } else { if(_embx_dvr_ctx.transports == 0) { res = EMBX_INVALID_STATUS; } else { *tpinfo = _embx_dvr_ctx.transports->transport->transportInfo; EMBX_Info(EMBX_INFO_TRANSPORT, ("Returning transport '%s'\n",tpinfo->name)); res = EMBX_SUCCESS; } } EMBX_OS_MUTEX_RELEASE(&_embx_dvr_ctx.lock); exit: EMBX_DebugOff(EMBX_INFO_TRANSPORT); EMBX_Info(EMBX_INFO_TRANSPORT, ("<<<<EMBX_GetFirstTransport = %d\n", res)); return res; }
void EMBX_OS_EventDelete(EMBX_EVENT ev) { EMBX_OS_MUTEX_TAKE(&cacheLock); EMBX_Assert(ev); EMBX_Assert(ev->next == (EMBX_EVENT) EMBX_HANDLE_VALID); EMBX_Assert(semaphore_value(ev->event) == 0); ev->next = cacheHead; cacheHead = ev; EMBX_OS_MUTEX_RELEASE(&cacheLock); }
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_RegisterTransformer(const char *name, MME_AbortCommand_t abortFunc, MME_GetTransformerCapability_t getTransformerCapabilityFunc, MME_InitTransformer_t initTransformerFunc, MME_ProcessCommand_t processCommandFunc, MME_TermTransformer_t termTransformerFunc) #endif { MMEReceiverFactory* factory; #ifndef MME_LEAN_AND_MEAN if (NULL == manager) { return MME_DRIVER_NOT_INITIALIZED; } if (NULL == name) { return MME_INVALID_ARGUMENT; } /* iterate over the (singly linked) factory list looking for duplicates */ for (factory = manager->factoryList; NULL != factory; factory = factory->next) { if (0 == strcmp(factory->transformerType, name)) { return MME_INVALID_ARGUMENT; } } #endif factory = malloc(sizeof(MMEReceiverFactory) + strlen(name) + 1); if (NULL == factory) { return MME_NOMEM; } factory->transformerType = (const char *) (factory + 1); strcpy((void *) factory->transformerType, name); factory->abortFunc = abortFunc; factory->getTransformerCapabilityFunc = getTransformerCapabilityFunc; factory->initTransformerFunc = initTransformerFunc; factory->processCommandFunc = processCommandFunc; factory->termTransformerFunc = termTransformerFunc; #ifdef EMBX_RECEIVE_CALLBACK factory->createThread = createThread; #endif /* EMBX_RECEIVE_CALLBACK */ EMBX_OS_MUTEX_TAKE(&(manager->factoryListMutex)); factory->next = manager->factoryList; manager->factoryList = factory; EMBX_OS_MUTEX_RELEASE(&(manager->factoryListMutex)); return MME_SUCCESS; }
MME_ERROR MME_MessageQueue_Enqueue(MMEMessageQueue * msgQ, void *message, unsigned int priority) { MMEMessageQueueEntry *entry; MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Enqueue(0x%08x, 0x%08x)\n", (unsigned) msgQ, (unsigned) message)); EMBX_OS_MUTEX_TAKE(&msgQ->queueLock); /* fetch a free linkage structure from the free list */ entry = msgQ->free_list; if (NULL == entry) { EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Enqueue = MME_NOMEM\n")); return MME_NOMEM; } msgQ->free_list = entry->next; /* fill in the linkage structure */ entry->next = NULL; entry->priority = priority; entry->message = message; /* add it to the unsorted FIFO queue. we use a FIFO queue in order to * exploit the FIFO optimizations in SortMMEMessageQueue. */ if (NULL == msgQ->unsorted_front) { msgQ->unsorted_front = entry; } else { msgQ->unsorted_back->next = entry; } msgQ->unsorted_back = entry; EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Enqueue = MME_SUCCESS\n")); return MME_SUCCESS; }
/* * Transport method to close an open handle */ static EMBX_ERROR closeHandle (EMBX_Transport_t *tp, EMBX_TransportHandle_t *tph) { EMBXSHM_Transport_t *tpshm = (EMBXSHM_Transport_t *)tp; EMBX_EventState_t *es, *next; EMBX_Info (EMBX_INFO_TRANSPORT, (">>>closeHandle()\n")); EMBX_Assert (tpshm); EMBX_Assert (tph); EMBX_OS_MUTEX_TAKE (&tpshm->connectionListMutex); /* * Unblock processes waiting for a connection through the closing handle */ for (es = tpshm->connectionRequests; es; es = next) { EMBXSHM_ConnectBlockState_t *cbs = es->data; /* match with CBS IN DATA */ next = es->next; if (cbs->requestingHandle == tph) { EMBX_EventListRemove(&tpshm->connectionRequests, es); EMBX_OS_MemFree (cbs); es->result = EMBX_TRANSPORT_CLOSED; EMBX_OS_EVENT_POST (&es->event); } } EMBX_OS_MUTEX_RELEASE (&tpshm->connectionListMutex); /* * Make key handle structures invalid to help catch use after close */ tph->state = EMBX_HANDLE_CLOSED; tph->transport = 0; EMBX_OS_MemFree (tph); EMBX_OS_MODULE_UNREF(); EMBX_Info (EMBX_INFO_TRANSPORT, ("<<<closeHandle = EMBX_SUCCESS\n")); return EMBX_SUCCESS; }
static void unblockWaitors(RemoteTransformer_t* remoteTransformer, MME_Event_t event, CommandSlot_t* command) { HostManager_t* manager = MMEGetManager(); /* Lock whilst this thread does event notification */ MME_Assert(manager); EMBX_OS_MUTEX_TAKE(&manager->eventLock); manager->eventTransformer = remoteTransformer; manager->eventCommand = command; manager->eventCommandType = event; EMBX_OS_EVENT_POST(command->waitor); EMBX_OS_EVENT_WAIT(&manager->waitorDone); EMBX_OS_MUTEX_RELEASE(&manager->eventLock); }
EMBX_ERROR EMBX_CloseTransport(EMBX_TRANSPORT htp) { EMBX_ERROR res = EMBX_INVALID_TRANSPORT; EMBX_Info(EMBX_INFO_TRANSPORT, (">>>>EMBX_CloseTransport(htp=0x%08lx)\n",(unsigned long)htp)); EMBX_DebugOn(EMBX_INFO_TRANSPORT); if(!_embx_dvr_ctx.isLockInitialized) { EMBX_DebugMessage((_driver_uninit_error)); goto exit; } if(!EMBX_HANDLE_ISTYPEOF(htp, EMBX_HANDLE_TYPE_TRANSPORT)) { goto exit; } EMBX_OS_MUTEX_TAKE(&_embx_dvr_ctx.lock); if(_embx_dvr_ctx.state != EMBX_DVR_INITIALIZED && _embx_dvr_ctx.state != EMBX_DVR_IN_SHUTDOWN ) { EMBX_DebugMessage((_driver_uninit_error)); } else { res = do_close_transport(htp); } EMBX_OS_MUTEX_RELEASE(&_embx_dvr_ctx.lock); exit: EMBX_DebugOff(EMBX_INFO_TRANSPORT); EMBX_Info(EMBX_INFO_TRANSPORT, ("<<<<EMBX_CloseTransport(htp=0x%08lx) = %d\n",(unsigned long)htp, res)); return res; }
MME_ERROR MME_MessageQueue_RemoveByValue(MMEMessageQueue *msgQ, void *message) { MMEMessageQueueEntry **prev, *cur; sortMessageQueue(msgQ); EMBX_OS_MUTEX_TAKE(&msgQ->queueLock); for (cur = *(prev = &msgQ->sorted_front); cur; cur = *(prev = &cur->next)) { if (cur->message == message) { /* dequeue the message */ *prev = cur->next; /* push it onto the free list */ cur->next = msgQ->free_list; msgQ->free_list = cur; break; } } EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock); return (cur ? MME_SUCCESS : MME_INVALID_ARGUMENT); }
MME_ERROR MME_IsStillAlive(MME_TransformerHandle_t handle, MME_UINT* alive) { Transformer_t *transformer; MME_ERROR result; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } #endif EMBX_OS_MUTEX_TAKE(&manager->monitorMutex); result = findTransformerInstance(handle, &transformer); EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex); if (result != MME_SUCCESS) { /* cannot find transformer for this handle */ return MME_INVALID_HANDLE; } result = transformer->vtable->isStillAlive(transformer, alive); return result; }
/* * Remote port method to perform an object update */ static EMBX_ERROR updateObject (EMBX_RemotePortHandle_t *ph, EMBX_HANDLE handle, EMBX_UINT offset, EMBX_UINT size) { EMBXSHM_RemotePortHandle_t *remotePortHandle = (EMBXSHM_RemotePortHandle_t *)ph; EMBXSHM_Transport_t *tpshm; EMBXSHM_Object_t *obj; EMBX_ERROR err = EMBX_SUCCESS; EMBX_Info(EMBX_INFO_REMOTEPORT, (">>>updateObject(0x%08x, ...)\n", (unsigned) ph)); EMBX_Assert (ph); EMBX_Assert (ph->transportHandle); tpshm = (EMBXSHM_Transport_t *)ph->transportHandle->transport; EMBX_Assert (tpshm); /* * Do some up front sanity checks */ obj = EMBXSHM_findObject (tpshm, handle); if ((obj == 0) || ((offset+size) > obj->size)) { EMBX_Info(EMBX_INFO_REMOTEPORT, ("<<<updateObject = EMBX_INVALID_ARGUMENT\n")); return EMBX_INVALID_ARGUMENT; } EMBX_Assert(EMBXSHM_ALIGNED_TO_CACHE_LINE(obj)); /* * See if this is a local or remote send/update */ if (remotePortHandle->destinationCPU == tpshm->cpuID) { /* * A local update, so we're all done */ EMBX_Info(EMBX_INFO_REMOTEPORT, ("<<<updateObject = EMBX_SUCCESS\n")); return EMBX_SUCCESS; } else { /* * This is an object update to a port owned by another CPU. * We may need to copy shadowed data around, and possibly * send an update message to the other guy. */ EMBXSHM_PipeElement_t element; EMBX_VOID *dst = BUS_TO_LOCAL (obj->sharedData, tpshm->pointerWarp); /* * Update the shared copy of this object is it is shadowed from a master * copy on this CPU. */ if (obj->owningCPU == tpshm->cpuID && obj->shadow) { memcpy ((void*)((size_t)dst+offset), (void*)((size_t)obj->localData+offset), size); } /* * Ensure the object data is not held in our own cache. */ if (obj->mode == EMBX_INCOHERENT_MEMORY) EMBX_OS_FlushCache((char *)dst+offset, size); /* * Under the protection of the accessMutex, check the port state * is still OK. If it is, then the local port we're pointing to * is still OK too. By the time the message gets to the other * side (could be another CPU), then the local port could could * have been closed out - he will drop it on the floor. */ EMBX_OS_MUTEX_TAKE (&remotePortHandle->accessMutex); if (remotePortHandle->port.state != EMBX_HANDLE_VALID) { EMBX_OS_MUTEX_RELEASE (&remotePortHandle->accessMutex); return EMBX_INVALID_STATUS; } EMBX_Assert (remotePortHandle->destination.sharedPort->owningCPU == remotePortHandle->destinationCPU); /* * Now inform the partner CPU that the object has been updated. */ element.control = EMBXSHM_PIPE_CTRL_OBJ_UPDATE; element.data.msg_send.port = (EMBXSHM_LocalPortShared_t*) LOCAL_TO_BUS ( remotePortHandle->destination.sharedPort, tpshm->pointerWarp); element.data.obj_send.handle = handle; element.data.obj_send.data = obj->sharedData; element.data.obj_send.offset = offset; element.data.obj_send.size = size; err = EMBXSHM_enqueuePipeElement (tpshm, remotePortHandle->destinationCPU, &element); EMBX_OS_MUTEX_RELEASE (&remotePortHandle->accessMutex); } EMBX_Info(EMBX_INFO_REMOTEPORT, ("<<<sendObject = %d\n", err)); return err; }