2 * Copyright © 2012-2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Daniel Vetter <daniel.vetter@ffwll.ch>
29 * Testcase: Check whether prime import/export works on the same device
31 * ... but with different fds, i.e. the wayland usecase.
43 #include <sys/ioctl.h>
47 #include "ioctl_wrappers.h"
49 #include "igt_debugfs.h"
51 #define BO_SIZE (16*1024)
54 volatile int pls_die = 0;
57 check_bo(int fd1, uint32_t handle1, int fd2, uint32_t handle2)
62 ptr1 = gem_mmap(fd1, handle1, BO_SIZE, PROT_READ | PROT_WRITE);
63 ptr2 = gem_mmap(fd2, handle2, BO_SIZE, PROT_READ | PROT_WRITE);
67 /* check whether it's still our old object first. */
68 for (i = 0; i < BO_SIZE; i++) {
69 igt_assert(ptr1[i] == counter);
70 igt_assert(ptr2[i] == counter);
75 memset(ptr1, counter, BO_SIZE);
76 igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
78 munmap(ptr1, BO_SIZE);
79 munmap(ptr2, BO_SIZE);
82 static void test_with_fd_dup(void)
85 uint32_t handle, handle_import;
86 int dma_buf_fd1, dma_buf_fd2;
93 handle = gem_create(fd1, BO_SIZE);
95 dma_buf_fd1 = prime_handle_to_fd(fd1, handle);
96 gem_close(fd1, handle);
98 dma_buf_fd2 = dup(dma_buf_fd1);
100 handle_import = prime_fd_to_handle(fd2, dma_buf_fd2);
101 check_bo(fd2, handle_import, fd2, handle_import);
104 check_bo(fd2, handle_import, fd2, handle_import);
110 static void test_with_two_bos(void)
113 uint32_t handle1, handle2, handle_import;
118 fd1 = drm_open_any();
119 fd2 = drm_open_any();
121 handle1 = gem_create(fd1, BO_SIZE);
122 handle2 = gem_create(fd1, BO_SIZE);
124 dma_buf_fd = prime_handle_to_fd(fd1, handle1);
125 handle_import = prime_fd_to_handle(fd2, dma_buf_fd);
128 gem_close(fd1, handle1);
130 dma_buf_fd = prime_handle_to_fd(fd1, handle2);
131 handle_import = prime_fd_to_handle(fd2, dma_buf_fd);
132 check_bo(fd1, handle2, fd2, handle_import);
134 gem_close(fd1, handle2);
137 check_bo(fd2, handle_import, fd2, handle_import);
143 static void test_with_one_bo_two_files(void)
146 uint32_t handle_import, handle_open, handle_orig, flink_name;
147 int dma_buf_fd1, dma_buf_fd2;
149 fd1 = drm_open_any();
150 fd2 = drm_open_any();
152 handle_orig = gem_create(fd1, BO_SIZE);
153 dma_buf_fd1 = prime_handle_to_fd(fd1, handle_orig);
155 flink_name = gem_flink(fd1, handle_orig);
156 handle_open = gem_open(fd2, flink_name);
158 dma_buf_fd2 = prime_handle_to_fd(fd2, handle_open);
159 handle_import = prime_fd_to_handle(fd2, dma_buf_fd2);
161 /* dma-buf selfimporting an flink bo should give the same handle */
162 igt_assert(handle_import == handle_open);
170 static void test_with_one_bo(void)
173 uint32_t handle, handle_import1, handle_import2, handle_selfimport;
176 fd1 = drm_open_any();
177 fd2 = drm_open_any();
179 handle = gem_create(fd1, BO_SIZE);
181 dma_buf_fd = prime_handle_to_fd(fd1, handle);
182 handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
184 check_bo(fd1, handle, fd2, handle_import1);
186 /* reimport should give us the same handle so that userspace can check
187 * whether it has that bo already somewhere. */
188 handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd);
189 igt_assert(handle_import1 == handle_import2);
191 /* Same for re-importing on the exporting fd. */
192 handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd);
193 igt_assert(handle == handle_selfimport);
195 /* close dma_buf, check whether nothing disappears. */
197 check_bo(fd1, handle, fd2, handle_import1);
199 gem_close(fd1, handle);
200 check_bo(fd2, handle_import1, fd2, handle_import1);
202 /* re-import into old exporter */
203 dma_buf_fd = prime_handle_to_fd(fd2, handle_import1);
204 /* but drop all references to the obj in between */
205 gem_close(fd2, handle_import1);
206 handle = prime_fd_to_handle(fd1, dma_buf_fd);
207 handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
208 check_bo(fd1, handle, fd2, handle_import1);
210 /* Completely rip out exporting fd. */
212 check_bo(fd2, handle_import1, fd2, handle_import1);
215 static int get_object_count(void)
219 int device = drm_get_card();
222 igt_drop_caches_set(DROP_RETIRE);
224 ret = asprintf(&path, "/sys/kernel/debug/dri/%d/i915_gem_objects", device);
225 igt_assert(ret != -1);
227 file = fopen(path, "r");
229 scanned = fscanf(file, "%i objects", &ret);
230 igt_assert(scanned == 1);
235 static void *thread_fn_reimport_vs_close(void *p)
237 struct drm_gem_close close_bo;
240 int dma_buf_fd = fds[1];
244 handle = prime_fd_to_handle(fd, dma_buf_fd);
246 close_bo.handle = handle;
247 ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
253 static void test_reimport_close_race(void)
256 int r, i, num_threads;
263 /* Allocate exit handler fds in here so that we dont screw
265 fake = drm_open_any();
267 obj_count = get_object_count();
269 num_threads = sysconf(_SC_NPROCESSORS_ONLN);
271 threads = calloc(num_threads, sizeof(pthread_t));
273 fds[0] = drm_open_any();
274 igt_assert(fds[0] >= 0);
276 handle = gem_create(fds[0], BO_SIZE);
278 fds[1] = prime_handle_to_fd(fds[0], handle);
280 for (i = 0; i < num_threads; i++) {
281 r = pthread_create(&threads[i], NULL,
282 thread_fn_reimport_vs_close,
283 (void *)(uintptr_t)fds);
291 for (i = 0; i < num_threads; i++) {
292 pthread_join(threads[i], &status);
293 igt_assert(status == 0);
299 obj_count = get_object_count() - obj_count;
301 igt_info("leaked %i objects\n", obj_count);
305 igt_assert_cmpint(obj_count, ==, 0);
308 static void *thread_fn_export_vs_close(void *p)
310 struct drm_prime_handle prime_h2f;
311 struct drm_gem_close close_bo;
312 int fd = (uintptr_t)p;
316 /* We want to race gem close against prime export on handle one.*/
317 handle = gem_create(fd, 4096);
319 gem_close(fd, handle);
321 /* raw ioctl since we expect this to fail */
323 /* WTF: for gem_flink_race I've unconditionally used handle == 1
324 * here, but with prime it seems to help a _lot_ to use
325 * something more random. */
326 prime_h2f.handle = 1;
327 prime_h2f.flags = DRM_CLOEXEC;
330 ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_h2f);
333 ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
341 static void test_export_close_race(void)
344 int r, i, num_threads;
349 obj_count = get_object_count();
351 num_threads = sysconf(_SC_NPROCESSORS_ONLN);
353 threads = calloc(num_threads, sizeof(pthread_t));
358 for (i = 0; i < num_threads; i++) {
359 r = pthread_create(&threads[i], NULL,
360 thread_fn_export_vs_close,
361 (void *)(uintptr_t)fd);
369 for (i = 0; i < num_threads; i++) {
370 pthread_join(threads[i], &status);
371 igt_assert(status == 0);
376 obj_count = get_object_count() - obj_count;
378 igt_info("leaked %i objects\n", obj_count);
379 igt_assert_cmpint(obj_count, ==, 0);
382 static void test_llseek_size(void)
393 for (i = 0; i < 10; i++) {
394 int bufsz = 4096 << i;
396 handle = gem_create(fd, bufsz);
397 dma_buf_fd = prime_handle_to_fd(fd, handle);
399 gem_close(fd, handle);
401 igt_assert(prime_get_size(dma_buf_fd) == bufsz);
409 static void test_llseek_bad(void)
420 handle = gem_create(fd, BO_SIZE);
421 dma_buf_fd = prime_handle_to_fd(fd, handle);
423 gem_close(fd, handle);
425 igt_require(lseek(dma_buf_fd, 0, SEEK_END) >= 0);
427 igt_assert(lseek(dma_buf_fd, -1, SEEK_END) == -1 && errno == EINVAL);
428 igt_assert(lseek(dma_buf_fd, 1, SEEK_SET) == -1 && errno == EINVAL);
429 igt_assert(lseek(dma_buf_fd, BO_SIZE, SEEK_SET) == -1 && errno == EINVAL);
430 igt_assert(lseek(dma_buf_fd, BO_SIZE + 1, SEEK_SET) == -1 && errno == EINVAL);
431 igt_assert(lseek(dma_buf_fd, BO_SIZE - 1, SEEK_SET) == -1 && errno == EINVAL);
444 { "with_one_bo", test_with_one_bo },
445 { "with_one_bo_two_files", test_with_one_bo_two_files },
446 { "with_two_bos", test_with_two_bos },
447 { "with_fd_dup", test_with_fd_dup },
448 { "export-vs-gem_close-race", test_export_close_race },
449 { "reimport-vs-gem_close-race", test_reimport_close_race },
450 { "llseek-size", test_llseek_size },
451 { "llseek-bad", test_llseek_bad },
455 for (i = 0; i < ARRAY_SIZE(tests); i++) {
456 igt_subtest(tests[i].name)