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;          
    }
}
static MME_ERROR RemoteTransformer_WaitForMessage(Transformer_t*  transformer, 
                                MME_Event_t*    eventPtr,
		                MME_Command_t** commandPtr)
{
	EMBX_RECEIVE_EVENT event;
	RemoteTransformer_t* remoteTransformer = (RemoteTransformer_t*)transformer;
	EMBX_ERROR err;
	
	MME_Assert(transformer);
	MME_Assert(eventPtr);
	MME_Assert(commandPtr);

	err = EMBX_ReceiveBlock(remoteTransformer->replyPort.port, &event);
	if (EMBX_SUCCESS != err) {
		*eventPtr = MME_COMMAND_COMPLETED_EVT;
		*commandPtr = NULL;
		return (err == EMBX_SYSTEM_INTERRUPT ? MME_SYSTEM_INTERRUPT
						     : MME_TRANSFORMER_NOT_RESPONDING);
	}
	
	MME_Assert(event.data);
	MME_Assert(event.type == EMBX_REC_MESSAGE);

	/* received message. */
	switch (((MME_UINT *) event.data)[0]) {
	case TMESSID_TRANSFORM:
		receiveTransformMessage(remoteTransformer, 
					(TransformerTransformMessage *) event.data, eventPtr, commandPtr);
		freeBuffer(remoteTransformer, event.data);
		return MME_SUCCESS;

	case TMESSID_STARVATION: {
		receiveStavationMessage(remoteTransformer,
					(TransformerStarvationMessage *) event.data, eventPtr, commandPtr);
		freeBuffer(remoteTransformer, event.data);
		return MME_SUCCESS;
	}
	case TMESSID_TERMINATE: {
		/* A Terminate message returned */
		remoteTransformer->terminationResult = ((TransformerTerminateMessage *) event.data)->result;
		MME_Assert(MME_SUCCESS == remoteTransformer->terminationResult);

		cleanupTerminateMessage(remoteTransformer,
				(TransformerTerminateMessage *) event.data);
		*eventPtr = MME_COMMAND_COMPLETED_EVT;
		*commandPtr = NULL;
		EMBX_OS_EVENT_POST(&remoteTransformer->terminateWasReplied);
		return MME_TRANSFORMER_NOT_RESPONDING;
	}
	default:
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "Unexpected message: %x\n", (unsigned) ((MME_UINT *) event.data)[0]));
		MME_Assert(0);
	}
	
	return MME_INTERNAL_ERROR;		
}	
Example #3
0
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;
		}
	}
}
Example #4
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;
}
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);
}
Example #6
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;
}
Example #7
0
/*
 * Helper function to kill off any worker threads started
 * by the transport. This is used in closedown and to tidy
 * up initialization if it fails.
 */
