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