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)); } } }
/* * Notification routine to inform us that a local port has been * closed. We need to invalidate all our remote port */ void EMBXSHM_portClosedNotification (EMBXSHM_Transport_t *tpshm) { EMBX_Info(EMBX_INFO_REMOTEPORT, (">>>EMBXSHM_portClosedNotification\n")); EMBX_Assert (tpshm); /* * Wait for notification of a local port closing, * then look for it and service it */ while (1) { EMBX_BOOL signalPending; EMBX_Info(EMBX_INFO_REMOTEPORT, (" waiting for port closed notification\n")); signalPending = EMBX_OS_EVENT_WAIT (&tpshm->closedPortEvent); EMBX_Info(EMBX_INFO_REMOTEPORT, (" received port closed notification\n")); /* * If we've been told to die, then do so */ if (signalPending || tpshm->closedPortDieFlag) { EMBX_Info(EMBX_INFO_REMOTEPORT, ("<<<EMBXSHM_portClosedNotification\n")); return; } /* Close the port */ EMBXSHM_portClose(tpshm); } }
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); }
static MME_ERROR RemoteTransformer_TermOrKill(Transformer_t* transformer, int doKill) { RemoteTransformer_t *remoteTransformer = (RemoteTransformer_t *) transformer; EMBX_ERROR err; EMBX_VOID *buffer; TransformerTerminateMessage *message; MME_ERROR result, res; result = MME_NOMEM; if (!remoteTransformer->sendPort.valid) { DP("MME port does not exist\n"); return MME_INVALID_ARGUMENT; } /* No command must be pending on the companion side */ if (remoteTransformer->numCommandSlots > 0) { DP("RemoteTransformer::Terminate() failed, commands pending\n"); return MME_COMMAND_STILL_EXECUTING; } res = createTerminateMessage(remoteTransformer, 0, &buffer); if (res != MME_SUCCESS) { DP("CreateTerminateMsg() failed, error=%d\n", res); return res; } /* Send the message */ message = (TransformerTerminateMessage *) buffer; DP("Sending %s message @$%08x...\n", message, (doKill ? "kill" : "terminate")); if (doKill) { EMBX_PORT replyPort; /* connect to our own reply port */ err = EMBX_Connect(remoteTransformer->super.info->handle, remoteTransformer->replyPort.name, &replyPort); if (EMBX_SUCCESS != err) { DP("RemoteTransformer_Term(): failed to connect to self\n"); cleanupTerminateMessage(remoteTransformer, message); return MME_EMBX_ERROR; } err = EMBX_SendMessage(replyPort, message, message->messageSize); if (EMBX_SUCCESS != err) { DP("RemoteTransformer_Term(): failed to send message to self\n"); cleanupTerminateMessage(remoteTransformer, message); return MME_EMBX_ERROR; } EMBX_ClosePort(replyPort); } else { err = EMBX_SendMessage(remoteTransformer->adminPort, message, message->messageSize); if (EMBX_SUCCESS != err) { DP("RemoteTransformer_Term(): failed to send message to coprocessor\n"); cleanupTerminateMessage(remoteTransformer, message); return MME_EMBX_ERROR; } } /* lost ownership */ message = NULL; /* Wait for ReceiverThread to terminate itself after receiving the reply message */ DP("Waiting for ReceiverThread to terminate itself...\n"); DP("terminateWasReplied 0x%08x\n", remoteTransformer->terminateWasReplied); EMBX_OS_EVENT_WAIT(&remoteTransformer->terminateWasReplied); if (remoteTransformer->terminationResult != MME_SUCCESS) { DP("Failed to terminate receiver thread properly\n"); return MME_INTERNAL_ERROR; } err = EMBX_OS_ThreadDelete(remoteTransformer->receiverThread); if (err != EMBX_SUCCESS) { DP("EMBX_OS_ThreadDelete() failed, error=d\n", err); } remoteTransformer->receiverThread = NULL; /* Close the MME port */ DP("Close mmePort...\n"); err = EMBX_ClosePort(remoteTransformer->sendPort.port); if (err != EMBX_SUCCESS) { DP("EMBX_ClosePort(mmePort) failed, error=d\n", err); } /* Close the reply port */ DP("Invalidate replyPort...\n"); err = EMBX_InvalidatePort(remoteTransformer->replyPort.port); if (err != EMBX_SUCCESS) { DP("EMBX_InvalidatePort(replyPort) failed, error=%d\n", err); } DP("Close replyPort...\n"); err = EMBX_ClosePort(remoteTransformer->replyPort.port); if (err != EMBX_SUCCESS) { DP("EMBX_ClosePort(replyPort) failed, error=%d\n", err); } remoteTransformer->replyPort.valid = EMBX_FALSE; return MME_SUCCESS; }
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; }