EMBX_ERROR EMBXSHM_killThread (EMBXSHM_Transport_t *tpshm,
                               EMBX_UINT            threadName)
{
    EMBX_ERROR res = EMBX_SUCCESS;

    EMBX_Info (EMBX_INFO_TRANSPORT, (">>>EMBXSHM_killThread()\n"));

    switch (threadName)
    {
        case EMBXSHM_NEWPORT_WORKER:
        {
            if(tpshm->locksValid && tpshm->secondHalfDieFlag == 0)
            {
		tpshm->secondHalfDieFlag = 1;

                EMBX_OS_EVENT_POST (&tpshm->secondHalfEvent);
            }

	    if (tpshm->secondHalfThread != EMBX_INVALID_THREAD)
	    {
		res = EMBX_OS_ThreadDelete(tpshm->secondHalfThread);
		if (res == EMBX_SUCCESS)
		{
		    tpshm->secondHalfThread = EMBX_INVALID_THREAD;
		}
	    }

            tpshm->secondHalfDieFlag = 0;
            break;
        } /* EMBXSHM_NEWPORT_WORKER */
        case EMBXSHM_CLOSEPORT_WORKER:
        {
            if(tpshm->locksValid && tpshm->closedPortDieFlag == 0)
            {
		tpshm->closedPortDieFlag = 1;

                EMBX_OS_EVENT_POST (&tpshm->closedPortEvent);
            }

 	    if (tpshm->closedPortThread != EMBX_INVALID_THREAD)
	    {
		res = EMBX_OS_ThreadDelete(tpshm->closedPortThread);
		if (res == EMBX_SUCCESS)
		{
		    tpshm->closedPortThread = EMBX_INVALID_THREAD;
		}
	    }

            tpshm->closedPortDieFlag = 0;
            break;
        } /* EMBXSHM_CLOSEPORT_WORKER */
        default:
        {
            EMBX_Assert(0);
            res = EMBX_INVALID_ARGUMENT;
        } /* default */
    }

    EMBX_Info (EMBX_INFO_TRANSPORT, ("<<<EMBXSHM_killThread\n"));

    return res;
}
Example #8
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"));
}
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;
}
Example #10
0
MME_ERROR MME_SendCommand(MME_TransformerHandle_t handle, MME_Command_t * commandInfo)
{
	Transformer_t *transformer;
	MME_ERROR         result;
	CommandSlot_t     *commandPrivate;

#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 == handle) {
 	        MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Invalid handle - NULL\n"));
                return MME_INVALID_HANDLE;
        }

        if (NULL == commandInfo ||
            commandInfo->StructSize != sizeof(MME_Command_t)) {
                MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Invalid struct size\n"));
                return MME_INVALID_ARGUMENT;
        }

        if (commandInfo->CmdCode != MME_SET_GLOBAL_TRANSFORM_PARAMS &&
            commandInfo->CmdCode != MME_TRANSFORM &&
            commandInfo->CmdCode != MME_SEND_BUFFERS) {
                MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Invalid command code\n"));
                return MME_INVALID_ARGUMENT;
        }

        if (commandInfo->CmdEnd != MME_COMMAND_END_RETURN_NO_INFO &&
            commandInfo->CmdEnd != MME_COMMAND_END_RETURN_NOTIFY) {
                MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Invalid command notify type\n"));
                return MME_INVALID_ARGUMENT;
        }
#endif

	EMBX_OS_MUTEX_TAKE(&manager->monitorMutex);

	result = findTransformerInstance(handle, &transformer);
	if (result != MME_SUCCESS) {
		/* cannot find transformer for this handle */
                MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Cannot find transformer with handle 0x%08x\n", handle));
		result = MME_INVALID_HANDLE;
		goto EXIT;
	}

	result = transformer->vtable->sendCommand(transformer, commandInfo, &commandPrivate);

#ifdef ENABLE_MME_WAITCOMMAND
	/* Wake up any thread waiting for new commands with MME_WaitCommand
           or place the new command in a 1-deep buffer for thread that is
           about to wait
         */

	/* Grab this mutex to prevent any command completion events from 
           fiddling with the manager event state */
	EMBX_OS_MUTEX_TAKE(&manager->eventLock);

	if (manager->newCommandEvents) {
		/* One or more threads waiting for a new command event */
		int i, waitors=0;
		NewCommand_t* current;

		manager->eventTransformer = transformer;
		manager->eventCommand = commandPrivate;
		manager->eventCommandType = MME_NEW_COMMAND_EVT;

		current = manager->newCommandEvents;
		while (current) {
			waitors++;
			EMBX_OS_EVENT_POST(current->event);
			current = current->next;
		}

		for (i=0; i<waitors; i++) {
			/* Wait for the last waitor thread to unblock and remove it's event */
			EMBX_OS_EVENT_WAIT(&manager->waitorDone);
		}

		/* All waitor threads have let us know they have dealt with new event - now remove them from the list */
		RemoveNewCommandEvents_HostManager();

		manager->newCommand = NULL;
		manager->newCommandTransformer = NULL;
	} else {
		manager->newCommand = commandInfo;
		manager->newCommandTransformer = transformer;
	}
	EMBX_OS_MUTEX_RELEASE(&manager->eventLock);
#endif

EXIT:
	EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex);
        MME_Info( MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "<<<< (%d)\n", result));
	return result;
}