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