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);
	
	
}
Beispiel #2
0
MME_ERROR MME_LookupTable_Insert(MMELookupTable_t *tbl, void *data, int *id)
{
	int i;

	MME_Assert(tbl);
	MME_Assert(data);

	i = tbl->insertAt;
	do {
		MME_Assert(i <= tbl->maxEntries);

		if (NULL == tbl->lookup[i]) {
			tbl->lookup[i] = data;
			*id = i;

			i++;
			tbl->insertAt = (i == tbl->maxEntries)?0:i;
			return MME_SUCCESS;
		}
		
		if (++i == tbl->maxEntries) {
			i = 0;
		}
	} while (i != tbl->insertAt);

	return MME_NOMEM;
}
Beispiel #3
0
static void receiveCapabilityMessage(TransformerCapabilityMessage *message)
{
	EMBX_ERROR err;
	EMBX_PORT replyPort;
	MMEReceiverFactory *factory;

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

	/* connect to the reply port */
	if (EMBX_SUCCESS != EMBX_Connect(manager->transportHandle, message->portName, &replyPort)) {
		MME_Assert(0); /* cannot recover */
		return;
	}

	/* TODO: no lock on this list */
	for (factory = manager->factoryList; factory; factory = factory->next) {
		if (0 == strcmp(factory->transformerType, message->transformerType)) {
			break;
		}
	}

	message->capability.TransformerInfo_p = (void *) 
		(message->capability.TransformerInfoSize ? message + 1 : 0);
	message->result = (factory ? factory->getTransformerCapabilityFunc(&message->capability)
	                           : MME_UNKNOWN_TRANSFORMER);

	/* post the reply back again */
	err = EMBX_SendMessage(replyPort, message, message->messageSize);
	MME_Assert(EMBX_SUCCESS == err); /* cannot recover */

	err = EMBX_ClosePort(replyPort);
	MME_Assert(EMBX_SUCCESS == err); /* cannot recover */
}
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;
}
/* This code forms a small cache of pre-allocated blocks that can be allocated by
 * the host without using (comparitively slow) spinlocks and semaphores. additionally
 * block coalescing does not take place which saves a number of uncached reads
 */
