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); }
static void make_connections(EMBXLB_Transport_t *tplb, EMBXLB_LocalPortHandle_t *phlb, const EMBX_CHAR *portName) { EMBXLB_ConnectBlockList_t *cbl = tplb->connectionRequests; EMBX_BOOL bRefuseConnection = EMBX_FALSE; /* In this transport we can directly access the connect block list, * without any additional locking, as all access to it is via API * calls which are serialized by the driver lock in the API * framework. If this transport had to use another thread to * manage connections then a transport level lock on the block list * would be required for all accesses to the list. */ while(cbl != 0) { EMBXLB_ConnectBlockList_t *next = cbl->next; /* We cannot use the phlb->port.portName member yet as it * hasn't been initialized. */ if(!strcmp(portName, cbl->portName)) { if(bRefuseConnection) { cbl->ev->result = EMBX_CONNECTION_REFUSED; } else { cbl->ev->result = create_remote_port(phlb, cbl->port); /* If we only support single connections then we must refuse any other * connection request for the same port name, assuming the * connection we just tried succeeded. */ if( cbl->ev->result == EMBX_SUCCESS && !tplb->transport.transportInfo.allowsMultipleConnections ) { bRefuseConnection = EMBX_TRUE; } } EMBX_OS_EVENT_POST(&cbl->ev->event); if(cbl->prev != 0) cbl->prev->next = next; else tplb->connectionRequests = next; if(next != 0) next->prev = cbl->prev; EMBX_OS_MemFree(cbl); } cbl = next; } }
MME_ERROR MME_FreeDataBuffer(MME_DataBuffer_t *dataBuffer) { struct InternalDataBuffer *buf = (struct InternalDataBuffer *) dataBuffer; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } if (NULL == buf) { return MME_INVALID_ARGUMENT; } if (buf->buffer.ScatterPages_p != buf->pages) { return MME_INVALID_ARGUMENT; } #endif if (0 == (buf->flags & MME_ALLOCATION_CACHED)) { if (EMBX_SUCCESS != EMBX_Free(buf->pages[0].Page_p)) { return MME_INVALID_ARGUMENT; } } EMBX_OS_MemFree(buf); return MME_SUCCESS; }
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; }
static EMBX_ERROR close_port(EMBX_RemotePortHandle_t *ph) { EMBXLB_RemotePortHandle_t *phlb = (EMBXLB_RemotePortHandle_t *)ph; if(phlb->destination != 0) { /* This port is still connected to a valid destination * so remove the port for the destination's remote * connection list. */ if(phlb->prevConnection != 0) phlb->prevConnection->nextConnection = phlb->nextConnection; else phlb->destination->remote_connections = phlb->nextConnection; if(phlb->nextConnection != 0) phlb->nextConnection->prevConnection = phlb->prevConnection; phlb->destination = 0; phlb->nextConnection = 0; phlb->prevConnection = 0; } phlb->port.state = EMBX_HANDLE_CLOSED; phlb->port.transportHandle = 0; EMBX_OS_MemFree(phlb); return EMBX_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; }
/* * 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; }
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 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; }
/* 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")); }
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); }
MME_ERROR MME_HostInit(void) #endif { if (NULL != manager) { return MME_DRIVER_ALREADY_INITIALIZED; } manager = EMBX_OS_MemAlloc(sizeof(HostManager_t)); if (!manager) { return MME_NOMEM; } memset(manager, 0, sizeof(HostManager_t)); manager->transformerInstances = MME_LookupTable_Create(MAX_TRANSFORMER_INSTANCES, 1); if (!manager->transformerInstances) { goto error_path; } if (EMBX_FALSE == EMBX_OS_MUTEX_INIT(&manager->monitorMutex)) { goto error_path; } if (EMBX_FALSE == EMBX_OS_MUTEX_INIT(&manager->eventLock)) { goto error_path; } if (EMBX_FALSE == EMBX_OS_EVENT_INIT(&manager->waitorDone)) { goto error_path; } return MME_SUCCESS; error_path: if (manager->transformerInstances) { MME_LookupTable_Delete(manager->transformerInstances); } EMBX_OS_MemFree(manager); manager = NULL; return MME_NOMEM; }
static EMBX_ERROR grow_port_table(EMBXLB_Transport_t *tplb, EMBX_INT *freeSlot) { EMBXLB_LocalPortHandle_t **newTable; EMBX_UINT newTableSize; EMBX_UINT nBytes; *freeSlot = tplb->portTableSize; newTableSize = tplb->portTableSize * 2; if(newTableSize < tplb->portTableSize) { EMBX_DebugMessage(("EMBXLB::grow_port_table 'table size overflowed!!!'\n")); return EMBX_NOMEM; } nBytes = newTableSize*sizeof(EMBXLB_LocalPortHandle_t *); newTable = (EMBXLB_LocalPortHandle_t **)EMBX_OS_MemAlloc(nBytes); if(newTable != 0) { memset(newTable, 0, nBytes); memcpy(newTable, tplb->portTable, tplb->portTableSize*sizeof(EMBXLB_LocalPortHandle_t *)); EMBX_OS_MemFree(tplb->portTable); tplb->portTable = newTable; tplb->portTableSize = newTableSize; EMBX_DebugMessage(("EMBXLB::grow_port_table 'new port table size = %u'\n", newTableSize)); return EMBX_SUCCESS; } EMBX_DebugMessage(("EMBXLB::grow_port_table 'could not grow port table'\n")); return EMBX_NOMEM; }
static EMBX_VOID connect_interrupt(EMBX_TransportHandle_t *tp, EMBX_EventState_t *es) { EMBXLB_Transport_t *tplb = (EMBXLB_Transport_t *)tp->transport; EMBXLB_ConnectBlockList_t *cpl = tplb->connectionRequests; /* In this transport we can directly access the connect block list * without any additional locking. */ while(cpl != 0) { EMBXLB_ConnectBlockList_t *next = cpl->next; if(cpl->ev == es) { /* Found the interrupted entry, so unhook it from the blocked list * and destroy the structure. This can be the only entry with this * eventState pointer, so return immediately. */ if(cpl->prev != 0) cpl->prev->next = next; else tplb->connectionRequests = next; if(next != 0) next->prev = cpl->prev; EMBX_OS_MemFree(cpl); return; } cpl = next; } }
static EMBX_ERROR do_send(EMBXLB_RemotePortHandle_t *phlb , EMBX_RECEIVE_TYPE evtype, EMBX_HANDLE handle, EMBX_VOID *data , EMBX_UINT offset, EMBX_UINT size ) { if(phlb->destination->blocked_receivers != 0) { EMBXLB_RecBlockList_t *receiver; /* Pick the first blocked receiver and put the object event info * directly into its receive event structure, then signal it to * wake up. */ receiver = phlb->destination->blocked_receivers; phlb->destination->blocked_receivers = receiver->next; receiver->recev->handle = handle; receiver->recev->data = data; receiver->recev->offset = offset; receiver->recev->size = size; receiver->recev->type = evtype; receiver->ev->result = EMBX_SUCCESS; EMBX_OS_EVENT_POST(&receiver->ev->event); EMBX_OS_MemFree(receiver); } else { EMBXLB_RecEventList_t *node; /* Nobody is waiting for the message so we have to queue it * on the destination */ node = (EMBXLB_RecEventList_t *)EMBX_OS_MemAlloc(sizeof(EMBXLB_RecEventList_t)); if(node == 0) return EMBX_NOMEM; node->recev.handle = handle; node->recev.data = data; node->recev.offset = offset; node->recev.size = size; node->recev.type = evtype; node->next = 0; if(phlb->destination->pending_head != 0) { phlb->destination->pending_tail->next = node; phlb->destination->pending_tail = node; } else { phlb->destination->pending_tail = node; phlb->destination->pending_head = node; } } return EMBX_SUCCESS; }
/* * 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; }
Transformer_t* MME_RemoteTransformer_Create(HostManager_t *manager, TransportInfo_t* info, EMBX_PORT adminPort) { static const TransformerVTable_t vtable = { RemoteTransformer_Destroy, RemoteTransformer_Init, RemoteTransformer_Term, RemoteTransformer_Kill, RemoteTransformer_AbortCommand, RemoteTransformer_KillCommand, RemoteTransformer_SendCommand, RemoteTransformer_IsStillAlive, RemoteTransformer_GetTransformerCapability, RemoteTransformer_WaitForMessage, RemoteTransformer_LookupCommand, RemoteTransformer_ReleaseCommandSlot }; RemoteTransformer_t* remoteTransformer; int i; remoteTransformer = EMBX_OS_MemAlloc(sizeof(RemoteTransformer_t)); if (!remoteTransformer) { return NULL; } /* zero the structure */ memset(remoteTransformer, 0, sizeof(RemoteTransformer_t)); /* initialize the non-zero elements */ remoteTransformer->super.vtable = &vtable; remoteTransformer->super.manager = manager; remoteTransformer->super.info = info; remoteTransformer->adminPort = adminPort; remoteTransformer->maxCommandSlots = MAX_TRANSFORMER_SEND_OPS; /* allocate the command slots (used to keep track of in-flight commands) */ remoteTransformer->commandSlots = EMBX_OS_MemAlloc(sizeof(CommandSlot_t) * remoteTransformer->maxCommandSlots); if (0 == remoteTransformer->commandSlots) { goto error_recovery; } for (i=0; i<remoteTransformer->maxCommandSlots; i++) { remoteTransformer->commandSlots[i].command = 0; remoteTransformer->commandSlots[i].status = MME_COMMAND_COMPLETED_EVT; } if (!EMBX_OS_EVENT_INIT(&remoteTransformer->terminateWasReplied)) { goto error_recovery; } if (!EMBX_OS_MUTEX_INIT(&remoteTransformer->commandSlotLock)) { EMBX_OS_EVENT_DESTROY(&remoteTransformer->terminateWasReplied); goto error_recovery; } /* reference the transport info structure (so it can't be deregistered) */ info->referenceCount++; return &remoteTransformer->super; error_recovery: /* EMBX_OS_MemFree() will ignore NULL pointers */ EMBX_OS_MemFree(remoteTransformer->commandSlots); EMBX_OS_MemFree(remoteTransformer); return NULL; }
void MME_LookupTable_Delete(MMELookupTable_t *tbl) { MME_Assert(tbl); EMBX_OS_MemFree(tbl); }
EMBX_Transport_t *EMBXLB_loopback_factory(void *param) { EMBXLB_Config_t *config = (EMBXLB_Config_t *)param; EMBXLB_Transport_t *tp; if(config->name == 0) return 0; if(strlen(config->name) > EMBX_MAX_TRANSPORT_NAME) return 0; /* The transport structure _must_ be allocated from OS * memory. It is managed from now on by the framework. */ tp = (EMBXLB_Transport_t *)EMBX_OS_MemAlloc(sizeof(EMBXLB_Transport_t)); if(tp == 0) return 0; /* Decide which type of initialization to do. * PLEASE NOTE: This is for the purposes of testing * the behaviour of the framework ONLY, a more realistic * transport implementation would either block, or not, * depending on the nature of its initialization * requirements. */ if(config->blockInit) { memcpy(tp,&_embxlb_blocktransport_template,sizeof(EMBXLB_Transport_t)); } else { memcpy(tp,&_embxlb_transport_template,sizeof(EMBXLB_Transport_t)); } /* Limiting the number of alocations is for testing the framework * error handling only. A more realistic transport would not do this. */ tp->maxAllocations = config->maxAllocations; /* 0 = no limit */ /* A more realistic transport would likely support only one of the * connection semantics. This configuration is for the purposes of * testing the framework. */ tp->transport.transportInfo.allowsMultipleConnections = config->multiConnect; tp->transport.transportInfo.maxPorts = config->maxPorts; /* 0 = no limit */ strcpy(tp->transport.transportInfo.name,config->name); if(config->maxObjects > 0) { if(!EMBX_HandleManager_SetSize(&tp->objectHandleManager, config->maxObjects)) { EMBX_OS_MemFree(tp); return 0; } } else { EMBX_HandleManager_SetSize(&tp->objectHandleManager, EMBX_HANDLE_DEFAULT_TABLE_SIZE); } return &tp->transport; }
static EMBX_ERROR do_close_transport(EMBX_TRANSPORT htp) { EMBX_ERROR res = EMBX_INVALID_TRANSPORT; EMBX_TransportHandle_t *tph; tph = (EMBX_TransportHandle_t *)EMBX_HANDLE_GETOBJ(&_embx_handle_manager, htp); if(tph != 0) { EMBX_Transport_t *tp; EMBX_TransportHandleList_t *handleList; if( (tph->state != EMBX_HANDLE_VALID) && (tph->state != EMBX_HANDLE_INVALID) ) { EMBX_DebugMessage(("Failed 'transport handle state is corrupted'\n")); return EMBX_INVALID_TRANSPORT; } if( (tph->localPorts != 0) || (tph->remotePorts != 0) ) { EMBX_DebugMessage(("Failed 'transport still has open ports'\n")); return EMBX_PORTS_STILL_OPEN; } tp = tph->transport; handleList = tp->transportHandles; while(handleList) { if(handleList->transportHandle == tph) break; handleList = handleList->next; } #if defined(EMBX_VERBOSE) if(handleList == 0) { EMBX_DebugMessage(("Unable to find transport handle (0x%08lx) on transport (0x%08lx) handle list!\n",(unsigned long)tph,(unsigned long)tp)); } #endif /* EMBX_VERBOSE */ res = tp->methods->close_handle(tp, tph); if(res == EMBX_SUCCESS) { /* At this point tph has been freed by the transport * so we must not use it again. */ EMBX_HANDLE_FREE(&_embx_handle_manager, htp); tp->transportInfo.nrOpenHandles--; /* Unhook the transport handle list entry */ if(handleList != 0) { if(handleList->prev != 0) handleList->prev->next = handleList->next; else tp->transportHandles = handleList->next; if(handleList->next != 0) handleList->next->prev = handleList->prev; EMBX_OS_MemFree(handleList); } if(tp->closeEvent != 0 && tp->transportHandles == 0) { /* Another thread is waiting for the last handle to * close on this transport. Signal it now this has * happened. */ EMBX_OS_EVENT_POST(&tp->closeEvent->event); } } } return res; }
MME_ERROR MME_AllocDataBuffer(MME_TransformerHandle_t handle, MME_UINT size, MME_AllocationFlags_t flags, MME_DataBuffer_t ** dataBuffer_p) { static const MME_AllocationFlags_t illegalFlags = (MME_AllocationFlags_t) ~(MME_ALLOCATION_PHYSICAL | MME_ALLOCATION_CACHED | MME_ALLOCATION_UNCACHED); Transformer_t *transformer; struct InternalDataBuffer *buf; unsigned localSize; #ifndef MME_LEAN_AND_MEAN if (manager == NULL) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Driver not initialized\n")); return MME_DRIVER_NOT_INITIALIZED; /* the manager must exist */ } if (0 == size || NULL == dataBuffer_p || (flags & illegalFlags)) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "size==0 || NULL == dataBuffer_p || (flags & illegalFlags)\n")); return MME_INVALID_ARGUMENT; } if (0 > (int) size) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "size<0\n")); return MME_NOMEM; } #endif /* lookup whether we should allocate using EMBX_OS_MemAlloc or EMBX_Alloc() */ if (MME_SUCCESS != findTransformerInstance(handle, &transformer)) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "invalid transformer handle\n")); return MME_INVALID_HANDLE; } if (0 == transformer->info) { /* this is a local transformers so we can't allocate memory using EMBX_Alloc */ flags |= MME_ALLOCATION_CACHED; } /* Allocate the buffer structure */ /* Cannot present a "negative" value to EMBX_OS_MemAlloc on SHLINUX KERNEL mode * as it "succeeds" and returns a non-NULL value */ localSize = (int) (sizeof(*buf) + (flags & MME_ALLOCATION_CACHED ? size + MME_MAX_CACHE_LINE-1 : 0)); if (0 > (int) localSize) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "localSze <0\n")); return MME_NOMEM; } buf = EMBX_OS_MemAlloc(localSize); if (NULL == buf) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Cannot EMBX_OS_MemAlloc(%d)\n", sizeof(*buf) + (flags & MME_ALLOCATION_CACHED ? size : 0) )); return MME_NOMEM; } /* populate the buffer structure */ memset(buf, 0, sizeof(*buf)); buf->buffer.StructSize = sizeof(MME_DataBuffer_t); buf->buffer.NumberOfScatterPages = 1; buf->buffer.ScatterPages_p = buf->pages; buf->buffer.TotalSize = size; buf->flags = flags; buf->pages[0].Size = size; if (flags & MME_ALLOCATION_CACHED) { /* We MUST align the data buffer to a cacheline boundary to keep this safe */ buf->pages[0].Page_p = (void *) MME_CACHE_LINE_ALIGN((buf + 1)); } else { /* if transportHandle is 0 this will fail so we have no specific path to * prevent uncached allocations for local transformers. */ EMBX_ERROR err = EMBX_Alloc(transformer->info->handle, size, &buf->pages[0].Page_p); if (EMBX_SUCCESS != err) { MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Cannot EMBX_Alloc(0x%08x, %d, 0x%08x)\n", transformer->info->handle, size, (unsigned) &buf->pages[0].Page_p)); EMBX_OS_MemFree(buf); return MME_NOMEM; } } *dataBuffer_p = &(buf->buffer); return MME_SUCCESS; }
/* * Transport method to invalidate a transport */ static EMBX_VOID invalidate (EMBX_Transport_t *tp) { EMBXSHM_Transport_t *tpshm = (EMBXSHM_Transport_t *)tp; EMBX_TransportHandleList_t *thandles = tpshm->transport.transportHandles; EMBX_Info (EMBX_INFO_TRANSPORT, (">>>invalidate()\n")); EMBX_Assert (tpshm); /* * Tell the other CPUs we are about to invalidate the transport. */ if (!tpshm->remoteInvalidateFlag) { EMBXSHM_PipeElement_t element; int i; element.control = EMBXSHM_PIPE_CTRL_TRANSPORT_INVALIDATE; for (i=0; i<EMBXSHM_MAX_CPUS; i++) { if (i != tpshm->cpuID && tpshm->participants[i]) { EMBX_ERROR err; /* * We are already part way through the operation so we'll * keep trying to repost until we manage it. */ while (EMBX_SUCCESS != (err = EMBXSHM_enqueuePipeElement (tpshm, i, &element))) { EMBX_Assert (EMBX_NOMEM == err); EMBX_OS_Delay(10); } } } } thandles = tpshm->transport.transportHandles; /* * First of all wake up any pending connection requests */ EMBX_OS_MUTEX_TAKE (&tpshm->connectionListMutex); while (tpshm->connectionRequests) { EMBX_EventState_t *es = EMBX_EventListFront(&tpshm->connectionRequests); EMBX_OS_MemFree(es->data); /* match with CBS IN DATA */ /* * When we post this event we have effectively freed es, it must not be used again */ EMBX_OS_EVENT_POST (&es->event); } EMBX_OS_MUTEX_RELEASE (&tpshm->connectionListMutex); /* * Now go and deal with still open transport handles */ while (thandles) { EMBXSHM_TransportHandle_t *th = (EMBXSHM_TransportHandle_t *)thandles->transportHandle; doInvalidateHandle (th); thandles = thandles->next; } EMBX_Info (EMBX_INFO_TRANSPORT, ("<<<invalidate\n")); }