/* * ======== serverTask ======== */ Void serverTask(UArg arg0, UArg arg1) { MessageQ_Handle serverMessageQ; MessageQ_QueueId replyQueue; MessageQ_Msg msg; UInt16 msgId; Int status; serverMessageQ = MessageQ_create(SERVERNAME, NULL); /* Loop forever processing requests */ System_printf("Server is ready to set processing requests\n"); while (TRUE) { /* Wait for a request. */ status = MessageQ_get(serverMessageQ, &msg, MessageQ_FOREVER); if (status < 0) { System_abort("Stopping test\n"); } /* Get the id and increment it to send back as validation */ msgId = MessageQ_getMsgId(msg); msgId += NUMCLIENTS; MessageQ_setMsgId(msg, msgId); /* Use the embedded reply destination */ replyQueue = MessageQ_getReplyQueue(msg); /* Send the response back */ status = MessageQ_put(replyQueue, msg); if (status < 0) { System_abort("MessageQ_put was not successful\n"); } } }
/* * ======== loopbackFxn======== * Receive and return messages. * Run at priority lower than tsk1Fxn above. * Inputs: * - arg0: number of the thread, appended to MessageQ host and slave names. */ Void loopbackFxn(UArg arg0, UArg arg1) { MessageQ_Msg getMsg; MessageQ_Handle messageQ; MessageQ_QueueId remoteQueueId; Int status; UInt16 msgId = 0; Char localQueueName[64]; Char hostQueueName[64]; System_printf("Thread loopbackFxn: %d\n", arg0); System_sprintf(localQueueName, "%s_%d", SLAVE_MESSAGEQNAME, arg0); System_sprintf(hostQueueName, "%s_%d", HOST_MESSAGEQNAME, arg0); /* Create a message queue. */ messageQ = MessageQ_create(localQueueName, NULL); if (messageQ == NULL) { System_abort("MessageQ_create failed\n"); } System_printf("loopbackFxn: created MessageQ: %s; QueueID: 0x%x\n", localQueueName, MessageQ_getQueueId(messageQ)); System_printf("Start the main loop: %d\n", arg0); while (msgId < NUMLOOPS) { /* Get a message */ status = MessageQ_get(messageQ, &getMsg, MessageQ_FOREVER); if (status != MessageQ_S_SUCCESS) { System_abort("This should not happen since timeout is forever\n"); } remoteQueueId = MessageQ_getReplyQueue(getMsg); #ifndef BENCHMARK System_printf("%d: Received message #%d from core %d\n", arg0, MessageQ_getMsgId(getMsg), MessageQ_getProcId(remoteQueueId)); #endif /* test id of message received */ if (MessageQ_getMsgId(getMsg) != msgId) { System_abort("The id received is incorrect!\n"); } #ifndef BENCHMARK /* Send it back */ System_printf("%d: Sending message Id #%d to core %d\n", arg0, msgId, MessageQ_getProcId(remoteQueueId)); #endif status = MessageQ_put(remoteQueueId, getMsg); if (status != MessageQ_S_SUCCESS) { System_abort("MessageQ_put had a failure/error\n"); } msgId++; } MessageQ_delete(&messageQ); numTests += NUMLOOPS; System_printf("Test thread %d complete!\n", arg0); }
/* * ======== Server_delete ======== */ Int Server_delete() { Int status; GateMPApp_Msg * msg; MessageQ_QueueId queId; Log_print0(Diags_ENTRY, "--> Server_delete:"); /* wait for inbound message */ status = MessageQ_get(Module.slaveQue, (MessageQ_Msg *)&msg, MessageQ_FOREVER); if (status < 0) { goto leave; } Log_print0(Diags_ENTRY, "--> Server_delete: got msg"); if (msg->cmd != GATEMPAPP_CMD_SHUTDOWN) { status = GATEMPAPP_E_UNEXPECTEDMSG; goto leave; } /* send message back to say that GateMP has been cleaned up */ queId = MessageQ_getReplyQueue(msg); /* type-cast not needed */ msg->cmd = GATEMPAPP_CMD_SHUTDOWN_ACK; MessageQ_put(queId, (MessageQ_Msg)msg); /* delete the video message queue */ status = MessageQ_delete(&Module.slaveQue); if (status < 0) { Log_print0(Diags_ENTRY, "Server_delete: MessageQ_delete failed"); goto leave; } Log_print0(Diags_ENTRY, "Server_delete: MessageQ deleted"); /* delete slave GateMP */ status = GateMP_delete(&Module.slaveGateMPHandle); if (status < 0) { Log_print0(Diags_ENTRY, "Server_delete: GateMP_delete failed"); goto leave; } Log_print0(Diags_ENTRY, "Server_delete: slave GateMP deleted"); leave: if (status < 0) { Log_error1("Server_delete: error=0x%x", (IArg)status); } /* disable log events */ Log_print1(Diags_EXIT, "<-- Server_delete: %d", (IArg)status); Diags_setMask(MODULE_NAME"-EXF"); return(status); }
/****************************************************************************** * TASK FUNCTION *****************************************************************************/ void task_fxn(UArg arg0, UArg arg1){ Int status; Int coreCount; Int nextCore; MessageQ_Msg msg; MessageQ_QueueId msgQueueIds[MAX_NUM_CORES]; /* Register this heap with the Message Q */ MessageQ_registerHeap((IHeap_Handle)SharedRegion_getHeap(0), HEAP_ID); /* * In order to send messages to other cores, we must know that core's Queue * ID. So, we'll create an array on each core that associates the Queue ID * with the core number, and then we'll open each queue. Again, we spin * here until the queue is open, sleeping for one tick after every attempt. */ for (coreCount = 0; coreCount < MAX_NUM_CORES; coreCount++){ System_sprintf(remoteQueueName, "%s", MultiProc_getName(coreCount)); do { status = MessageQ_open(remoteQueueName, &msgQueueIds[coreCount]); if (status < 0){ Task_sleep(1); } }while (status < 0); } /* * At this point, our application is ready to begin sending messages using * Message Queue. The core with the number TOKEN_START_CORE has the * responsibility of sending the first message. So, we'll handle that in * this block. */ if (selfId == TOKEN_START_CORE){ /* * Allocate the initial message. If the message is not properly * allocated, we must abort */ /* * TODO: IPC #1 - Allocate Memory for Token Message * Add core below that ALLOCATES the memory for the token message. * We've already declared the variable msg to hold the pointer to * this message. The code to check if the pointer is NULL is * already included. */ msg = MessageQ_alloc(HEAP_ID, sizeof(myMsg)); if (msg == NULL){ System_abort("MessageQ_alloc failed\n"); } /* * Now randomly select the next processor to send the. This function * simply selects a random core number and ensures it's not the same as * the current core number. */ nextCore = findNextCore(selfId); /* * Set the Initial Token Count in the message, and specify that the * message type is MSG_TOKEN */ ((myMsg*)msg)->tokenCount = 1; ((myMsg*)msg)->messageType = MSG_TOKEN; /* * We can also set a reply queue so that the core can acknowledge this * message without having to know which core it came from. */ MessageQ_setReplyQueue(messageQ, msg); /* * Now we actually send the message to the next core that we've chosen. */ /* TODO: IPC #2 - Pass the token to the destination core * Add the code to send the message to the destination core. This is * done by putting the message in the destination core's queue. Don't * forget that the ID of the destination core's queue is stored at * element "nextCore" in the array msgQueueIds, and is NOT the same * as the core number. */ status = MessageQ_put(msgQueueIds[nextCore], msg); } while (TRUE){ msgType messageType; MessageQ_Msg ack; MessageQ_QueueId ackQueueId; Int currentTokenCount; /* TODO: IPC #3 - Get a Message from the local queue. * Take the message from the local queue and store it in the variable * message. The function call return value should be stored in the * variable status. Hint: The parameters passed to this function * specify a time out size. We want to configure this call to * never time out, and block eternally until a message is received. */ status = MessageQ_get(messageQ, &msg, MessageQ_FOREVER); if (status < 0){ System_abort("This should not occur since the timeout is forever\n"); } /* * Read the Message Type from the received message, along with the current * token count. */ messageType = ((myMsg*)msg)->messageType; currentTokenCount = ((myMsg*)msg)->tokenCount; /* * Now, check what type of message it is and take action. Here are the * actions to be taken. * * MSG_TOKEN * - Acknowledge that token is received to sending core. * - If token count is less than MAX_MESSAGES * - Increment the token count. * - Forward the token on to the next random core * - If token count is equal to MAX Messages * - Free the Token message. * - Send a Done Message to all other cores. * - Break out of the infinite loop. * * MSG_ACK * - Free the Ack message * MSG_DONE * - Free the Done Message * - Break Out of infinite loop */ switch (messageType){ case MSG_TOKEN: System_printf("Token Received - Count = %d\n", currentTokenCount); /* * TODO: IPC #4 - Get the Reply Queue for the token * Store the ID of the reply queue in the variable ackQueueId. * This function allows us to not have to figure out which core * sent this message. This is the analogous function to the * MessageQ_setReplyQueue() function that was set before the * message was sent. This data is stored in the MessageQ_MsgHeader * element that's included with the message */ ackQueueId = MessageQ_getReplyQueue(msg); /* * TODO: IPC #5 - Allocate the acknowledge message * Allocate the acknowledge message and store the pointer to it * in the variable ack. */ ack = MessageQ_alloc(HEAP_ID, sizeof(myMsg)); // Set the Message Type of the new Message to MSG_ACK if (ack==NULL){ System_abort("MessageQ Alloc Failed\n"); } // Set the Message Type of the new Message to MSG_ACK ((myMsg*)ack)->messageType = MSG_ACK; /* * TODO: IPC #6 - Send the Acknowledge message * Don't forget that we've already stored the reply queue ID in * ackQueueId above. */ status = MessageQ_put(ackQueueId, ack); /* * Now handle the actions required by the status of the message. First * we must check to see if we're at the Token Passing limit. So we'll * compare the current Token count with MAX_MESSAGES. */ /* * If the current token count is the max, then we must free the current * message and then allocate new DONE messages to be sent to the other * cores. */ if (currentTokenCount == NUM_MESSAGES){ /* * TODO: IPC #7 - Free the memory used by the token message * Don't forget that the pointer to this memory is in the * variable msg. */ MessageQ_free(msg); /* * Now allocate and send ALL cores a DONE message. We don't need to * worry about special handling of the current core. It will just * send itself a DONE message and handle it just as the other cores * do */ /* * TODO: IPC #8 - Note that this core will send itself a message. * There's nothing to be added here. just note that this * routine is blindly sending done messages to all of the cores * and not taking into account it's own core number. So, this * core will send one of these messages to itself. */ for (coreCount =0; coreCount < MAX_NUM_CORES; coreCount++){ msg = MessageQ_alloc(HEAP_ID, sizeof(myMsg)); if (msg == NULL){ System_abort("MessageQ Alloc Failed\n"); } // Set the Message Type to MSG_DONE ((myMsg*)msg)->messageType = MSG_DONE; // Now send it to the selected core status = MessageQ_put(msgQueueIds[coreCount], msg); } break; } /* * If we're not at the last message, then we must increment the * tokenCount and pass the message on to a random core. Don't * forget to set the reply queue so we can get an acknowledge. */ nextCore = findNextCore(selfId); ((myMsg*)msg)->tokenCount = currentTokenCount + 1; /* * TODO: IPC #9- Set the reply queue for the token message. * We need to be sure to set the reply queue each time. * Otherwise, the wrong core will receive the acknowledge. */ MessageQ_setReplyQueue(messageQ, msg); // Put the message on the proper queue status = MessageQ_put(msgQueueIds[nextCore], msg); break; case MSG_ACK: System_printf("Ack Received\n"); /* * All we need to do in this case is free the Ack message */ MessageQ_free(msg); break; case MSG_DONE: System_printf("Done Received\n"); /* * If we receive the Done message we just need to free the message, and * then exit SYS/BIOS because the application is complete. */ MessageQ_free(msg); BIOS_exit(0); break; default: System_printf("Invalid Message Type Received\n"); return; } } }
/* * ======== Server_exec ======== */ Int Server_exec() { Int status; GateMPApp_Msg * msg; MessageQ_QueueId queId; UInt32 physAddr; volatile UInt32 * intPtr = 0; Int num = 0; Int prevNum = 0; UInt i = 0; IArg gateKey = 0; Log_print0(Diags_ENTRY | Diags_INFO, "--> Server_exec:"); /* wait for inbound message */ status = MessageQ_get(Module.slaveQue, (MessageQ_Msg *)&msg, MessageQ_FOREVER); if (status < 0) { goto leave; } if (msg->cmd != GATEMPAPP_CMD_SPTR_ADDR) { status = GATEMPAPP_E_UNEXPECTEDMSG; goto leave; } /* Get physical address of shared memory */ physAddr = msg->payload; /* translate the physical address to slave virtual addr */ if (Resource_physToVirt(physAddr, (UInt32 *)&intPtr)) { Log_error1("Server_exec: Failed to translate phys addr %p to virt addr", physAddr); goto leave; } /* send message back */ queId = MessageQ_getReplyQueue(msg); /* type-cast not needed */ msg->cmd = GATEMPAPP_CMD_SPTR_ADDR_ACK; MessageQ_put(queId, (MessageQ_Msg)msg); Log_print0(Diags_INFO,"Server_exec: Modifying shared variable " "value"); /* open host-created GateMP */ do { status = GateMP_open(GATEMP_HOST_NAME, &Module.hostGateMPHandle); } while (status == GateMP_E_NOTFOUND); if (status < 0) { Log_error0("Server_exec: Failed to open host-created GateMP"); status = GATEMPAPP_E_FAILURE; goto leave; } Log_print0(Diags_INFO,"Server_exec: Opened GateMP successfully"); Log_print0(Diags_INFO,"Server_exec: Using host-created gate"); for (i = 0;i < LOOP_ITR; i++) { /* modify the shared variable as long as no one else is currently * accessing it */ /* enter GateMP */ gateKey = GateMP_enter(Module.hostGateMPHandle); /* read shared variable value */ prevNum = *intPtr; /* randomly modify the shared variable */ if ( rand() % 2) { *intPtr -= 1; } else { *intPtr += 1; } /* read shared variable value again */ num = *intPtr; if ((prevNum != num + 1) && (prevNum != num - 1)) { Log_print0(Diags_INFO, "Server_exec: unexpected variable value." \ "Test failed."); Log_print2(Diags_INFO, "Server_exec: Previous shared variable " "value %d, current value=%d", prevNum, num); status = GATEMPAPP_E_FAILURE; goto leave; } /* leave Gate */ GateMP_leave(Module.hostGateMPHandle, gateKey); } /* wait for sync message before we switch gates */ status = MessageQ_get(Module.slaveQue, (MessageQ_Msg *)&msg, MessageQ_FOREVER); if (status < 0) { goto leave; } if (msg->cmd != GATEMPAPP_CMD_SYNC) { status = GATEMPAPP_E_UNEXPECTEDMSG; goto leave; } queId = MessageQ_getReplyQueue(msg); MessageQ_put(queId, (MessageQ_Msg)msg); Log_print0(Diags_INFO,"Server_exec: Using slave-created gate"); for (i = 0;i < LOOP_ITR; i++) { /* modify the shared variable as long as no one else is currently * accessing it */ /* enter GateMP */ gateKey = GateMP_enter(Module.slaveGateMPHandle); /* read shared variable value */ prevNum = *intPtr; /* randomly modify the shared variable */ if ( rand() % 2) { *intPtr -= 1; } else { *intPtr += 1; } /* read shared variable value again */ num = *intPtr; if ((prevNum != num - 1) && (prevNum != num + 1)) { Log_print0(Diags_INFO, "Server_exec: unexpected variable value." \ "Test failed."); Log_print2(Diags_INFO, "Server_exec: Previous " "value=%d, current value=%d", prevNum, num); status = GATEMPAPP_E_FAILURE; goto leave; } /* leave Gate */ GateMP_leave(Module.slaveGateMPHandle, gateKey); } leave: /* close host GateMP */ if (Module.hostGateMPHandle) { GateMP_close(&Module.hostGateMPHandle); } Log_print0(Diags_ENTRY, "Server_exec: host GateMP closed"); Log_print1(Diags_EXIT, "<-- Server_exec: %d", (IArg)status); return(status); }
Void *System_ipcMsgQTaskMain(Void *arg) { UInt32 prmSize; SystemIpcMsgQ_Msg *pMsgCommon; Void *pPrm; Int32 status; while(1) { status = MessageQ_get(gSystem_ipcObj.selfMsgQ, (MessageQ_Msg*)&pMsgCommon, OSA_TIMEOUT_FOREVER); if(status==MessageQ_E_UNBLOCKED) break; if(status!=MessageQ_S_SUCCESS) { printf(" %u: MSGQ: MsgQ get failed !!!\n", OSA_getCurTimeInMsec() ); continue; } #if 0 printf(" %u: MSGQ: Received command [0x%04x] (prmSize = %d) for [%s][%02d] (waitAck=%d)\n", OSA_getCurTimeInMsec(), pMsgCommon->cmd, pMsgCommon->prmSize, MultiProc_getName(SYSTEM_GET_PROC_ID(pMsgCommon->linkId)), SYSTEM_GET_LINK_ID(pMsgCommon->linkId), pMsgCommon->waitAck ); #endif prmSize = pMsgCommon->prmSize; pPrm = SYSTEM_IPC_MSGQ_MSG_PAYLOAD_PTR(pMsgCommon); if(pMsgCommon->cmd==SYSTEM_CMD_GET_INFO) { UTILS_assert(prmSize == sizeof(System_LinkInfo)); pMsgCommon->status = System_linkGetInfo_local(pMsgCommon->linkId, pPrm); } else { pMsgCommon->status = System_linkControl_local( pMsgCommon->linkId, pMsgCommon->cmd, pPrm, prmSize, pMsgCommon->waitAck ); } if(pMsgCommon->waitAck) { MessageQ_QueueId replyMsgQ; replyMsgQ = MessageQ_getReplyQueue(pMsgCommon); status = MessageQ_put(replyMsgQ, (MessageQ_Msg)pMsgCommon); if(status!=MessageQ_S_SUCCESS) { printf(" %u: MSGQ: MsgQ Ack put failed !!!\n", OSA_getCurTimeInMsec() ); MessageQ_free((MessageQ_Msg)pMsgCommon); } } else { MessageQ_free((MessageQ_Msg)pMsgCommon); } } return NULL; }
void slave_main(void) { process_message_t * p_msg = 0; MessageQ_Handle h_receive_queue = 0; MessageQ_QueueId reply_queue_id = 0; HeapBufMP_Handle heapHandle; Int status; char receive_queue_name[16]; GET_SLAVE_QUEUE_NAME(receive_queue_name, DNUM); /* Open the heap created by the other processor. Loop until opened. */ do { status = HeapBufMP_open(IMAGE_PROCESSING_HEAP_NAME, &heapHandle); if (status < 0) { Task_sleep(1); } } while (status < 0); /* Register this heap with MessageQ */ MessageQ_registerHeap((IHeap_Handle)heapHandle, IMAGE_PROCESSING_HEAPID); /* Create the local message queue */ h_receive_queue = MessageQ_create(receive_queue_name, NULL); if (h_receive_queue == NULL) { logout("MessageQ_create failed\n" ); goto close_n_exit; } for (;;) { if (MessageQ_get(h_receive_queue, (MessageQ_Msg *)&p_msg, MessageQ_FOREVER) < 0) { logout("%s: This should not happen since timeout is forever\n", receive_queue_name); goto close_n_exit; } reply_queue_id = MessageQ_getReplyQueue(p_msg); if (reply_queue_id == MessageQ_INVALIDMESSAGEQ) { logout("receive_queue_name: Ignoring the message as reply queue is not set.\n", receive_queue_name); continue; } //Execute calculation #ifdef _TRACE_MC_ logout("[core_%u] Execute process (processing_type=%u)\n", p_msg->core_id, p_msg->info.processing_type); //trace #endif switch(p_msg->info.processing_type) { case pt_ssd: //Call calculation code exec_ssd(p_msg); break; case pt_ssdJacHess: //Call calculation code exec_ssdJacHess(p_msg); break; case pt_cacheinval: CacheInvalTotalMemory(p_msg); break; case pt_shrink: //Call image shrink code exec_shrinkImage(p_msg); break; default: logout("Invalid IPC processing type: %u", p_msg->info.processing_type); } /* send the message to the remote processor */ #ifdef _TRACE_MC_ logout("[core_%u] Putting slave response to the MessageQ, then going idle again ...\n", p_msg->core_id); #endif if (MessageQ_put(reply_queue_id, (MessageQ_Msg)p_msg) < 0) { logout("%s: MessageQ_put had a failure error\n", receive_queue_name); } } close_n_exit: if(h_receive_queue) MessageQ_delete(&h_receive_queue); }