static void *allocBuffer(RemoteTransformer_t *remoteTransformer, MME_UINT sz)
{
	EMBX_ERROR err;
	EMBX_VOID *ptr;

	if (sz <= 4096) {
		EMBX_OS_INTERRUPT_LOCK();		

		if (remoteTransformer->bufferCache) {
			ptr = remoteTransformer->bufferCache;
			remoteTransformer->bufferCache = *remoteTransformer->bufferCache;

			EMBX_OS_INTERRUPT_UNLOCK();

			/* this assert technically has side effects (alters sz) so have a
			 * care if altering this function
			 */
			MME_Assert(EMBX_SUCCESS == EMBX_GetBufferSize(ptr, &sz));
			MME_Assert(4096 == sz);
			return ptr;
		}

		sz = 4096;
		EMBX_OS_INTERRUPT_UNLOCK();
	}
	err = EMBX_Alloc(remoteTransformer->super.info->handle, sz, &ptr);

	return (EMBX_SUCCESS == err ? ptr : 0);
}
Beispiel #6
0
static MME_ERROR createTransformerInstance(const char *name, Transformer_t **tfp)
{
	MME_ERROR res;
	MME_ERROR res2 = MME_UNKNOWN_TRANSFORMER;
	RegisteredLocalTransformer_t *rlt;
	Transformer_t *tf;
	TransportInfo_t *tpInfo;

	MME_Assert(manager);
	MME_Assert(name);

#ifndef MULTIHOST
	/* first check whether this is a locally registered transformer (because this is much
	 * faster than querying the companions)
	 */
	res = findTransformerOnHost(name, &rlt);
	if (MME_SUCCESS == res) {
		tf = MME_LocalTransformer_Create(manager, rlt);
		if (tf) {
			*tfp = tf;
			return MME_SUCCESS;
		} else {
			return MME_NOMEM;
		}
	}
#endif /* !MULTIHOST */

	/* now start looking for the named transformer in each of the registered transports */
	for (tpInfo = manager->transportList; tpInfo; tpInfo = tpInfo->next) {
		EMBX_PORT adminPort;

		res = findTransformerWithinTransport(tpInfo, name, &adminPort);
		if (MME_SUCCESS == res) {
			/* RemoteTransformer_Create will update tpInfo's reference count and
			 * keep a reference to it. adminPort is transfered outright to the
			 * transformer
			 */
			tf = MME_RemoteTransformer_Create(manager, tpInfo, adminPort);
			if (tf) {
				*tfp = tf;
				return MME_SUCCESS;
			} else {
				return MME_NOMEM;
			}
		}
		/* TIMEOUT SUPPORT: Remember res if we see a timeout from any of the transports */
		else if (res == MME_TRANSFORMER_NOT_RESPONDING)
			res2 = res;
	}

	MME_Assert(res2 == MME_UNKNOWN_TRANSFORMER || res2 == MME_TRANSFORMER_NOT_RESPONDING);

	/* TIMEOUT SUPPORT: Returns MME_TRANSFORMER_NOT_RESPONDING if we failed
	 * to communicate with any of the transformers. MME_UNKNOWN_TRANSFORMER otherwise
	 */
	return res2;
}
static MME_ERROR cleanupTransformMessage(RemoteTransformer_t* remoteTransformer, 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;

	MME_Command_t *cmd;
	EMBX_ERROR err;
	unsigned int i, j;

	p.p = buffer;
	MME_Assert(p.message->numInputBuffers == p.message->hostCommand->NumberInputBuffers);
	MME_Assert(p.message->numOutputBuffers == p.message->hostCommand->NumberOutputBuffers);

	cmd = p.message->hostCommand;

	p.message += 1;
	p.buffer += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;
	p.pp += cmd->NumberInputBuffers + cmd->NumberOutputBuffers;

	for (i = 0; i < (cmd->NumberInputBuffers + cmd->NumberOutputBuffers); i++) {
		MME_DataBuffer_t *buf = cmd->DataBuffers_p[i];
		MME_ScatterPage_t *pages = p.page;

		p.page += buf->NumberOfScatterPages;

		for (j=0; j < buf->NumberOfScatterPages; j++) {
			if (i >= cmd->NumberInputBuffers) {
				buf->ScatterPages_p[j].BytesUsed = pages[j].BytesUsed;
				buf->ScatterPages_p[j].FlagsOut = pages[j].FlagsOut;
			}

			if (0xf0000000 & p.hdl[j]) {
				err = EMBX_DeregisterObject(
						remoteTransformer->super.info->handle, p.hdl[j]);
				MME_Assert(EMBX_SUCCESS == err); /* no error recovery possible */
			}
		}
		
		p.hdl += buf->NumberOfScatterPages;
	}

	/* Deal with status transformer paramters */
	if (cmd->CmdStatus.AdditionalInfoSize > 0) {
		memcpy(cmd->CmdStatus.AdditionalInfo_p, p.p, cmd->CmdStatus.AdditionalInfoSize);
	}

	return MME_SUCCESS;
}
Beispiel #8
0
MME_ERROR MME_LookupTable_Find(MMELookupTable_t *tbl, int id, void **data)
{
	MME_Assert(tbl);
	MME_Assert(data);

	if (id < 0 || id >= tbl->maxEntries) {
		return MME_INVALID_HANDLE;
	}

	*data = tbl->lookup[id];
	return (*data ? MME_SUCCESS : MME_INVALID_HANDLE);
}
Beispiel #9
0
static void deregisterTransformerInstance(MME_TransformerHandle_t handle)
{
	MME_ERROR res;

	MME_Assert(manager);

	/* clear the prefix */
	handle -= MME_TRANSFORMER_HANDLE_PREFIX;

	res = MME_LookupTable_Remove(manager->transformerInstances, handle);

	MME_Assert(MME_SUCCESS == res);
}
Beispiel #10
0
static MME_ERROR createExecutionLoop(MMEManager_t *manager, int id)
{
	const struct { MME_UINT priority; const char *name; } lookup[MME_NUM_EXECUTION_LOOPS] = {
		{ MME_TUNEABLE_EXECUTION_LOOP_LOWEST_PRIORITY,       "ExecutionLoopLowest" },
		{ MME_TUNEABLE_EXECUTION_LOOP_BELOW_NORMAL_PRIORITY, "ExecutionLoopBelowNormal" },
		{ MME_TUNEABLE_EXECUTION_LOOP_NORMAL_PRIORITY,       "ExecutionLoopNormal" },
		{ MME_TUNEABLE_EXECUTION_LOOP_ABOVE_NORMAL_PRIORITY, "ExecutionLoopAboveNormal" },
		{ MME_TUNEABLE_EXECUTION_LOOP_HIGHEST_PRIORITY,      "ExecutionLoopHighest" },
	};

	MME_Assert(manager);
	MME_Assert(id < MME_NUM_EXECUTION_LOOPS);

	if (manager->loopTasksRunning[id]) {
		return MME_SUCCESS;
	}

	MME_Assert(0 == manager->loopTasks[id]);
	MME_Assert(0 == manager->receiverLists[id]);
	
	/* this code can only be called from the manager thread and therefore needs
	 * no thread protection.
	 */
	if (!EMBX_OS_MUTEX_INIT(&(manager->receiverListMutexes[id]))) {
		return MME_NOMEM;
	}

	if (!EMBX_OS_EVENT_INIT(&(manager->commandEvents[id]))) {
		goto cleanup_mutex;
	}

	/* spawn the worker thread */
	manager->loopTasks[id] = EMBX_OS_ThreadCreate((void(*)()) executionLoopTask, 
		    (void *) id, MME_GetTuneable(lookup[id].priority), lookup[id].name);
	if (0 == manager->loopTasks[id]) {
		goto cleanup_event;
	}

	/* mark the task as running */
	manager->loopTasksRunning[id] = 1;

	return MME_SUCCESS;

   cleanup_event:
	EMBX_OS_EVENT_DESTROY(&(manager->commandEvents[id]));
	
   cleanup_mutex:
	EMBX_OS_MUTEX_DESTROY(&(manager->receiverListMutexes[id]));

	return MME_NOMEM;
}
Beispiel #11
0
static void sortMessageQueue(MMEMessageQueue *msgQ)
{
	MMEMessageQueueEntry *entry;

	/* take the unsorted list and merge it with the sorted list.
	 * this code is optimized for FIFO operations and the time
	 * comparisions allow time to wrap. they do not directly 
	 * compare values but subtract with overflow wrap and compare
	 * against 0. note ANSI C only guarantees overflow wrap for 
	 * unsigned values (which is why the priority member is unsigned).
	 */

	EMBX_OS_MUTEX_TAKE(&msgQ->queueLock);
	entry = msgQ->unsorted_front;
	while (entry) {
		msgQ->unsorted_front = entry->next;

		if (NULL == msgQ->sorted_front) {
			/* empty list short circuit */
			entry->next = NULL;
			msgQ->sorted_front = entry;
			msgQ->sorted_back = entry;
		} else if (0 >= (int) (msgQ->sorted_back->priority - entry->priority)) {
			/* FIFO ordered queue short circuit */
			entry->next = NULL;
			msgQ->sorted_back->next = entry;
			msgQ->sorted_back = entry;
		} else {
			/* search the queue until we find a entry with a (strictly) more
			 * distant due date
			 */
			MMEMessageQueueEntry **prev, *cur;

			/* search the queue until we find our insertion point. we know
			 * we cannot run off the end otherwise we would have taken one
			 * of the short circuits above.
			 */
			for (prev = &(msgQ->sorted_front), cur = *prev;
			     MME_Assert(cur), 0 >= (int) (cur->priority - entry->priority);
			     prev = &(cur->next), cur = *prev) {} 

			entry->next = cur;
			*prev = entry;
			MME_Assert(*prev != msgQ->sorted_back);
		}

		entry = msgQ->unsorted_front;
	}
	EMBX_OS_MUTEX_RELEASE(&msgQ->queueLock);
}
Beispiel #12
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;
}
Beispiel #13
0
MME_ERROR MME_WaitForMessage(Transformer_t*  transformer, 
                             MME_Event_t*    eventPtr,
 	                     MME_Command_t** commandPtr)
{
	MME_Assert(transformer->vtable->waitForMessage);

	/* this is not an external visible API so invalid arguments are an
	 * internal error.
	 */
	MME_Assert(transformer); 
	MME_Assert(eventPtr);
	MME_Assert(commandPtr);

	return transformer->vtable->waitForMessage(
			transformer, eventPtr, commandPtr);
}
Beispiel #14
0
static void cleanupTerminateMMEMessage(TransportInfo_t *tpInfo, 
				       TransformerTerminateMMEMessage* buffer)
{
	EMBX_ERROR err;
	err = EMBX_Free(buffer);
	MME_Assert(EMBX_SUCCESS == err);
}
Beispiel #15
0
static void cleanupRegisteredMessage(TransportInfo_t *tpInfo, TransformerRegisteredMessage *msg)
{
	EMBX_ERROR err;

	err = EMBX_Free(msg);
	MME_Assert(EMBX_SUCCESS == err);
}
Beispiel #16
0
static MME_ERROR findTransformerInstance(MME_TransformerHandle_t handle,
                                         Transformer_t** transformer)
{
	void *p;
	MME_ERROR res;

	MME_Assert(manager);
	MME_Assert(transformer);
	handle -= MME_TRANSFORMER_HANDLE_PREFIX;

	res = MME_LookupTable_Find(manager->transformerInstances, handle, &p);
	if (MME_SUCCESS == res) {
		*transformer = (Transformer_t *) p;
	}

	return res;
}
Beispiel #17
0
static MME_ERROR registerTransformerInstance(Transformer_t* transformer, 
                                          MME_TransformerHandle_t * handle)
{
	MME_ERROR res;
	int id;

	MME_Assert(manager);
	MME_Assert(transformer);
	MME_Assert(handle);

	res = MME_LookupTable_Insert(manager->transformerInstances, transformer, &id);
	if (MME_SUCCESS == res) {
		*handle = MME_TRANSFORMER_HANDLE_PREFIX + id;
	}

	return res;
}
Beispiel #18
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"));
	}
}
Beispiel #19
0
MME_ERROR MME_LookupTable_Remove(MMELookupTable_t *tbl, int id)
{
	MME_Assert(tbl);
	MME_Assert(id < tbl->maxEntries);

	if (id < 0 || id >= tbl->maxEntries) {
		return MME_INVALID_HANDLE;
	}

	tbl->lookup[id] = NULL;

	if (!tbl->temporallyUnique) {
		/* improves locality of reference at bit */
		tbl->insertAt = id;
	}

	return MME_SUCCESS;
}
Beispiel #20
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;
}
Beispiel #21
0
MMELookupTable_t * MME_LookupTable_Create(int max, int temporal)
{
	MMELookupTable_t *tbl;
        int size = sizeof(MMELookupTable_t) + (max-1) * sizeof(void *);

	MME_Assert(max > 0);
	MME_Assert(0 == temporal || 1 == temporal);

	/* allocation */
        tbl = EMBX_OS_MemAlloc(size);
        if (!tbl) {
                return NULL;
        }
        memset(tbl, 0, size);

	tbl->maxEntries = max;
	tbl->temporallyUnique = temporal;

	return tbl;
}
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;		
}	
Beispiel #23
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;
}
/* The list management here is extremely vulnerable to duplicate frees. this
 * will make the buffer list cyclic resulting either in the buffer release
 * code in RemoteTransformer_Term() looping forever or (worse) memory
 * being allocated twice.
 */
