• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <getopt.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <sys/mman.h>
8 #include <sys/ioctl.h>
9 #include <sys/socket.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 
14 #include <ion/ion.h>
15 #include <linux/ion.h>
16 #include <linux/omap_ion.h>
17 
18 size_t len = 1024*1024, align = 0;
19 int prot = PROT_READ | PROT_WRITE;
20 int map_flags = MAP_SHARED;
21 int alloc_flags = 0;
22 int heap_mask = 1;
23 int test = -1;
24 size_t stride;
25 
_ion_alloc_test(int * fd,struct ion_handle ** handle)26 int _ion_alloc_test(int *fd, struct ion_handle **handle)
27 {
28 	int ret;
29 
30 	*fd = ion_open();
31 	if (*fd < 0)
32 		return *fd;
33 
34 	ret = ion_alloc(*fd, len, align, heap_mask, alloc_flags, handle);
35 
36 	if (ret)
37 		printf("%s failed: %s\n", __func__, strerror(ret));
38 	return ret;
39 }
40 
ion_alloc_test()41 void ion_alloc_test()
42 {
43 	int fd, ret;
44 	struct ion_handle *handle;
45 
46 	if(_ion_alloc_test(&fd, &handle))
47 			return;
48 
49 	ret = ion_free(fd, handle);
50 	if (ret) {
51 		printf("%s failed: %s %p\n", __func__, strerror(ret), handle);
52 		return;
53 	}
54 	ion_close(fd);
55 	printf("ion alloc test: passed\n");
56 }
57 
ion_map_test()58 void ion_map_test()
59 {
60 	int fd, map_fd, ret;
61 	size_t i;
62 	struct ion_handle *handle;
63 	unsigned char *ptr;
64 
65 	if(_ion_alloc_test(&fd, &handle))
66 		return;
67 
68 	ret = ion_map(fd, handle, len, prot, map_flags, 0, &ptr, &map_fd);
69 	if (ret)
70 		return;
71 
72 	for (i = 0; i < len; i++) {
73 		ptr[i] = (unsigned char)i;
74 	}
75 	for (i = 0; i < len; i++)
76 		if (ptr[i] != (unsigned char)i)
77 			printf("%s failed wrote %d read %d from mapped "
78 			       "memory\n", __func__, i, ptr[i]);
79 	/* clean up properly */
80 	ret = ion_free(fd, handle);
81 	ion_close(fd);
82 	munmap(ptr, len);
83 	close(map_fd);
84 
85 	_ion_alloc_test(&fd, &handle);
86 	close(fd);
87 
88 #if 0
89 	munmap(ptr, len);
90 	close(map_fd);
91 	ion_close(fd);
92 
93 	_ion_alloc_test(len, align, flags, &fd, &handle);
94 	close(map_fd);
95 	ret = ion_map(fd, handle, len, prot, flags, 0, &ptr, &map_fd);
96 	/* don't clean up */
97 #endif
98 }
99 
ion_share_test()100 void ion_share_test()
101 
102 {
103 	struct ion_handle *handle;
104 	int sd[2];
105 	int num_fd = 1;
106 	struct iovec count_vec = {
107 		.iov_base = &num_fd,
108 		.iov_len = sizeof num_fd,
109 	};
110 	char buf[CMSG_SPACE(sizeof(int))];
111 	socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
112 	if (fork()) {
113 		struct msghdr msg = {
114 			.msg_control = buf,
115 			.msg_controllen = sizeof buf,
116 			.msg_iov = &count_vec,
117 			.msg_iovlen = 1,
118 		};
119 
120 		struct cmsghdr *cmsg;
121 		int fd, share_fd, ret;
122 		char *ptr;
123 		/* parent */
124 		if(_ion_alloc_test(&fd, &handle))
125 			return;
126 		ret = ion_share(fd, handle, &share_fd);
127 		if (ret)
128 			printf("share failed %s\n", strerror(errno));
129 		ptr = mmap(NULL, len, prot, map_flags, share_fd, 0);
130 		if (ptr == MAP_FAILED) {
131 			return;
132 		}
133 		strcpy(ptr, "master");
134 		cmsg = CMSG_FIRSTHDR(&msg);
135 		cmsg->cmsg_level = SOL_SOCKET;
136 		cmsg->cmsg_type = SCM_RIGHTS;
137 		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
138 		*(int *)CMSG_DATA(cmsg) = share_fd;
139 		/* send the fd */
140 		printf("master? [%10s] should be [master]\n", ptr);
141 		printf("master sending msg 1\n");
142 		sendmsg(sd[0], &msg, 0);
143 		if (recvmsg(sd[0], &msg, 0) < 0)
144 			perror("master recv msg 2");
145 		printf("master? [%10s] should be [child]\n", ptr);
146 
147 		/* send ping */
148 		sendmsg(sd[0], &msg, 0);
149 		printf("master->master? [%10s]\n", ptr);
150 		if (recvmsg(sd[0], &msg, 0) < 0)
151 			perror("master recv 1");
152 	} else {
153 		struct msghdr msg;
154 		struct cmsghdr *cmsg;
155 		char* ptr;
156 		int fd, recv_fd;
157 		char* child_buf[100];
158 		/* child */
159 		struct iovec count_vec = {
160 			.iov_base = child_buf,
161 			.iov_len = sizeof child_buf,
162 		};
163 
164 		struct msghdr child_msg = {
165 			.msg_control = buf,
166 			.msg_controllen = sizeof buf,
167 			.msg_iov = &count_vec,
168 			.msg_iovlen = 1,
169 		};
170 
171 		if (recvmsg(sd[1], &child_msg, 0) < 0)
172 			perror("child recv msg 1");
173 		cmsg = CMSG_FIRSTHDR(&child_msg);
174 		if (cmsg == NULL) {
175 			printf("no cmsg rcvd in child");
176 			return;
177 		}
178 		recv_fd = *(int*)CMSG_DATA(cmsg);
179 		if (recv_fd < 0) {
180 			printf("could not get recv_fd from socket");
181 			return;
182 		}
183 		printf("child %d\n", recv_fd);
184 		fd = ion_open();
185 		ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0);
186 		if (ptr == MAP_FAILED) {
187 			return;
188 		}
189 		printf("child? [%10s] should be [master]\n", ptr);
190 		strcpy(ptr, "child");
191 		printf("child sending msg 2\n");
192 		sendmsg(sd[1], &child_msg, 0);
193 	}
194 }
195 
main(int argc,char * argv[])196 int main(int argc, char* argv[]) {
197 	int c;
198 	enum tests {
199 		ALLOC_TEST = 0, MAP_TEST, SHARE_TEST,
200 	};
201 
202 	while (1) {
203 		static struct option opts[] = {
204 			{"alloc", no_argument, 0, 'a'},
205 			{"alloc_flags", required_argument, 0, 'f'},
206 			{"heap_mask", required_argument, 0, 'h'},
207 			{"map", no_argument, 0, 'm'},
208 			{"share", no_argument, 0, 's'},
209 			{"len", required_argument, 0, 'l'},
210 			{"align", required_argument, 0, 'g'},
211 			{"map_flags", required_argument, 0, 'z'},
212 			{"prot", required_argument, 0, 'p'},
213 		};
214 		int i = 0;
215 		c = getopt_long(argc, argv, "af:h:l:mr:st", opts, &i);
216 		if (c == -1)
217 			break;
218 
219 		switch (c) {
220 		case 'l':
221 			len = atol(optarg);
222 			break;
223 		case 'g':
224 			align = atol(optarg);
225 			break;
226 		case 'z':
227 			map_flags = 0;
228 			map_flags |= strstr(optarg, "PROT_EXEC") ?
229 				PROT_EXEC : 0;
230 			map_flags |= strstr(optarg, "PROT_READ") ?
231 				PROT_READ: 0;
232 			map_flags |= strstr(optarg, "PROT_WRITE") ?
233 				PROT_WRITE: 0;
234 			map_flags |= strstr(optarg, "PROT_NONE") ?
235 				PROT_NONE: 0;
236 			break;
237 		case 'p':
238 			prot = 0;
239 			prot |= strstr(optarg, "MAP_PRIVATE") ?
240 				MAP_PRIVATE	 : 0;
241 			prot |= strstr(optarg, "MAP_SHARED") ?
242 				MAP_PRIVATE	 : 0;
243 			break;
244 		case 'f':
245 			alloc_flags = atol(optarg);
246 			break;
247 		case 'h':
248 			heap_mask = atol(optarg);
249 			break;
250 		case 'a':
251 			test = ALLOC_TEST;
252 			break;
253 		case 'm':
254 			test = MAP_TEST;
255 			break;
256 		case 's':
257 			test = SHARE_TEST;
258 			break;
259 		}
260 	}
261 	printf("test %d, len %u, align %u, map_flags %d, prot %d, heap_mask %d,"
262 	       " alloc_flags %d\n", test, len, align, map_flags, prot,
263 	       heap_mask, alloc_flags);
264 	switch (test) {
265 		case ALLOC_TEST:
266 			ion_alloc_test();
267 			break;
268 		case MAP_TEST:
269 			ion_map_test();
270 			break;
271 		case SHARE_TEST:
272 			ion_share_test();
273 			break;
274 		default:
275 			printf("must specify a test (alloc, map, share)\n");
276 	}
277 	return 0;
278 }
279