Example #1
0
MME_ERROR MME_KillTransformer(MME_TransformerHandle_t handle)
{
	Transformer_t *transformer;
	MME_ERROR res;

#ifndef MME_LEAN_AND_MEAN
        if (NULL == manager) {
 	        MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Driver not initialized\n"));
                return MME_DRIVER_NOT_INITIALIZED;      /* the manager must exist */
        }
#endif

	EMBX_OS_MUTEX_TAKE(&manager->monitorMutex);

	/* Find the transformer */
	res = findTransformerInstance(handle, &transformer);
	if (res != MME_SUCCESS) {
		EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex);
 	        MME_Info( MME_INFO_MANAGER, (DEBUG_ERROR_STR "Failed to find transformer instance\n"));
		return MME_INVALID_HANDLE;
	}

	
	res = transformer->vtable->kill(transformer);
	if (MME_SUCCESS == res) {
		deregisterTransformerInstance(handle);

		transformer->vtable->destroy(transformer);
	}
	
	EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex);
	return res;
}
Example #2
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;
}
Example #3
0
MME_ERROR MME_MessageQueue_Dequeue(MMEMessageQueue * msgQ, void **message)
{
	MMEMessageQueueEntry *entry;

	MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Dequeue(0x%08x, ...)\n", (unsigned) msgQ));

	sortMessageQueue(msgQ);

	EMBX_OS_MUTEX_TAKE(&msgQ->queueLock);

	/* dequeue the first message */
	entry = msgQ->sorted_front;
	if (NULL == entry) {
		*message = NULL;
		MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Dequeue(..., 0x%08x) = MME_INVALID_HANDLE\n",
		                          (unsigned) *message));
		EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
		return MME_INVALID_HANDLE;
	}
	msgQ->sorted_front = entry->next;

	/* push it onto the free list */
	entry->next = msgQ->free_list;
	msgQ->free_list = entry;

	*message = entry->message;

	MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Dequeue(..., 0x%08x) = MME_SUCCESS\n",
				  (unsigned) *message));
	EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
	return MME_SUCCESS;
}
Example #4
0
MME_ERROR MME_MessageQueue_RemoveAll(MMEMessageQueue * msgQ)
{
	MMEMessageQueueEntry **prev;
	int i;

	MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_RemoveAll(0x%08x)\n", (unsigned) msgQ));
	MME_Assert(msgQ);
	MME_Assert(msgQ->maxEntries > 0);

	EMBX_OS_MUTEX_TAKE(&msgQ->queueLock);

	/* initialize the free list */
	for (prev = &(msgQ->free_list), i=0;
	     i < msgQ->maxEntries;
	     prev = &(msgQ->queue[i].next), i++) {
		*prev = &(msgQ->queue[i]);
	}
	*prev = NULL;

	msgQ->sorted_front = 0;
	msgQ->unsorted_front = 0;

	EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
	MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_RemoveAll = MME_SUCCESS\n"));
	return MME_SUCCESS;
}
Example #5
0
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;
}
Example #6
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"));
}
Example #7
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;	
}
Example #8
0
MME_ERROR MME_HostRegisterTransport(const char *name)
#endif
{
	MME_ERROR res;
	EMBX_ERROR err;
	TransportInfo_t *tpInfo = 0;

#ifndef MME_LEAN_AND_MEAN
        if (manager == NULL) {
		MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "MME not initialized\n"));
                return MME_DRIVER_NOT_INITIALIZED;      /* the manager must exist */
        }

	if (name == NULL) {
		MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Name not valid\n"));
		return MME_INVALID_ARGUMENT;
	}
#endif

	EMBX_OS_MUTEX_TAKE(&manager->monitorMutex);	

#ifndef MME_LEAN_AND_MEAN
	/* prevent duplicate transport registrations */
	for (tpInfo = manager->transportList; tpInfo; tpInfo = tpInfo->next) {
		EMBX_TPINFO embxTpInfo;

		err = EMBX_GetTransportInfo(tpInfo->handle, &embxTpInfo);
		MME_Assert(EMBX_SUCCESS == err);

		if (0 == strcmp(name, embxTpInfo.name)) {
			EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex);
			MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Transport already registered\n"));
			return MME_INVALID_ARGUMENT;
		}
	}
