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