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