#endif

	/* allocate space for the transport descriptor */
	res = createTransportInfo(name, &tpInfo);
	if (MME_SUCCESS == res) {
		/* update the lists with in the manager */
		tpInfo->next = manager->transportList;
		manager->transportList = tpInfo;
	}

	EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex);
       	MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "<<<< (%d)\n", res));
	return res;
}
static void receiveTransformMessage(RemoteTransformer_t *remoteTransformer, 
				   TransformerTransformMessage *message,
                                   MME_Event_t*    eventPtr,
 				   MME_Command_t** commandPtr)
{
	MME_UINT slot;
	MME_CommandStatus_t *status;

	cleanupTransformMessage(remoteTransformer, message);

	/* Find the right slot for this commandID. */
	slot = MME_CMDID_GET_COMMAND(message->command.CmdStatus.CmdId);

	/* Setup our results and update the client's MME_CommandStatus_t. */
	*eventPtr = MME_COMMAND_COMPLETED_EVT;
	*commandPtr = remoteTransformer->commandSlots[slot].command;
	status = (MME_CommandStatus_t*) &((*commandPtr)->CmdStatus);

	status->Error = message->command.CmdStatus.Error;
	status->ProcessedTime = message->command.CmdStatus.ProcessedTime;

	/* At the moment that we write the command state, a sampling client will know
	  we are finished with the command. The command has completed or failed. */
	status->State = message->command.CmdStatus.State;

	RemoteTransformer_ReleaseCommandSlot((Transformer_t *) remoteTransformer,
			&(remoteTransformer->commandSlots[slot]));

	MME_Info(MME_INFO_TRANSFORMER,
			(DEBUG_NOTIFY_STR "MME_COMMAND_COMPLETED_EVT (cmd %08x @ 0x%08x)\n", 
			 message->command.CmdStatus.CmdId, (unsigned) *commandPtr));
}
Example #10
0
static MME_ERROR RemoteTransformer_AbortCommand(Transformer_t* transformer, MME_CommandId_t commandId)
{
	RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer;
	EMBX_ERROR err;
	EMBX_VOID *buffer;
	TransformerAbortMessage *message;
	CommandSlot_t *slot;

	/* TODO: shouldn't this be asserted! */
	if (!remoteTransformer->sendPort.valid) {
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "MME port does not exist\n"));
		return MME_DRIVER_NOT_INITIALIZED;
	}

	/* confirm that the command is actually pending on the companion before we
	 * issue the abort */
	slot = &(remoteTransformer->commandSlots[MME_CMDID_GET_COMMAND(commandId)]);
	if (slot->status != MME_RUNNING || commandId != slot->command->CmdStatus.CmdId) { 
		return MME_INVALID_ARGUMENT;
	}

	/* Allocate an abort message and send it to the companion side, which disposes the buffer */
	buffer = allocBuffer(remoteTransformer, sizeof(TransformerAbortMessage));
	if (0 == buffer) {
		return MME_NOMEM;
	}

	/* initialize the message */
	message = (TransformerAbortMessage *) buffer;
	message->id = TMESSID_ABORT;
	message->messageSize = sizeof(TransformerAbortMessage);
	message->commandId = commandId;

	/* post the message */
	err = EMBX_SendMessage(remoteTransformer->sendPort.port, message, message->messageSize);
	if (err != EMBX_SUCCESS) {
		/* If sending the message did not work, there is nothing we can do. */
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "EMBX_SendMessage(TransformerAbortMessage) failed, error=%d\n", err));
		freeBuffer(remoteTransformer, buffer);
		return MME_NOMEM;
	}
	
	/* success does not indicate the command has been aborted only
	 * that the request has been sent
	 */
	return MME_SUCCESS;
}
Example #11
0
MME_ERROR MME_DeregisterTransport(const char *name)
{
	EMBX_ERROR err;
	MME_Info(MME_INFO_MANAGER, ("MME_DeregisterTransport()\n"));
	if (NULL == manager) {
		return MME_DRIVER_NOT_INITIALIZED;
	}

	if (NULL == name) {
		return MME_INVALID_ARGUMENT;
	}

	MME_Info(MME_INFO_MANAGER, ("EMBX_InvalidatePort() - handle %d\n", manager->adminPort));
	err = EMBX_InvalidatePort(manager->adminPort);
	if (err != EMBX_SUCCESS) {
		MME_Info(MME_INFO_MANAGER, ("EMBX_InvalidatePort() failed, error=%d\n", err));
		return MME_HANDLES_STILL_OPEN;
	}

	MME_Info(MME_INFO_MANAGER, ("EMBX_ClosePort() - handle %d\n", manager->adminPort));
	EMBX_ClosePort(manager->adminPort);
	if (err != EMBX_SUCCESS) {
		MME_Info(MME_INFO_MANAGER, ("EMBX_ClosePort() failed, error=%d\n", err));
		return MME_HANDLES_STILL_OPEN;
	}

	MME_Info(MME_INFO_MANAGER, ("EMBX_CloseTransport() - handle %d\n", manager->transportHandle));
	err = EMBX_CloseTransport(manager->transportHandle);
	if (err != EMBX_SUCCESS) {
		MME_Info(MME_INFO_MANAGER, ("EMBX_CloseTransport() failed, error=%d\n", err));
		return MME_HANDLES_STILL_OPEN;
	}

	return MME_SUCCESS;
}
Example #12
0
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 #13
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;
}
Example #14
0
static void receiveTransformerRegisteredMessage(TransformerRegisteredMessage* message)
{
	EMBX_PORT replyPort;
	EMBX_ERROR embxError;
	MMEReceiverFactory* factory;

	message->result = MME_SUCCESS;	/* preliminary result */

	/* Connect to the reply port. */
	embxError = EMBX_ConnectBlock(manager->transportHandle, message->portName, &replyPort);
	if (EMBX_SUCCESS != embxError) {
		/* ??? This is a bit of a problem. We cannot connect to the port that we should now send
		   the error message to. */
		MME_Info(MME_INFO_MANAGER, ("EMBX_ConnectBlock() to reply port failed, error=%d\n", embxError));
		return;
	}

	/* Need a lock on this list */
	/* Find the right receiver factory. */
	factory = manager->factoryList;
	while (factory &&
	       factory->transformerType &&
	       strcmp(factory->transformerType, message->transformerType) != 0) {
		factory = factory->next;
	}

	if (factory == NULL) {
		/* No such factory available. */
		MME_Info(MME_INFO_MANAGER, ("No receiver found for %s\n", message->transformerType));
		message->result = MME_UNKNOWN_TRANSFORMER;
	}

	/* Send the message back with the updated result field */
	embxError = EMBX_SendMessage(replyPort, message, message->messageSize);
	if (EMBX_SUCCESS != embxError) {
		MME_Info(MME_INFO_MANAGER, ("EMBX_SendMessage() to reply port failed, error=%d\n", embxError));
		return;
	}

	EMBX_ClosePort(replyPort);
}
Example #15
0
/* Peek does not dequeue the entry. */
MME_ERROR MME_MessageQueue_Peek(MMEMessageQueue * msgQ, void **message)
{
	MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Peek(0x%08x, ...)\n", (unsigned) msgQ));

	sortMessageQueue(msgQ);
	EMBX_OS_MUTEX_TAKE(&msgQ->queueLock);
	if (NULL == msgQ->sorted_front) {
		*message = NULL;
		MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Peek(..., 0) = MME_INVALID_HANDLE\n"));
		EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
		return MME_INVALID_HANDLE;
	}

	*message = msgQ->sorted_front->message;

	EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);

	MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Peek(..., 0x%08x) = MME_SUCCESS\n",
				  (unsigned) *message));
	return MME_SUCCESS;
}
Example #16
0
MME_ERROR MME_HostDeregisterTransport(const char* name)
#endif
{
	EMBX_ERROR err;
	TransportInfo_t *tpInfo, **prev;
	MME_ERROR res;

#ifndef MME_LEAN_AND_MEAN
        if (manager == NULL) {
		MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "MME not initialized\n"));
                return MME_DRIVER_NOT_INITIALIZED;      /* the manager must exist */
        }

	if (name == NULL) {
		MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Transport name NULL\n"));
		return MME_INVALID_ARGUMENT;
	}
