Home | History | Annotate | Download | only in libion
      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 
     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 
     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 
     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 
    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 
    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