static void freeBuffer(RemoteTransformer_t *remoteTransformer, EMBX_VOID *ptr)
{
	EMBX_UINT sz;
	EMBX_ERROR err;

	err = EMBX_GetBufferSize(ptr, &sz);
	MME_Assert(EMBX_SUCCESS == err);

	if (sz == 4096) {
		EMBX_VOID **p = ptr;

		MME_Assert(ptr != remoteTransformer->bufferCache);
		EMBX_OS_INTERRUPT_LOCK();
		*p = remoteTransformer->bufferCache;
		remoteTransformer->bufferCache = p;
		EMBX_OS_INTERRUPT_UNLOCK();
	} else {
		EMBX_ERROR err = EMBX_Free(ptr);
		MME_Assert(EMBX_SUCCESS == err);
	}
}
Beispiel #25
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);
}
Beispiel #26
0
/* Construct a one-way message requesting complete termination of our partner CPU. */
static MME_ERROR createTerminateMMEMessage(TransportInfo_t *tpInfo,
					   TransformerTerminateMMEMessage** buffer) {
	TransformerTerminateMMEMessage *message;
	EMBX_ERROR err;

	MME_Assert(manager);
	MME_Assert(tpInfo);
	MME_Assert(buffer);
	
	err = EMBX_Alloc(tpInfo->handle, sizeof(*message), (EMBX_VOID **) &message);
	if (EMBX_SUCCESS == err) {
		message->id = TMESSID_TERMINATE_MME;
		message->messageSize = sizeof(*message);
		message->result = MME_SUCCESS;
		*buffer = message;
	}
	
	/* map the EMBX error to an MME one */
	return EMBX_SUCCESS == err ? MME_SUCCESS :
	       EMBX_NOMEM == err   ? MME_NOMEM :
	                             MME_EMBX_ERROR;
}
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));
}
Beispiel #28
0
int MME_LookupTable_IsEmpty(MMELookupTable_t *tbl)
{
	int i;

	MME_Assert(tbl);

	for (i=0; i<tbl->maxEntries; i++) {
		if (tbl->lookup[i]) {
			return 0;
		}
	}

	return 1;
}
Beispiel #29
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 MME_ERROR createInitMessage(RemoteTransformer_t* remoteTransformer, const char* name,
		MME_TransformerInitParams_t* params, EMBX_VOID** buffer)
{
	TransformerInitMessage *message;
	unsigned paramsSize;
	int messageSize;

	MME_Assert(params->StructSize == sizeof(MME_TransformerInitParams_t));

	messageSize = sizeof(TransformerInitMessage);
	paramsSize  = params->TransformerInitParamsSize;
	messageSize += paramsSize;

	message = allocBuffer(remoteTransformer, messageSize);
	if (0 == message ) {
		return MME_NOMEM;
	}

	message->id = TMESSID_INIT;
	message->messageSize = messageSize;
	message->priority = params->Priority;
	message->result = MME_SUCCESS;

	MME_Assert(strlen(name) < MME_MAX_TRANSFORMER_NAME);
	strcpy(message->transformerType, name);

	MME_Assert(strlen(remoteTransformer->replyPort.name) < EMBX_MAX_PORT_NAME);
	strcpy(message->portName, remoteTransformer->replyPort.name);

	/* Copy TransformerInitParams data */
	/* TODO: these should be byte swapped on a big endian machine */
	memcpy((void *) (message + 1), params->TransformerInitParams_p, paramsSize);

	*buffer = message;
	return MME_SUCCESS;
}