Change CmiUInt2 msgType to CmiUInt1 cmaMsgType:2 in conv-common.h
[charm.git] / src / arch / util / machine-cma.c
1 #ifndef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #endif
4 #include <sys/uio.h>
5
6 // Method checks if process has permissions to use CMA
7 int CmiInitCma() {
8   char buffer   = '0';
9   int cma_works = 0;
10   int fd;
11
12   // determine permissions
13   fd = open("/proc/sys/kernel/yama/ptrace_scope", O_RDONLY);
14   if (0 <= fd) {
15     if (read (fd, &buffer, 1) != 1) {
16       CmiAbort("CMA> reading /proc/sys/kernel/yama/ptrace_scope failed!");
17     }
18     close(fd);
19   }
20
21   if('0' != buffer) {
22 #if defined PR_SET_PTRACER
23     // set ptrace scope to allow attach
24     int ret = prctl (PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
25     if (0 == ret) {
26       cma_works = 1;
27     }
28 #endif
29   } else {
30     cma_works = 1;
31   }
32   return cma_works;
33 }
34
35 // Method to display thresholds for regular messaging using CMA
36 void CmiDisplayCMAThresholds(int cma_min_threshold, int cma_max_threshold) {
37   if(_Cmi_mynode == 0) {
38       if(cma_min_threshold > cma_max_threshold) {
39         CmiAbort("CMA size thresholds incorrect! Values should satisfy cma_min_threshold <= cma_min_threshold condition");
40       }
41       CmiPrintf("Charm++> CMA enabled for within node transfers of messages(sized between %d & %d bytes)\n", cma_min_threshold, cma_max_threshold);
42   }
43 }
44
45 /* Used to read from a list of remote buffers and write into a
46  * list of local buffers over SHM using the cma library
47  */
48 int readShmCma(
49   pid_t remote_pid,
50   struct iovec *local,
51   struct iovec *remote,
52   int numOps,
53   size_t total_bytes) {
54
55   int nread = process_vm_readv(remote_pid, local, numOps, remote, numOps, 0);
56   if(nread != total_bytes) {
57     CmiAbort("process_vm_readv failed!\n");
58     return errno;
59   }
60   return 0;
61 }
62
63 /* Used to write into a list of remote buffers by reading from a
64  * list of local buffers over SHM using the cma library
65  */
66 int writeShmCma(
67   pid_t remote_pid,
68   struct iovec *local,
69   struct iovec *remote,
70   int numOps,
71   size_t total_bytes) {
72
73   int nread = process_vm_writev(remote_pid, local, numOps, remote, numOps, 0);
74   if(nread != total_bytes) {
75     CmiAbort("process_vm_writev failed!\n");
76     return errno;
77   }
78   return 0;
79 }
80
81 // Metadata of a buffer that is to be sent to another intra-host process over CMA
82 typedef struct _cma_src_buffer_info {
83   int srcPE;
84   pid_t srcPid;
85   void *srcAddr;
86   int size;
87 }CmaSrcBufferInfo_t;
88
89 // Method invoked on receiving a CMK_CMA_MD_MSG
90 // This method uses the buffer metadata to perform a CMA read. It also modifies *sizePtr & *msgPtr to
91 // point to the buffer message
92 void handleOneCmaMdMsg(int *sizePtr, char **msgPtr) {
93   struct iovec local, remote;
94   char *destAddr;
95
96   // Get buffer metadata
97   CmaSrcBufferInfo_t *bufInfo = (CmaSrcBufferInfo_t *)(*msgPtr + CmiMsgHeaderSizeBytes);
98
99   // Allocate a buffer to hold the buffer
100   destAddr = (char *)CmiAlloc(bufInfo->size);
101
102   local.iov_base = (void *)destAddr;
103   local.iov_len  = bufInfo->size;
104
105   remote.iov_base = bufInfo->srcAddr;
106   remote.iov_len  = bufInfo->size;
107
108   // Perform CMA read into destAddr
109   readShmCma(bufInfo->srcPid,
110              &local,
111              &remote,
112              1,
113              bufInfo->size);
114
115   // Send the buffer md msg back as an ack msg to signal CMA read completion in order to free buffers
116   // on the source process
117   CMI_CMA_MSGTYPE(*msgPtr) = CMK_CMA_ACK_MSG;
118
119   CmiInterSendNetworkFunc(bufInfo->srcPE,
120                           CmiMyPartition(),
121                           CmiMsgHeaderSizeBytes + sizeof(CmaSrcBufferInfo_t),
122                           *msgPtr,
123                           P2P_SYNC);
124
125   // Reassign *msgPtr to the buffer
126   *msgPtr = destAddr;
127   // Reassign *sizePtr to the size of the buffer
128   *sizePtr = local.iov_len;
129 }
130
131
132 // Method invoked on receiving CMK_CMA_ACK_MSG
133 // This method frees the buffer and the received buffer ack msg
134 void handleOneCmaAckMsg(int size, void *msg) {
135
136   // Get buffer metadata
137   CmaSrcBufferInfo_t *bufInfo = (CmaSrcBufferInfo_t *)((char *)msg + CmiMsgHeaderSizeBytes);
138
139   // Free the large buffer sent
140   CmiFree(bufInfo->srcAddr);
141
142   // Free this ack message
143   CmiFree(msg);
144 }
145
146 // Method invoked to send the buffer via CMA
147 // This method creates a buffer metadata msg from a buffer and modifies the *msgPtr and *sizePtr to point to
148 // the buffer metadata msg.
149 void CmiSendMessageCma(char **msgPtr, int *sizePtr) {
150
151   // Send buffer metadata instead of original msg
152   // Buffer metadata msg consists of pid, addr, size for the other process to perform a read through CMA
153   char *cmaBufMdMsg = (char *)CmiAlloc(CmiMsgHeaderSizeBytes + sizeof(CmaSrcBufferInfo_t));
154   CmaSrcBufferInfo_t *bufInfo = (CmaSrcBufferInfo_t *)(cmaBufMdMsg + CmiMsgHeaderSizeBytes);
155   bufInfo->srcPE  = CmiMyPe();
156   bufInfo->srcPid = getpid();
157   bufInfo->srcAddr = *msgPtr;
158   bufInfo->size    = *sizePtr;
159
160   // Tag this message as a CMA buffer md message
161   CMI_CMA_MSGTYPE(cmaBufMdMsg) = CMK_CMA_MD_MSG;
162
163   // Reassign *sizePtr to store the size of the buffer md msg
164   *sizePtr = CmiMsgHeaderSizeBytes + sizeof(CmaSrcBufferInfo_t);
165
166   // Reassign *msgPtr to point to the buffer metadata msg
167   *msgPtr = (char *)cmaBufMdMsg;
168 }