예제 #1
0
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);
	
	
}
예제 #2
0
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;          
    }
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
/*
 * 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;
}
예제 #9
0
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;	
}
예제 #10
0
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;
}
예제 #11
0
/* 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"));
}
예제 #12
0
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);
}
예제 #13
0
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;
}
예제 #14
0
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;
}
예제 #15
0
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;
    }
}
예제 #16
0
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;
}
예제 #17
0
/*
 * 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;
}
예제 #18
0
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;
}
예제 #19
0
void MME_LookupTable_Delete(MMELookupTable_t *tbl)
{
	MME_Assert(tbl);
	EMBX_OS_MemFree(tbl);
}
예제 #20
0
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;
}
예제 #21
0
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;
}
예제 #22
0
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;
}
예제 #23
0
/*
 * 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"));
}