MME_ERROR MME_Init(void) { if (manager) { return MME_DRIVER_ALREADY_INITIALIZED; } manager = malloc(sizeof(MMEManager_t)); if (NULL == manager) { return MME_NOMEM; } memset(manager, 0, sizeof(*manager)); if (!EMBX_OS_MUTEX_INIT(&(manager->factoryListMutex))) { goto error_recovery; } if (!EMBX_OS_MUTEX_INIT(&(manager->abortMutex))) { goto error_recovery; } return MME_SUCCESS; error_recovery: if (manager->factoryListMutex) { EMBX_OS_MUTEX_DESTROY(&(manager->factoryListMutex)); } if (manager->abortMutex) { EMBX_OS_MUTEX_DESTROY(&(manager->abortMutex)); } EMBX_OS_MemFree(manager); return MME_NOMEM; }
MME_ERROR MME_HostTerm(void) #endif { TransportInfo_t *tpInfo, *next; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Failed to find transformer instance\n")); return MME_DRIVER_NOT_INITIALIZED; } #endif if (!MME_LookupTable_IsEmpty(manager->transformerInstances)) { /* Need to close all transformers first */ MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Handles still open\n")); return MME_HANDLES_STILL_OPEN; } /* Deregister all the transports (so that the companions receive terminate messages) */ for (tpInfo = manager->transportList; tpInfo && (next = tpInfo->next, 1); tpInfo = next) { destroyTransportInfo(tpInfo); } EMBX_OS_MUTEX_DESTROY(&manager->monitorMutex); EMBX_OS_MUTEX_DESTROY(&manager->eventLock); EMBX_OS_EVENT_DESTROY(&manager->waitorDone); MME_LookupTable_Delete(manager->transformerInstances); EMBX_OS_MemFree(manager); manager = NULL; return MME_SUCCESS; }
MME_ERROR MME_Deinit(void) { EMBX_ERROR err; int i; if (manager == NULL) { return MME_DRIVER_NOT_INITIALIZED; } MME_Info(MME_INFO_MANAGER, ("TerminateMMEManager...\n")); /* We cannot terminate if there is any receiver * * TODO: this is not thread-safe (and the receiver list locks are no * good here). we really need request the manager thread perform the * shutdown, the same code would be safe there! */ for (i=0; i<MME_NUM_EXECUTION_LOOPS; i++) { if (NULL != manager->receiverLists[i]) { MME_Info(MME_INFO_MANAGER, ("Cannot terminate MMEManager, receiverList isn't empty\n")); return MME_COMMAND_STILL_EXECUTING; /* potentially, this is true */ } } /* reap all the execution loop threads */ terminateExecutionLoops(manager); /* TODO: there should normally be no need to reap the thread since it this code * should refuse to run if MME_Run() is still active. */ manager->managerRunning = 0; /* TODO: this cleanup should be delegated to MME_DeregisterTransport() */ /* Close the administration port. */ MME_Info(MME_INFO_MANAGER, ("Invalidate adminPort...\n")); err = EMBX_InvalidatePort(manager->adminPort); MME_Info(MME_INFO_MANAGER, ("Invalidate adminPort...err %d\n", err)); MME_Info(MME_INFO_MANAGER, ("Close adminPort...\n")); err = EMBX_ClosePort(manager->adminPort); MME_Info(MME_INFO_MANAGER, ("Close adminPort...err %d\n", err)); /* Close the transport and EMBX. */ MME_Info(MME_INFO_MANAGER, ("Close Transport...\n")); err = EMBX_CloseTransport(manager->transportHandle); MME_Info(MME_INFO_MANAGER, ("EMBX_CloseTransport() - handle %d\n", manager->transportHandle)); if (err != EMBX_SUCCESS) { MME_Info(MME_INFO_MANAGER, ("EMBX_CloseTransport() failed, error=%d\n", err)); } /* Delete the mutex. */ EMBX_OS_MUTEX_DESTROY(&(manager->factoryListMutex)); EMBX_OS_MUTEX_DESTROY(&(manager->abortMutex)); EMBX_OS_MemFree(manager); manager = NULL; return MME_SUCCESS; }
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); }
/* Clean up and deallocate everything. */ void MME_MessageQueue_Term(MMEMessageQueue * msgQ) { MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Term(0x%08x)\n", (unsigned) msgQ)); EMBX_OS_MUTEX_DESTROY(&msgQ->queueLock); if (msgQ->queue != NULL) { EMBX_OS_MemFree(msgQ->queue); } memset(msgQ, 0, sizeof(*msgQ)); MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Term\n")); }
void __exit embx_deinit( void ) { remove_proc_entry("embx", NULL /* parent dir */); EMBX_Deinit(); EMBX_OS_MUTEX_DESTROY(&_embx_dvr_ctx.lock); _embx_dvr_ctx.isLockInitialized = EMBX_FALSE; EMBX_HandleManager_Destroy(&_embx_handle_manager); return; }
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 terminateExecutionLoops(MMEManager_t *mgr) { int i; for (i=0; i<MME_NUM_EXECUTION_LOOPS; i++) { if (mgr->loopTasksRunning[i]) { mgr->loopTasksRunning[i] = 0; EMBX_OS_EVENT_POST(&(mgr->commandEvents[i])); EMBX_OS_ThreadDelete(mgr->loopTasks[i]); EMBX_OS_EVENT_DESTROY(&(mgr->commandEvents[i])); EMBX_OS_MUTEX_DESTROY(&(mgr->receiverListMutexes[i])); mgr->loopTasks[i] = NULL; mgr->receiverLists[i] = NULL; } } }
/* * Remote port close method. */ static EMBX_ERROR closePort (EMBX_RemotePortHandle_t *ph) { EMBXSHM_RemotePortHandle_t *remotePortHandle = (EMBXSHM_RemotePortHandle_t *)ph; EMBXSHM_Transport_t *tpshm; EMBX_Info(EMBX_INFO_REMOTEPORT, (">>>closePort(0x%08x)\n", (unsigned) ph)); EMBX_Assert (remotePortHandle); tpshm = (EMBXSHM_Transport_t *)remotePortHandle->port.transportHandle->transport; EMBX_Assert (tpshm); /* * Take the port close/invalidate locks to ensure serialisation */ EMBXSHM_takeSpinlock (tpshm, &tpshm->portConnectMutex, tpshm->portConnectSpinlock); EMBXSHM_READS(remotePortHandle->linkageShared); /* * No need to take the accessMutex here - we're protected by the shell level * transport lock (to serialise with sends), and we're serialised with the * port close notification by the portConnect* locks */ if (remotePortHandle->port.state != EMBX_HANDLE_INVALID) { EMBXSHM_LocalPortShared_t *localPortShared; EMBXSHM_RemotePortLink_t *prev; /* * Work out how to access the shared part of the local port * structure */ if (remotePortHandle->destinationCPU == tpshm->cpuID) { localPortShared = remotePortHandle->destination.localPort->localPortShared; } else { localPortShared = remotePortHandle->destination.sharedPort; } EMBX_Assert(EMBXSHM_ALIGNED_TO_CACHE_LINE(localPortShared)); EMBXSHM_READS(localPortShared); prev = remotePortHandle->linkageShared->prevConnection; EMBX_Assert(EMBXSHM_ALIGNED_TO_CACHE_LINE(prev)); /* * This port is still connected to a valid destination * so remove the port from the destination's remote connection * list */ if (prev) { EMBXSHM_RemotePortLink_t *p = BUS_TO_LOCAL(prev, tpshm->pointerWarp); EMBXSHM_READS(p); p->nextConnection = remotePortHandle->linkageShared->nextConnection; EMBXSHM_WROTE(p); } else { localPortShared->remoteConnections = remotePortHandle->linkageShared->nextConnection; EMBXSHM_WROTE(localPortShared); } if (remotePortHandle->linkageShared->nextConnection) { EMBXSHM_RemotePortLink_t *next; next = (EMBXSHM_RemotePortLink_t*)BUS_TO_LOCAL (remotePortHandle->linkageShared->nextConnection, tpshm->pointerWarp); EMBXSHM_READS(next); EMBX_Assert(EMBXSHM_ALIGNED_TO_CACHE_LINE(localPortShared)); next->prevConnection = remotePortHandle->linkageShared->prevConnection; EMBXSHM_WROTE(next); } } remotePortHandle->port.state = EMBX_HANDLE_CLOSED; remotePortHandle->port.transportHandle = 0; /* * Done with port close invalidate stuff, so release locks */ EMBXSHM_releaseSpinlock (tpshm, &tpshm->portConnectMutex, tpshm->portConnectSpinlock); EMBXSHM_free (tpshm, remotePortHandle->linkageShared); EMBX_OS_MUTEX_DESTROY (&remotePortHandle->accessMutex); EMBX_OS_MemFree (remotePortHandle); EMBX_Info(EMBX_INFO_REMOTEPORT, ("<<<closePort = EMBX_SUCCESS\n")); return EMBX_SUCCESS; }