Add a flag to provide timer for the case of no objs in Meta-Balancer
[charm.git] / src / arch / mpi / machine-ctrlmsg.c
1 /* An alternative way to implement MPI-based machine layer */
2 /* Control flows of this scheme:
3  * SEND SIDE:
4  * 1. send a fixed-size small control msg to destination (MPI_Send)
5  *     so the ctrl msg buffer can be reused every time.
6  * 2. immediately following the 1st step, send the actual msg (MPI_Isend)
7  * 3. free the buffer for the sent msg
8  * 
9  * RECV SIDE:
10  * 1. Pre-post buffers for those small ctrl msgs (MPI_Irecv)
11  * 2. If any ctrl msg is received, issue a (i)recv call for the actual msg 
12  *     (differentiate small/large msgs)
13  *
14  * MEMORY ALLOCATION:
15  * use MPI_Alloc_mem and MPI_Free_mem so that CmiAllloc/CmiFree needs to be changed
16  */
17
18 /* This file contains variables and function declarations that are used for this alternative implementation */
19
20 /* This file contains function and variables definitions that are used for this alternative implementation */
21
22 #if USE_MPI_CTRLMSG_SCHEME
23
24 #define CTRL_MSG_TAG         (TAG-13)
25
26 static int MPI_CTRL_MSG_CNT=10;
27
28 typedef struct MPICtrlMsgEntry{
29         int src;
30         int size;
31 }MPICtrlMsgEntry;
32
33 typedef struct RecvCtrlMsgEntry{
34         int bufCnt;
35         MPI_Request *ctrlReqs; /* sizeof(MPI_Request* bufCnt */
36         MPICtrlMsgEntry *bufs; /*sizeof(MPICtrlMsgEntry)*bufCnt*/
37 }RecvCtrlMsgEntry;
38
39 static RecvCtrlMsgEntry recvCtrlMsgList;
40
41 static void createCtrlMsgIrecvBufs(){
42         int i;
43         MPICtrlMsgEntry *bufPtr = NULL;
44         MPI_Request *reqPtr = NULL;
45         int count = MPI_CTRL_MSG_CNT;
46         
47         recvCtrlMsgList.bufCnt = count;
48         recvCtrlMsgList.ctrlReqs = (MPI_Request *)malloc(sizeof(MPI_Request)*count);
49         recvCtrlMsgList.bufs = (MPICtrlMsgEntry *)malloc(sizeof(MPICtrlMsgEntry)*count);
50         
51         bufPtr = recvCtrlMsgList.bufs;
52         reqPtr = recvCtrlMsgList.ctrlReqs;
53         
54         for(i=0; i<count; i++, bufPtr++, reqPtr++){
55                 if(MPI_SUCCESS != MPI_Irecv(bufPtr, sizeof(MPICtrlMsgEntry), 
56                                                                                                          MPI_BYTE, MPI_ANY_SOURCE, CTRL_MSG_TAG, charmComm, reqPtr)){
57                         CmiAbort("MPI_Irecv failed in creating pre-posted ctrl msg buffers\n");
58                 }
59         }
60 }
61
62 static void sendViaCtrlMsg(int node, int size, char *msg, SMSG_LIST *smsg){
63         MPICtrlMsgEntry one;
64
65         one.src = CmiMyNode();
66         one.size = size;
67         
68         START_TRACE_SENDCOMM(msg);
69         if(MPI_SUCCESS != MPI_Send((void *)&one, sizeof(MPICtrlMsgEntry), MPI_BYTE, node, 
70                                                                                                    CTRL_MSG_TAG, charmComm)){
71                 CmiAbort("MPI_Send failed in sending ctrl msg\n");
72         }
73         
74         if (MPI_SUCCESS != MPI_Isend((void *)msg,size,MPI_BYTE,node,TAG,charmComm,&(smsg->req)))
75             CmiAbort("MPISendOneMsg: MPI_Isend failed!\n");
76         END_TRACE_SENDCOMM(msg);
77 }
78
79 /* returns the size of msg to be received. If there's no msg to be received, then -1 is returned */
80 static int recvViaCtrlMsg(){
81         int count = recvCtrlMsgList.bufCnt;
82         MPI_Request *ctrlReqs = recvCtrlMsgList.ctrlReqs;
83         MPICtrlMsgEntry *ctrlMsgs = recvCtrlMsgList.bufs;
84         
85         int completed_index = -1;
86         int flg = 0;
87         int nbytes = -1;
88         MPI_Status sts;
89         
90         if(MPI_SUCCESS != MPI_Testany(count, ctrlReqs, &completed_index, &flg, &sts)){
91                 CmiAbort("MPI_Testany failed for checking if ctrl msg is received\n");
92         }
93         
94         if(flg){
95                 int src = ctrlMsgs[completed_index].src;
96                 int msgsize = ctrlMsgs[completed_index].size;
97                 nbytes = msgsize;
98                 char *actualMsg = (char *)CmiAlloc(msgsize);
99                 
100                 IRecvList one = irecvListEntryAllocate();
101                 
102                 /* repost the ctrl msg */
103                 if(MPI_SUCCESS != MPI_Irecv(ctrlMsgs+completed_index, sizeof(MPICtrlMsgEntry), MPI_BYTE,
104                                                                   MPI_ANY_SOURCE, CTRL_MSG_TAG, charmComm, ctrlReqs+completed_index)){
105                         CmiAbort("MPI_Irecv failed in re-posting a ctrl msg is received\n");
106                 }
107                 
108                 /* irecv the actual msg */
109                 if(MPI_SUCCESS != MPI_Irecv(actualMsg, msgsize, MPI_BYTE, src, TAG, charmComm, &(one->req))){
110                         CmiAbort("MPI_Irecv failed after a ctrl msg is received\n");
111                 }
112                 one->msg = actualMsg;
113                 one->size = msgsize;
114                 one->next = NULL;
115                 waitIrecvListTail->next = one;
116                 waitIrecvListTail = one;
117         }
118         
119         return nbytes;
120 }
121
122 #endif