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; }
/* * Transport method to open a handle */ static EMBX_ERROR openHandle (EMBX_Transport_t *tp, EMBX_TransportHandle_t **tph) { EMBXSHM_TransportHandle_t *handle; EMBX_Info (EMBX_INFO_TRANSPORT, (">>>openHandle()\n")); EMBX_Assert (tp); EMBX_Assert (tph); /* * Allocate memory for handle */ handle = (EMBXSHM_TransportHandle_t *)EMBX_OS_MemAlloc (sizeof (EMBXSHM_TransportHandle_t)); if (handle != NULL) { /* * Copy default structure contents. */ memcpy (handle, &EMBXSHM_transportHandleTemplate, sizeof (EMBXSHM_TransportHandle_t)); *tph = (EMBX_TransportHandle_t *)handle; EMBX_OS_MODULE_REF(); EMBX_Info (EMBX_INFO_TRANSPORT, ("<<<openHandle = EMBX_SUCCESS\n")); return EMBX_SUCCESS; } else { EMBX_Info (EMBX_INFO_TRANSPORT, ("<<<openHandle = EMBX_NOMEM\n")); return EMBX_NOMEM; } }
static EMBX_ERROR create_remote_port(EMBXLB_LocalPortHandle_t *localPort, EMBX_RemotePortHandle_t **port) { EMBXLB_RemotePortHandle_t *remotePort; remotePort = (EMBXLB_RemotePortHandle_t *)EMBX_OS_MemAlloc(sizeof(EMBXLB_RemotePortHandle_t)); if(remotePort != 0) { memcpy(remotePort, &_embxlb_remoteport_handle_template, sizeof(EMBXLB_RemotePortHandle_t)); remotePort->destination = localPort; remotePort->nextConnection = localPort->remote_connections; if(localPort->remote_connections != 0) localPort->remote_connections->prevConnection = remotePort; localPort->remote_connections = remotePort; *port = &remotePort->port; return EMBX_SUCCESS; } *port = 0; return EMBX_NOMEM; }
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; }
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; }
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; }
static EMBX_ERROR connect_block(EMBX_TransportHandle_t *tp, const EMBX_CHAR *portName, EMBX_EventState_t *es, EMBX_RemotePortHandle_t **port) { EMBX_ERROR res; res = connect_async(tp,portName,port); if(res == EMBX_PORT_NOT_BIND) { EMBXLB_ConnectBlockList_t *node; EMBXLB_Transport_t *tplb; /* Portname not found so try and block the task until it is created */ node = (EMBXLB_ConnectBlockList_t *)EMBX_OS_MemAlloc(sizeof(EMBXLB_ConnectBlockList_t)); if(node == 0) return EMBX_NOMEM; strcpy(node->portName, portName); /* In this transport we can directly access the connect block list * without any additional locking. */ tplb = (EMBXLB_Transport_t *)tp->transport; node->ev = es; node->port = port; node->requestingHandle = tp; /* Needed for close_handle to clean up its blocked connections */ node->prev = 0; node->next = tplb->connectionRequests; if(node->next != 0) node->next->prev = node; tplb->connectionRequests = node; return EMBX_BLOCK; } else { return res; } }
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; }
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; }
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; }
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_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; }
static EMBX_ERROR create_port(EMBX_TransportHandle_t *tp, const EMBX_CHAR *portName, EMBX_LocalPortHandle_t **port) { EMBX_ERROR res; EMBX_INT freeSlot; EMBXLB_LocalPortHandle_t *phlb; EMBXLB_Transport_t *tplb; tplb = (EMBXLB_Transport_t *)tp->transport; res = find_free_port_table_entry(tplb, portName, &freeSlot); switch (res) { case EMBX_SUCCESS: { break; } /* EMBX_SUCCESS */ case EMBX_NOMEM: { /* * If we have got to this point then there is no fixed * transport limit to number of ports (this is checked * in the shell) so try and grow the port table. */ if(grow_port_table(tplb, &freeSlot) != EMBX_SUCCESS) return EMBX_NOMEM; break; } /* EMBX_NOMEM */ default: { return res; } } phlb = (EMBXLB_LocalPortHandle_t *)EMBX_OS_MemAlloc(sizeof(EMBXLB_LocalPortHandle_t)); if(phlb != 0) { memcpy(phlb, &_embxlb_localport_handle_template, sizeof(EMBXLB_LocalPortHandle_t)); tplb->portTable[freeSlot] = phlb; *port = &phlb->port; /* * The transportHandle,port name and state members of the local port base * structure are filled in by the framework. */ /* * Finally, make connections for any blocked connection requests waiting * for this new port name. */ make_connections(tplb, phlb, portName); return EMBX_SUCCESS; } return EMBX_NOMEM; }
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; }