#endif

	EMBX_OS_MUTEX_TAKE(&manager->monitorMutex);	

	MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "Looking for transport %s\n", name));
	/* search the transport list for the appropriate transport */
	for (tpInfo = *(prev = &manager->transportList); tpInfo; tpInfo = *(prev = &tpInfo->next)) {
		EMBX_TPINFO embxTpInfo;

		err = EMBX_GetTransportInfo(tpInfo->handle, &embxTpInfo);
		MME_Assert(EMBX_SUCCESS == err);

		if (0 == strcmp(name, embxTpInfo.name)) {
			break;
		}
	}

	if (!tpInfo) {
		MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Transport not found\n"));
		res = MME_INVALID_ARGUMENT;
	} else if (0 != tpInfo->referenceCount) {
		MME_Info(MME_INFO_MANAGER, (DEBUG_ERROR_STR "Handles still open\n"));
		res = MME_HANDLES_STILL_OPEN;
	} else {
		res = MME_SUCCESS;
		
		MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "Removing transport\n"));
		/* remove the transport information from the list and cleanup */
		*prev = tpInfo->next;
		destroyTransportInfo(tpInfo);
	}

	EMBX_OS_MUTEX_RELEASE(&manager->monitorMutex);
	MME_Info(MME_INFO_MANAGER, (DEBUG_NOTIFY_STR "<<<< (%d)\n", res));
	return res;
}
Example #17
0
static MME_ERROR RemoteTransformer_KillCommand(Transformer_t* transformer, MME_CommandId_t commandId)
{
	RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer;
	MME_ERROR result;
	EMBX_ERROR err;
	CommandSlot_t *slot;
	EMBX_VOID *buffer;
	TransformerTransformMessage *message;
	EMBX_PORT replyPort;

	/* TODO: shouldn't this be asserted! */
	if (!remoteTransformer->sendPort.valid) {
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "MME port does not exist\n"));
		return MME_DRIVER_NOT_INITIALIZED;
	}

	/* confirm that the command is actually pending on the companion before we
	 * issue the abort */
	slot = &(remoteTransformer->commandSlots[MME_CMDID_GET_COMMAND(commandId)]);
	if (slot->status != MME_RUNNING || commandId != slot->command->CmdStatus.CmdId) { 
		return MME_INVALID_ARGUMENT;
	}

	/* mark the command as complete */
	slot->command->CmdStatus.Error = MME_COMMAND_ABORTED;
	slot->command->CmdStatus.State = MME_COMMAND_FAILED;

	/* fake up a completed transform request */
	result = createTransformMessage(remoteTransformer, slot->command, &buffer);
	if (result != MME_SUCCESS) {
		return result;
	}

	/* connect to our own reply port */
	err = EMBX_Connect(remoteTransformer->super.info->handle, remoteTransformer->replyPort.name, &replyPort);
	if (EMBX_SUCCESS != err) {
		return MME_EMBX_ERROR;
	}

	/* send the message */
	message = (TransformerTransformMessage *) buffer;
	err = EMBX_SendMessage(replyPort, message, message->messageSize);
	if (EMBX_SUCCESS != err) {
		return MME_EMBX_ERROR;
	}

	EMBX_ClosePort(replyPort);
	
	return MME_SUCCESS;
}
Example #18
0
MME_ERROR MME_MessageQueue_Enqueue(MMEMessageQueue * msgQ, void *message, unsigned int priority)
{
	MMEMessageQueueEntry *entry;

	MME_Info(MME_INFO_QUEUE, (">>>MME_MessageQueue_Enqueue(0x%08x, 0x%08x)\n", 
	                          (unsigned) msgQ, (unsigned) message));

	EMBX_OS_MUTEX_TAKE(&msgQ->queueLock);

	/* fetch a free linkage structure from the free list */
	entry = msgQ->free_list;
	if (NULL == entry) {
		EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
		MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Enqueue = MME_NOMEM\n"));
		return MME_NOMEM;
	}
	msgQ->free_list = entry->next;

	/* fill in the linkage structure */
	entry->next = NULL;
	entry->priority = priority;
	entry->message = message;

	/* add it to the unsorted FIFO queue. we use a FIFO queue in order to
	 * exploit the FIFO optimizations in SortMMEMessageQueue.
	 */
	if (NULL == msgQ->unsorted_front) {
		msgQ->unsorted_front = entry;
	} else {
		msgQ->unsorted_back->next = entry;
	}
	msgQ->unsorted_back = entry;

	EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
	MME_Info(MME_INFO_QUEUE, ("<<<MME_MessageQueue_Enqueue = MME_SUCCESS\n"));
	return MME_SUCCESS;
}
Example #19
0
static void executionLoopTask(void *params)
{
	int id = (int) params;

	for (EMBX_OS_EVENT_WAIT(&(manager->commandEvents[id]));
	     manager->loopTasksRunning[id];
	     EMBX_OS_EVENT_WAIT(&(manager->commandEvents[id]))) {

		MMEReceiver *receiver;
		MMEReceiver *lowestReceiver;
		MME_Time_t dueTime, lowestDueTime;
		int found = 0;

		EMBX_OS_MUTEX_TAKE(&(manager->receiverListMutexes[id]));

		EMBX_OS_MUTEX_TAKE(&(manager->abortMutex));

		/* Find the receiver with the lowest dueTime. */
		lowestReceiver = manager->receiverLists[id];
		lowestDueTime = MME_MaxTime_c;
		for (receiver = lowestReceiver; receiver; receiver = receiver->next) {
			if (MME_SUCCESS == MME_Receiver_NextDueTime(receiver, &dueTime)) {
				if (dueTime < lowestDueTime) {
					found = 1;
					lowestReceiver = receiver;
					lowestDueTime = dueTime;
				}
			}
		}

		/* TODO: Note that if we support the bufferQueue, we need to serve it here */
		if (found) {
			EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id]));
			/* Execute this receiver's command. */
			/* Mutex will be released once the message is dequeued - otherwise
			   an abort requiest may come take the message off the queue
                           but leave the receiver in the executing state 
                        */
			MME_Receiver_ProcessCommand(lowestReceiver);
		} else {
			/* Nothing is pending. We could waste some time. */
			MME_Info(MME_INFO_MANAGER, ("Execution loop error: Semaphore signalled but no command found!\n"));
			EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id]));

			EMBX_OS_MUTEX_RELEASE(&(manager->abortMutex));
		}
	}
}
Example #20
0
static void receiveIsAliveMessage(TransformerIsAliveMessage * message)
{
	EMBX_PORT replyPort = EMBX_INVALID_HANDLE_VALUE;
	EMBX_ERROR err;

	MMEReceiver **prev = NULL, *receiver = NULL;
	int id;

	/* Search each receiver list for a matching handle */
	for (id=0; id<MME_NUM_EXECUTION_LOOPS; id++) {
		if (manager->loopTasksRunning[id]) {
			EMBX_OS_MUTEX_TAKE(&(manager->receiverListMutexes[id]));

			/* iterate of the receiver list keeping track of the linkage pointer */
			for (prev = &(manager->receiverLists[id]), receiver = *prev;
			     NULL != receiver;
			     prev = &(receiver->next), receiver = *prev) {
				if (receiver == (void *) (message->mmeHandle)) {
					/* even Java lets you use labelled jumps to do this ... */
					goto double_break;
				}
			}

			EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id]));
		} else {
			MME_Assert(0 == manager->loopTasks[id]);
			MME_Assert(0 == manager->receiverLists[id]);
		}

	}
    double_break:

        /* WARNING: if receiver is non-NULL we still own receiverListMutexes[id] */

	if (NULL != receiver) {
		replyPort = MME_Receiver_GetReplyPort(receiver);
		
		EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id]));

		/* send the message back to the host */
		err = EMBX_SendMessage(replyPort, message, message->messageSize);
		MME_Assert(EMBX_SUCCESS == err); /* cannot recover */
	} else {
		MME_Info(MME_INFO_MANAGER, ("receiveIsAliveMessage could not find receiver, no reply port available!\n"));
	}
}
Example #21
0
static void receiverThread(void* ctx)
{
	RemoteTransformer_t* remoteTransformer = (RemoteTransformer_t*) ctx;
	MME_ERROR res;

	MME_Assert(remoteTransformer);
	MME_Assert(remoteTransformer->replyPort.valid);

	while (1) {
		MME_Event_t evt;
		MME_Command_t *cmd;

		/* wait for a transformer message (callback) to be received */		
		res = RemoteTransformer_WaitForMessage(
				(Transformer_t *) remoteTransformer, &evt, &cmd);
		
		if (MME_SUCCESS != res) {
			break;
		}
		
		MME_Assert(cmd);
		
		/* perform the callback if this has been requested */
		if (MME_COMMAND_COMPLETED_EVT != evt ||
		    MME_COMMAND_END_RETURN_NOTIFY == cmd->CmdEnd) {
		    	/* it would really make more sense to assert Callback and make it illegal to send
		    	 * commands with MME_COMMAND_END_RETURN_NOTIFY fail if Callback is NULL. However this
		    	 * would mean changing the behavior of the API.
		    	 */
		    	if (remoteTransformer->super.initParams.Callback) {
				remoteTransformer->super.initParams.Callback(evt, cmd,
						remoteTransformer->super.initParams.CallbackUserData);
		    	}
		}
	}
	
	MME_Info(MME_INFO_TRANSFORMER, ("receiverThread: terminating due (res = %d)\n", res));
}
Example #22
0
MME_ERROR MME_RegisterTransport(const char *transportName)
{
	const char portName[] = "MMECompanionAdmin#0";
	EMBX_ERROR err;

	if (NULL == transportName) {
		return MME_INVALID_ARGUMENT;
	}

	if (NULL == manager) {
		return MME_DRIVER_NOT_INITIALIZED;
	}

	MME_Info(MME_INFO_MANAGER, ("EMBX_OpenTransport(), name <%s>...\n", transportName));
	/* Open the transport. */
	err = EMBX_OpenTransport(transportName, &manager->transportHandle);
	MME_Info(MME_INFO_MANAGER, ("EMBX_OpenTransport() - handle %d\n", manager->transportHandle));

	if (EMBX_SUCCESS != err) {
		MME_Info(MME_INFO_MANAGER, ("Failed to open EMBX_OpenTransport() - EMBX err %d\n", err));
		return MME_INVALID_ARGUMENT;
	}

	/* Create the administration port. */
	memcpy(manager->adminPortName, portName, sizeof(portName));

	do {
		MME_Info(MME_INFO_MANAGER, ("   EMBX_CreatePort(), port name <%s>...\n", 
					   manager->adminPortName));
		err = EMBX_CreatePort(manager->transportHandle, 
				      manager->adminPortName, &manager->adminPort);
	} while (EMBX_ALREADY_BIND == err && 
	         manager->adminPortName[sizeof(portName)-2]++ < '9');
	if (err != EMBX_SUCCESS) {
		MME_Info(MME_INFO_MANAGER, ("EMBX_CreatePort(%s) failed - error %d\n", manager->adminPortName, err));
		EMBX_CloseTransport(manager->transportHandle);
		manager->transportHandle = 0;
		return MME_INVALID_ARGUMENT;
	}
	MME_Info(MME_INFO_MANAGER, ("EMBX_CreatePort(%s) handle 0x%08x\n", manager->adminPortName, manager->adminPort));

	manager->managerRunning = 1;
	return MME_SUCCESS;
}
Example #23
0
static void receiveStavationMessage(RemoteTransformer_t *remoteTransformer, 
				    TransformerStarvationMessage *message,
                                    MME_Event_t*    eventPtr,
				    MME_Command_t** commandPtr)
{
	MME_UINT slot;
	MME_CommandStatus_t *status;

	/* Find the right slot for this commandID. */
	slot = MME_CMDID_GET_COMMAND(message->status.CmdId);

	*eventPtr = (MME_Event_t) message->event;

	/* Copy the status from the message to the client's MME_CommandStatus_t. */
	*commandPtr = remoteTransformer->commandSlots[slot].command;
	status = (MME_CommandStatus_t*) &((*commandPtr)->CmdStatus);
	status->Error = message->status.Error;
	status->ProcessedTime = message->status.ProcessedTime;
	status->State = message->status.State;

	MME_Info(MME_INFO_TRANSFORMER,
			(DEBUG_NOTIFY_STR "Stavation event  %d (cmd %08x @ 0x%08x)\n",
			*eventPtr, message->status.CmdId, (unsigned) *commandPtr));
}
Example #24
0
/* Run the manager. This call only returns when everything is shut down. */
MME_ERROR MME_Run(void)
{
	MME_ERROR result;
	EMBX_ERROR err;
	EMBX_RECEIVE_EVENT event;
	MME_UINT messageID;
	int running = 1;
	int oldTaskPriority;

	if (manager == NULL) {
		return MME_DRIVER_NOT_INITIALIZED;
	}

	/* Note that the manager should be running at high priority (e.g. 200 of 255). */
	oldTaskPriority = task_priority_set(NULL, MANAGER_TASK_PRIORITY);

	while (running && manager->managerRunning) {
		/* Wait for a host request. */
		MME_Info(MME_INFO_MANAGER, ("Waiting for host request... on port 0x%08x\n", manager->adminPort));
		err = EMBX_ReceiveBlock(manager->adminPort, &event);
		if (err == EMBX_SUCCESS) {
			if (event.type == EMBX_REC_MESSAGE && event.size >= sizeof(MME_UINT) && event.data != NULL) {
				/* The message ID decides. */
				messageID = *((MME_UINT*) event.data);
				switch (messageID) {
				case TMESSID_INIT:
					/* It is a TransformerInitMessage. */
					receiveInitMessage((TransformerInitMessage *) event.data);
					break;

				case TMESSID_TERMINATE:
					/* It is a TransformerTerminateMessage to terminate a single transformer. */
					receiveTerminateMessage((TransformerTerminateMessage *) event.data);
					break;

				case TMESSID_CAPABILITY: 
					receiveCapabilityMessage((TransformerCapabilityMessage *) event.data);
					break;
					
				case TMESSID_TERMINATE_MME: {
					/* It is a TransformerTerminateMessage to terminate all of the MME! */
					TransformerTerminateMMEMessage *msg = (TransformerTerminateMMEMessage*) event.data;
					result = MME_Term();
					msg->result = result;
					running = 0;
					/* ??? Problem: We need to tell someone if termination worked, but there's no port to talk to,
					   and EMBX has been shut down as well. */
					break;
				}
				case TMESSID_TRANSFORMER_REGISTERED:
					receiveTransformerRegisteredMessage((TransformerRegisteredMessage*) event.data);
					break;
				default:
					MME_Info(MME_INFO_MANAGER, ("Received unknown message ID %d\n", messageID));
					break;
				}
			} else {
				/* Strange message arrived. */
				MME_Info(MME_INFO_MANAGER, ("Strange message: type %d, size %d, data %0x\n", event.type, event.size, event.data));
			}
		} else {
			if (err == EMBX_INVALID_PORT || err == EMBX_PORT_INVALIDATED) {
				MME_Info(MME_INFO_MANAGER, ("RunMMEManager:EMBX_ReceiveBlock() returned due to invalid(ated) port, error=%d\n", err));
				result = MME_Term();
				if (result != MME_SUCCESS) {
					MME_Info(MME_INFO_MANAGER, ("TerminateMMEManager() failed, result=%d\n", result));
				}
				running = 0;
			} else {
				MME_Info(MME_INFO_MANAGER, ("RunMMEManager: EMBX_ReceiveBlock() failed, error=%d\n", err));
			}
		}
	}

	task_priority_set(NULL, oldTaskPriority);

	return MME_SUCCESS;
}
Example #25
0
static MME_ERROR createTransformMessage(RemoteTransformer_t* remoteTransformer, 
						    MME_Command_t * cmd, EMBX_VOID ** buffer)
{
	union {
		TransformerTransformMessage *message;
		MME_DataBuffer_t *buffer;
		MME_ScatterPage_t *page;
		EMBX_HANDLE *hdl;
		char *ch;
		int i;
		void *p;
		void **pp;
	} p, q, size;

	MME_ERROR res = MME_NOMEM;
	EMBX_ERROR err;
	unsigned int i, j;

	/* all argument checking should have been performed further up the food chain
	 * so all the argument checking in this function can asserted
	 */
	MME_Assert(remoteTransformer);
	MME_Assert(cmd);
	MME_Assert(buffer);

        MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "Command 0x%08x\n", (int)cmd));

	/* determine the size of message we will need */
	size.i = 0;
	size.message += 1;
	size.buffer += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;
	size.pp += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;
	for (i=0; i < (cmd->NumberInputBuffers + cmd->NumberOutputBuffers); i++) {
		size.page += cmd->DataBuffers_p[i]->NumberOfScatterPages;
		size.hdl  += cmd->DataBuffers_p[i]->NumberOfScatterPages;
	}
	size.i += cmd->CmdStatus.AdditionalInfoSize;
	size.i += cmd->ParamSize;

	/* allocate the message */
	p.p = allocBuffer(remoteTransformer, size.i);
	if (0 == p.p) {
		return MME_NOMEM;
	}
	*buffer = p.p;

	/* populate the fundamental message structure */
	p.message = (TransformerTransformMessage *) (*buffer);
	p.message->id = TMESSID_TRANSFORM;
	p.message->messageSize = size.i;
	p.message->hostCommand = cmd;
	p.message->receiverInstance = (MME_UINT)remoteTransformer->mmeHandle;  /* used for sanity check on companion */
	p.message->command = *cmd;
	p.message->command.DataBuffers_p = NULL;	/* invalid local pointers */
	p.message->transformer = remoteTransformer;
	p.message->numInputBuffers = cmd->NumberInputBuffers; 
	p.message->numOutputBuffers = cmd->NumberOutputBuffers;
	p.message += 1;

	/* copy the data buffers into our message */
	for (i=0; i < (cmd->NumberInputBuffers + cmd->NumberOutputBuffers); i++) {
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "Buffer %d at 0x%08x\n", 
                         i, (int)(cmd->DataBuffers_p[i]) ));
		*p.buffer++ = *cmd->DataBuffers_p[i];
	}

	/* skip the pre-allocated data buffers structure */
	p.pp += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;

	/* copy the scatter pages into our message */
	for (i=0; i < (cmd->NumberInputBuffers + cmd->NumberOutputBuffers); i++) {
		MME_DataBuffer_t *buf = cmd->DataBuffers_p[i];
		MME_ScatterPage_t *pages;
		EMBX_HANDLE *hdls;
		
		pages = p.page;
		p.page += buf->NumberOfScatterPages;
		hdls = p.hdl;
		p.hdl += buf->NumberOfScatterPages;

		for (j=0; j < buf->NumberOfScatterPages; j++) {
			MME_ScatterPage_t *page = &buf->ScatterPages_p[j];

			MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "Page %d at 0x%08x\n", j, (int)page ));

			/* copy the original page into the data buffer */
			pages[j] = *page;

			/* serialize the object (try direct pointer warping before falling back to registering
			 * the object)
			 */
			err = EMBX_Offset(remoteTransformer->super.info->handle,
			                  page->Page_p, (EMBX_INT *) hdls + j);

			MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR 
                                 "Page 0x%08x, Pointer warp %s, Handle 0x%08x buf-id %d, page-id %d\n", 
                                 (int) page->Page_p, 
				 (EMBX_INCOHERENT_MEMORY==err) ? "PURGE" :
				                                 (EMBX_SUCCESS==err) ? "YES" : "NO",
	                         (int)hdls[j], i, j));

			if (EMBX_INCOHERENT_MEMORY == err) {
				if (0 == (page->FlagsIn & MME_DATA_CACHE_COHERENT)) {
					EMBX_OS_PurgeCache(page->Page_p, page->Size);
				}
			} else if (EMBX_SUCCESS != err) {
				err = EMBX_RegisterObject(remoteTransformer->super.info->handle, 
							  page->Page_p, page->Size, hdls + j);
				if (EMBX_SUCCESS != err) {
					res = MME_EMBX_ERROR;
					MME_Info(1, ("Failed to reg obj err %d, i %d, j %d\n", 
                                                     err, i, j));
					goto error_recovery;
				}
                        }

			/* update the copy (or view) of the object at our destination port */
			if (0xf0000000 & hdls[j]) {

				err = EMBX_UpdateObject(remoteTransformer->sendPort.port, 
							hdls[j], 0, page->Size);
				if (EMBX_SUCCESS != err) {
					MME_Info(1, ("Failed to update obj err %d\n", err ));
					res = MME_EMBX_ERROR;
					goto error_recovery;
				}
			}
		}
	}
	
	/* TODO: Need to use a macro to swap all args to little endian if on a big endian machine */

	if (cmd->CmdStatus.AdditionalInfoSize > 0) {
		memcpy(p.p, cmd->CmdStatus.AdditionalInfo_p, 
		       cmd->CmdStatus.AdditionalInfoSize);
		p.ch += cmd->CmdStatus.AdditionalInfoSize;
	}

	if (cmd->ParamSize > 0) {
		memcpy(p.p, cmd->Param_p, cmd->ParamSize);
	}

	return MME_SUCCESS;

    error_recovery:
	/* to recover from the error we walk through the currently marshalled data knowing
	 * that p (in any of its forms) points to the first uninitialized byte in the 
	 * buffer.
	 */
	
	/* get to the scatter page and handles section of the buffer */
	q.p = *buffer;
	q.message += 1;
	q.buffer += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;
	q.pp += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;

	/* now iterate though the buffer deregistering the objects */
	for (i=0; i < (cmd->NumberInputBuffers + cmd->NumberOutputBuffers) && q.p < p.p; i++) {
		q.page += cmd->DataBuffers_p[i]->NumberOfScatterPages;
		for (j=0; j < cmd->DataBuffers_p[i]->NumberOfScatterPages && q.p < p.p; j++) {
			if (0xf0000000 & q.hdl[j]) {
				err = EMBX_DeregisterObject(
						remoteTransformer->super.info->handle, q.hdl[j]);
				MME_Assert(EMBX_SUCCESS == err); /* no error recovery possible */
			}
		}
		q.hdl += cmd->DataBuffers_p[i]->NumberOfScatterPages;
	}

	/* unallocate the buffer */

	freeBuffer(remoteTransformer, buffer);

	return res;
}
Example #26
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;
}
Example #27
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;
}
Example #28
0
static MME_ERROR RemoteTransformer_SendCommand(Transformer_t* transformer, MME_Command_t * commandInfo, CommandSlot_t** slot)
{
	RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer;
	EMBX_VOID *buffer;
	EMBX_ERROR err;
	MME_CommandStatus_t *status;
	TransformerTransformMessage *message;
	MME_ERROR result;
	int i;
	MME_CommandCode_t cmdCode = commandInfo->CmdCode;
	int newCommandIndex;

	if (!remoteTransformer->sendPort.valid) {
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "MME port does not exist\n"));
		return MME_INVALID_ARGUMENT;
	}

	status = (MME_CommandStatus_t*) &(commandInfo->CmdStatus);

	MME_Assert(cmdCode == MME_TRANSFORM || cmdCode == MME_SEND_BUFFERS || 
	           cmdCode == MME_SET_GLOBAL_TRANSFORM_PARAMS);

	/* Acquire lock on the transformer's command slots */
	EMBX_OS_MUTEX_TAKE(&remoteTransformer->commandSlotLock);

	if (remoteTransformer->numCommandSlots >= remoteTransformer->maxCommandSlots) {
		/* no free slot */
		EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock);
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "SendCommand: maxCommandSlots overflow\n"));
		return MME_NOMEM;
	}

	/* Find a free command slot so we can memorize parameters */
	for (i = 0; 
	     i < remoteTransformer->maxCommandSlots && 
	         remoteTransformer->commandSlots[remoteTransformer->commandIndex].status 
				!= MME_COMMAND_COMPLETED_EVT; 
	     i++) {

		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "RemoteTransformer: SendCommand: CommandIndex %d is already used\n", remoteTransformer->commandIndex));

		remoteTransformer->commandIndex++;
		if (remoteTransformer->commandIndex >= remoteTransformer->maxCommandSlots) {
			remoteTransformer->commandIndex = 0;
		}
	}

	if (i >= remoteTransformer->maxCommandSlots) {
		EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock);
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "SendCommand error: No free command slot found!\n"));
		return MME_NOMEM;
	}
	newCommandIndex = remoteTransformer->commandIndex;

	/* Generate a unique command ID per transformer */
	status->CmdId = MME_CMDID_PACK(
			(remoteTransformer->super.handle)-MME_TRANSFORMER_HANDLE_PREFIX,
		        newCommandIndex, &(remoteTransformer->commandIDCounter));

	MME_Info(MME_INFO_TRANSFORMER, (DEBUG_NOTIFY_STR "RemoteTransformer: SendCommand: code=%d ID=%d slot=%d\n", 
	   cmdCode, status->CmdId, newCommandIndex));

	/* In order to avoid sending buffers, but then being unable to allocate the transform message,
	   we create and fill in the transform message first
	*/
	result = createTransformMessage(remoteTransformer, commandInfo, &buffer);
	if (result != MME_SUCCESS) {
		EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock);
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "CreateTransformMsg() failed, result=%d\n", result));
		return MME_NOMEM;
	}
	/* Setting the command state to FAILED allows us to identify incomplete SendCommand()s
	   at our receiver task.
	*/
	status->State = MME_COMMAND_FAILED;	

	/* New command slot entry. Initially, assume that the transform message can't be sent */
	status->Error = MME_SUCCESS;
	remoteTransformer->commandSlots[newCommandIndex].endType   = commandInfo->CmdEnd;
	/* In the moment that the status is not zero, the receiver task regards it as valid */
	remoteTransformer->commandSlots[newCommandIndex].command = commandInfo;
	remoteTransformer->commandSlots[newCommandIndex].waitor = NULL;
	remoteTransformer->commandSlots[newCommandIndex].status = MME_RUNNING;

	remoteTransformer->numCommandSlots++;

	EMBX_OS_MUTEX_RELEASE(&remoteTransformer->commandSlotLock);

	/* TODO: Should we move the state here or on the companion once the command is
	 * scheduled - I think the latter 
	 */
	status->State = MME_COMMAND_EXECUTING;

	message = (TransformerTransformMessage *) buffer;

	/* Send the message */
	err = EMBX_SendMessage(remoteTransformer->sendPort.port, message, message->messageSize);
	if (err != EMBX_SUCCESS) {
		/* The message could not be sent. Mark the command slot as incomplete */
		MME_Info(MME_INFO_TRANSFORMER, (DEBUG_ERROR_STR "EMBX_SendMessage() failed, error=%d\n", err));
		/* Mark incomplete command */
		status->State = MME_COMMAND_FAILED;	
		freeBuffer(remoteTransformer, buffer);
		return MME_NOMEM;
	} else {
		/* Lost ownership */
		buffer = NULL;
	}

	*slot = &(remoteTransformer->commandSlots[newCommandIndex]);

	return MME_SUCCESS;
}
Example #29
0
static MME_ERROR RemoteTransformer_Init(Transformer_t* transformer, 
                                        const char* name,
					MME_TransformerInitParams_t * params, 
                                        MME_TransformerHandle_t handle, 
                                        EMBX_BOOL createThread)
{
	RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer;
	EMBX_ERROR err;
	EMBX_RECEIVE_EVENT event;
	TransformerInitMessage *message = NULL;
	char receiverThreadName[EMBX_MAX_PORT_NAME+1];
	int messageSize,n;
	MME_ERROR result, res;

	result = MME_NOMEM;

	remoteTransformer->super.handle = handle;

	/* TODO: We should take a copy of our (transformer specific) parameters. These might
	 * be deallocated once the transformer is initialized.
	 */
	remoteTransformer->super.initParams = *params;

	MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: initialising '%s'\n", name));

	/* Create the reply port. We use the unique handle to create a unique reply port name.*/
	n = sprintf(remoteTransformer->replyPort.name, "MMEReply_0x%x", handle);
	MME_Assert(n < EMBX_MAX_PORT_NAME);
	err = EMBX_CreatePort(remoteTransformer->super.info->handle, 
			remoteTransformer->replyPort.name, &remoteTransformer->replyPort.port);
	if (EMBX_SUCCESS != err) {
		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot create port '%s'\n",
		                                remoteTransformer->replyPort.name));
		goto embx_error_recovery;
	}
	remoteTransformer->replyPort.valid = 1;

	MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Created port '%s', port 0x%08x\n",
	                                remoteTransformer->replyPort.name,
					(unsigned) remoteTransformer->replyPort.port));
	
	/* Create the init message */
	res = createInitMessage(remoteTransformer, name, params, (EMBX_VOID **) &message);
	if (MME_SUCCESS != res) {
		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot create initialisation message\n"));
		goto error_recovery;
	}

	/* Remember size for check of reply message */
	messageSize = message->messageSize;	

	/* Send the message */
	err = EMBX_SendMessage(remoteTransformer->adminPort, message, messageSize);
	if (err != EMBX_SUCCESS) {
		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot set initialisation message\n"));
		goto embx_error_recovery;
	}

	/* Record ownership tranfer (see error_recovery) */
	message = NULL;

	MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Waiting for initialisation reply\n"));

	/* Wait for an answer from the companion */
	err = EMBX_ReceiveBlock(remoteTransformer->replyPort.port, &event);
	if (EMBX_SUCCESS != err) {
		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Error while waiting for initialisation reply\n"));
		goto embx_error_recovery;
	}

	/* Check if the message is as expected */
	message = (TransformerInitMessage *) event.data;
	
	MME_Assert(EMBX_REC_MESSAGE == event.type);
	MME_Assert(event.size >= messageSize);
	MME_Assert(message && message->id == TMESSID_INIT);
	
	if (MME_SUCCESS != message->result) {
		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Error initialising remote transformer\n"));
		res = message->result;
		goto error_recovery;
	}

	/* The MME successfully created its transformer */
	strncpy(remoteTransformer->sendPort.name, message->portName, EMBX_MAX_PORT_NAME);
	remoteTransformer->sendPort.name[EMBX_MAX_PORT_NAME] = '\0';
	remoteTransformer->mmeHandle = message->mmeHandle;

	MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Connecting to transformer port '%s'\n",
	                                remoteTransformer->sendPort.name));

	/* Connect to the MME port */
	err = EMBX_ConnectBlock(remoteTransformer->super.info->handle, 
			        remoteTransformer->sendPort.name,
				&remoteTransformer->sendPort.port);
	if (EMBX_SUCCESS != err) {
		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot connect to port '%s'\n",
		                                remoteTransformer->sendPort.name));
		goto embx_error_recovery;
	}
	remoteTransformer->sendPort.valid = 1;

	MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Connected to port '%s', port 0x%08x\n",
					remoteTransformer->sendPort.name,
					(unsigned) remoteTransformer->sendPort.port));

	if (createThread) {
		/* Create our receiver task for the reply port */
		sprintf(receiverThreadName, "HostRec%x", handle);

		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Creating receiver thread '%s'\n",
						receiverThreadName));

		/* TODO: think about whether we want all the receiver threads to have the same priority */
		remoteTransformer->receiverThread = EMBX_OS_ThreadCreate(receiverThread,
			(void *) remoteTransformer, RECEIVER_TASK_PRIORITY, receiverThreadName);
		if (EMBX_INVALID_THREAD == remoteTransformer->receiverThread) {
			MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Cannot create receiver thread '%s'\n",
			                                receiverThreadName));
			res = MME_NOMEM;
			goto error_recovery;
		}

		MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: Created receiver thread '%s', thread 0x%08x\n",
						receiverThreadName, (unsigned) remoteTransformer->receiverThread));
        }

	/* Cleanup and exit */
	cleanupInitMessage(remoteTransformer, message);
	MME_Info(MME_INFO_TRANSFORMER, ("RemoteTransformer_Init: SUCCESS\n"));
	return MME_SUCCESS;

    embx_error_recovery:

    	/* As normal error recovery but map the EMBX error code to a MME error code first */
    	res = (EMBX_NOMEM == err ? MME_NOMEM : MME_EMBX_ERROR);
    	
    error_recovery:
    
   	if (remoteTransformer->mmeHandle) {
   		MME_Assert(message);
   		message->id = TMESSID_TERMINATE;
   		err = EMBX_SendMessage(remoteTransformer->adminPort, message, message->messageSize);
   		if (EMBX_SUCCESS == err) {
   			/* TODO: is blocking really a good idea during error recovery? */
   			err = EMBX_ReceiveBlock(remoteTransformer->replyPort.port, &event);
   			message = (EMBX_SUCCESS == err ? event.data : NULL);
   		}
   		
   		remoteTransformer->mmeHandle = 0;
   	}
   	
   	if (remoteTransformer->sendPort.valid) {
   		EMBX_ClosePort(remoteTransformer->sendPort.port);
   		remoteTransformer->sendPort.valid = 0;
   	}
   	
    	if (remoteTransformer->replyPort.valid) {
    		EMBX_ClosePort(remoteTransformer->replyPort.port);
    		remoteTransformer->replyPort.valid = 0;
    	}
    	
    	if (message) {
    		cleanupInitMessage(remoteTransformer, message);
    	}
    
    	return res;
}
Example #30
0
static void receiveInitMessage(TransformerInitMessage * message)
{
	EMBX_ERROR err;
	EMBX_PORT replyPort;
	MMEReceiverFactory *factory;
	MMEReceiver *receiver;
	MME_ERROR res;

	message->result = MME_NOMEM;	/* preliminary result */

	/* Connect to the reply port. */
	err = EMBX_ConnectBlock(manager->transportHandle, message->portName, &replyPort);
	if (err != EMBX_SUCCESS) {
		/* ??? This is a bit of a problem. We cannot connect to the port that we should now send
		   the error message to. */
		MME_Info(MME_INFO_MANAGER, ("EMBX_ConnectBlock() to reply port failed, error=%d\n", err));
		return;
	}

	/* Need a lock on this list */
	/* Find the right receiver factory. */
	factory = manager->factoryList;
	while (factory != NULL && strcmp(factory->transformerType, message->transformerType) != 0) {
		factory = factory->next;
	}

	if (factory == NULL) {
		/* No such factory available. */
		MME_Info(MME_INFO_MANAGER, ("No receiver factory found\n"));
		res = MME_UNKNOWN_TRANSFORMER;
	} else {
		/* Create a receiver object. This will result in the constructors being called as well. */
		res = MME_Receiver_Create(factory, &receiver);
		if (MME_SUCCESS == res) {
			int id = MME_PRIORITY_TO_ID(message->priority);

			res = createExecutionLoop(manager, id);
			assert(MME_SUCCESS == res); /* TODO: proper error handling */

			/* Initialize the receiver. */
			/* This call will also fail if an existing transformer does not support multi-instantiation. */
			res = MME_Receiver_Init(receiver, manager, manager->transportHandle, message, replyPort,
						         &(manager->commandEvents[id]));
			if (res == MME_SUCCESS) {
				/* Add the new receiver to the list. */
				EMBX_OS_MUTEX_TAKE(&(manager->receiverListMutexes[id]));

				receiver->next = manager->receiverLists[id];
				manager->receiverLists[id] = receiver;

				EMBX_OS_MUTEX_RELEASE(&(manager->receiverListMutexes[id]));

				/* We are successfully done. */
				message->result = res;
				EMBX_SendMessage(replyPort, message, message->messageSize);
				return;
			}

			/* Could not initialize receiver. Clean up and return error. */
			MME_Receiver_Destroy(receiver);
		}
	}

	/* Send the message back to the host with an error. */
	message->result = res;
	EMBX_SendMessage(replyPort, message, message->messageSize);
	EMBX_ClosePort(replyPort);
}