ion_test.c revision 1dac52160a4c982fbe3e08b633f5e24171bee2d8
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
18size_t len = 1024*1024, align = 0;
19int prot = PROT_READ | PROT_WRITE;
20int map_flags = MAP_SHARED;
21int alloc_flags = 0;
22int heap_mask = 1;
23int test = -1;
24size_t width = 1024*1024, height = 1024*1024;
25int fmt = TILER_PIXEL_FMT_32BIT;
26int tiler_test = 0;
27size_t stride;
28
29int _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
48void 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
65void _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
84void 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
132void 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
228int 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