1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2012-2013 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker *
23*d83cc019SAndroid Build Coastguard Worker * Authors:
24*d83cc019SAndroid Build Coastguard Worker * Daniel Vetter <[email protected]>
25*d83cc019SAndroid Build Coastguard Worker *
26*d83cc019SAndroid Build Coastguard Worker */
27*d83cc019SAndroid Build Coastguard Worker
28*d83cc019SAndroid Build Coastguard Worker /*
29*d83cc019SAndroid Build Coastguard Worker * Testcase: Check whether prime import/export works on the same device
30*d83cc019SAndroid Build Coastguard Worker *
31*d83cc019SAndroid Build Coastguard Worker * ... but with different fds, i.e. the wayland usecase.
32*d83cc019SAndroid Build Coastguard Worker */
33*d83cc019SAndroid Build Coastguard Worker
34*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
35*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
36*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
37*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
38*d83cc019SAndroid Build Coastguard Worker #include <string.h>
39*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
40*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
41*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
42*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
43*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
44*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
45*d83cc019SAndroid Build Coastguard Worker
46*d83cc019SAndroid Build Coastguard Worker #include "drm.h"
47*d83cc019SAndroid Build Coastguard Worker
48*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Check whether prime import/export works on the same"
49*d83cc019SAndroid Build Coastguard Worker " device... but with different fds.");
50*d83cc019SAndroid Build Coastguard Worker
51*d83cc019SAndroid Build Coastguard Worker #define BO_SIZE (16*1024)
52*d83cc019SAndroid Build Coastguard Worker
53*d83cc019SAndroid Build Coastguard Worker static char counter;
54*d83cc019SAndroid Build Coastguard Worker volatile int pls_die = 0;
55*d83cc019SAndroid Build Coastguard Worker
56*d83cc019SAndroid Build Coastguard Worker static void
check_bo(int fd1,uint32_t handle1,int fd2,uint32_t handle2)57*d83cc019SAndroid Build Coastguard Worker check_bo(int fd1, uint32_t handle1, int fd2, uint32_t handle2)
58*d83cc019SAndroid Build Coastguard Worker {
59*d83cc019SAndroid Build Coastguard Worker char *ptr1, *ptr2;
60*d83cc019SAndroid Build Coastguard Worker int i;
61*d83cc019SAndroid Build Coastguard Worker
62*d83cc019SAndroid Build Coastguard Worker
63*d83cc019SAndroid Build Coastguard Worker ptr1 = gem_mmap__cpu(fd1, handle1, 0, BO_SIZE, PROT_READ | PROT_WRITE);
64*d83cc019SAndroid Build Coastguard Worker ptr2 = gem_mmap__cpu(fd2, handle2, 0, BO_SIZE, PROT_READ | PROT_WRITE);
65*d83cc019SAndroid Build Coastguard Worker
66*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd1, handle1, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
67*d83cc019SAndroid Build Coastguard Worker gem_set_domain(fd2, handle2, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
68*d83cc019SAndroid Build Coastguard Worker
69*d83cc019SAndroid Build Coastguard Worker /* check whether it's still our old object first. */
70*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < BO_SIZE; i++) {
71*d83cc019SAndroid Build Coastguard Worker igt_assert(ptr1[i] == counter);
72*d83cc019SAndroid Build Coastguard Worker igt_assert(ptr2[i] == counter);
73*d83cc019SAndroid Build Coastguard Worker }
74*d83cc019SAndroid Build Coastguard Worker
75*d83cc019SAndroid Build Coastguard Worker counter++;
76*d83cc019SAndroid Build Coastguard Worker
77*d83cc019SAndroid Build Coastguard Worker memset(ptr1, counter, BO_SIZE);
78*d83cc019SAndroid Build Coastguard Worker igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
79*d83cc019SAndroid Build Coastguard Worker
80*d83cc019SAndroid Build Coastguard Worker munmap(ptr1, BO_SIZE);
81*d83cc019SAndroid Build Coastguard Worker munmap(ptr2, BO_SIZE);
82*d83cc019SAndroid Build Coastguard Worker }
83*d83cc019SAndroid Build Coastguard Worker
test_with_fd_dup(void)84*d83cc019SAndroid Build Coastguard Worker static void test_with_fd_dup(void)
85*d83cc019SAndroid Build Coastguard Worker {
86*d83cc019SAndroid Build Coastguard Worker int fd1, fd2;
87*d83cc019SAndroid Build Coastguard Worker uint32_t handle, handle_import;
88*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd1, dma_buf_fd2;
89*d83cc019SAndroid Build Coastguard Worker
90*d83cc019SAndroid Build Coastguard Worker counter = 0;
91*d83cc019SAndroid Build Coastguard Worker
92*d83cc019SAndroid Build Coastguard Worker fd1 = drm_open_driver(DRIVER_INTEL);
93*d83cc019SAndroid Build Coastguard Worker fd2 = drm_open_driver(DRIVER_INTEL);
94*d83cc019SAndroid Build Coastguard Worker
95*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fd1, BO_SIZE);
96*d83cc019SAndroid Build Coastguard Worker
97*d83cc019SAndroid Build Coastguard Worker dma_buf_fd1 = prime_handle_to_fd(fd1, handle);
98*d83cc019SAndroid Build Coastguard Worker gem_close(fd1, handle);
99*d83cc019SAndroid Build Coastguard Worker
100*d83cc019SAndroid Build Coastguard Worker dma_buf_fd2 = dup(dma_buf_fd1);
101*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd1);
102*d83cc019SAndroid Build Coastguard Worker handle_import = prime_fd_to_handle(fd2, dma_buf_fd2);
103*d83cc019SAndroid Build Coastguard Worker check_bo(fd2, handle_import, fd2, handle_import);
104*d83cc019SAndroid Build Coastguard Worker
105*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd2);
106*d83cc019SAndroid Build Coastguard Worker check_bo(fd2, handle_import, fd2, handle_import);
107*d83cc019SAndroid Build Coastguard Worker
108*d83cc019SAndroid Build Coastguard Worker close(fd1);
109*d83cc019SAndroid Build Coastguard Worker close(fd2);
110*d83cc019SAndroid Build Coastguard Worker }
111*d83cc019SAndroid Build Coastguard Worker
test_with_two_bos(void)112*d83cc019SAndroid Build Coastguard Worker static void test_with_two_bos(void)
113*d83cc019SAndroid Build Coastguard Worker {
114*d83cc019SAndroid Build Coastguard Worker int fd1, fd2;
115*d83cc019SAndroid Build Coastguard Worker uint32_t handle1, handle2, handle_import;
116*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd;
117*d83cc019SAndroid Build Coastguard Worker
118*d83cc019SAndroid Build Coastguard Worker counter = 0;
119*d83cc019SAndroid Build Coastguard Worker
120*d83cc019SAndroid Build Coastguard Worker fd1 = drm_open_driver(DRIVER_INTEL);
121*d83cc019SAndroid Build Coastguard Worker fd2 = drm_open_driver(DRIVER_INTEL);
122*d83cc019SAndroid Build Coastguard Worker
123*d83cc019SAndroid Build Coastguard Worker handle1 = gem_create(fd1, BO_SIZE);
124*d83cc019SAndroid Build Coastguard Worker handle2 = gem_create(fd1, BO_SIZE);
125*d83cc019SAndroid Build Coastguard Worker
126*d83cc019SAndroid Build Coastguard Worker dma_buf_fd = prime_handle_to_fd(fd1, handle1);
127*d83cc019SAndroid Build Coastguard Worker handle_import = prime_fd_to_handle(fd2, dma_buf_fd);
128*d83cc019SAndroid Build Coastguard Worker
129*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd);
130*d83cc019SAndroid Build Coastguard Worker gem_close(fd1, handle1);
131*d83cc019SAndroid Build Coastguard Worker
132*d83cc019SAndroid Build Coastguard Worker dma_buf_fd = prime_handle_to_fd(fd1, handle2);
133*d83cc019SAndroid Build Coastguard Worker handle_import = prime_fd_to_handle(fd2, dma_buf_fd);
134*d83cc019SAndroid Build Coastguard Worker check_bo(fd1, handle2, fd2, handle_import);
135*d83cc019SAndroid Build Coastguard Worker
136*d83cc019SAndroid Build Coastguard Worker gem_close(fd1, handle2);
137*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd);
138*d83cc019SAndroid Build Coastguard Worker
139*d83cc019SAndroid Build Coastguard Worker check_bo(fd2, handle_import, fd2, handle_import);
140*d83cc019SAndroid Build Coastguard Worker
141*d83cc019SAndroid Build Coastguard Worker close(fd1);
142*d83cc019SAndroid Build Coastguard Worker close(fd2);
143*d83cc019SAndroid Build Coastguard Worker }
144*d83cc019SAndroid Build Coastguard Worker
test_with_one_bo_two_files(void)145*d83cc019SAndroid Build Coastguard Worker static void test_with_one_bo_two_files(void)
146*d83cc019SAndroid Build Coastguard Worker {
147*d83cc019SAndroid Build Coastguard Worker int fd1, fd2;
148*d83cc019SAndroid Build Coastguard Worker uint32_t handle_import, handle_open, handle_orig, flink_name;
149*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd1, dma_buf_fd2;
150*d83cc019SAndroid Build Coastguard Worker
151*d83cc019SAndroid Build Coastguard Worker fd1 = drm_open_driver(DRIVER_INTEL);
152*d83cc019SAndroid Build Coastguard Worker fd2 = drm_open_driver(DRIVER_INTEL);
153*d83cc019SAndroid Build Coastguard Worker
154*d83cc019SAndroid Build Coastguard Worker handle_orig = gem_create(fd1, BO_SIZE);
155*d83cc019SAndroid Build Coastguard Worker dma_buf_fd1 = prime_handle_to_fd(fd1, handle_orig);
156*d83cc019SAndroid Build Coastguard Worker
157*d83cc019SAndroid Build Coastguard Worker flink_name = gem_flink(fd1, handle_orig);
158*d83cc019SAndroid Build Coastguard Worker handle_open = gem_open(fd2, flink_name);
159*d83cc019SAndroid Build Coastguard Worker
160*d83cc019SAndroid Build Coastguard Worker dma_buf_fd2 = prime_handle_to_fd(fd2, handle_open);
161*d83cc019SAndroid Build Coastguard Worker handle_import = prime_fd_to_handle(fd2, dma_buf_fd2);
162*d83cc019SAndroid Build Coastguard Worker
163*d83cc019SAndroid Build Coastguard Worker /* dma-buf self importing an flink bo should give the same handle */
164*d83cc019SAndroid Build Coastguard Worker igt_assert_eq_u32(handle_import, handle_open);
165*d83cc019SAndroid Build Coastguard Worker
166*d83cc019SAndroid Build Coastguard Worker close(fd1);
167*d83cc019SAndroid Build Coastguard Worker close(fd2);
168*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd1);
169*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd2);
170*d83cc019SAndroid Build Coastguard Worker }
171*d83cc019SAndroid Build Coastguard Worker
test_with_one_bo(void)172*d83cc019SAndroid Build Coastguard Worker static void test_with_one_bo(void)
173*d83cc019SAndroid Build Coastguard Worker {
174*d83cc019SAndroid Build Coastguard Worker int fd1, fd2;
175*d83cc019SAndroid Build Coastguard Worker uint32_t handle, handle_import1, handle_import2, handle_selfimport;
176*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd;
177*d83cc019SAndroid Build Coastguard Worker
178*d83cc019SAndroid Build Coastguard Worker fd1 = drm_open_driver(DRIVER_INTEL);
179*d83cc019SAndroid Build Coastguard Worker fd2 = drm_open_driver(DRIVER_INTEL);
180*d83cc019SAndroid Build Coastguard Worker
181*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fd1, BO_SIZE);
182*d83cc019SAndroid Build Coastguard Worker
183*d83cc019SAndroid Build Coastguard Worker dma_buf_fd = prime_handle_to_fd(fd1, handle);
184*d83cc019SAndroid Build Coastguard Worker handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
185*d83cc019SAndroid Build Coastguard Worker
186*d83cc019SAndroid Build Coastguard Worker check_bo(fd1, handle, fd2, handle_import1);
187*d83cc019SAndroid Build Coastguard Worker
188*d83cc019SAndroid Build Coastguard Worker /* reimport should give us the same handle so that userspace can check
189*d83cc019SAndroid Build Coastguard Worker * whether it has that bo already somewhere. */
190*d83cc019SAndroid Build Coastguard Worker handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd);
191*d83cc019SAndroid Build Coastguard Worker igt_assert_eq_u32(handle_import1, handle_import2);
192*d83cc019SAndroid Build Coastguard Worker
193*d83cc019SAndroid Build Coastguard Worker /* Same for re-importing on the exporting fd. */
194*d83cc019SAndroid Build Coastguard Worker handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd);
195*d83cc019SAndroid Build Coastguard Worker igt_assert_eq_u32(handle, handle_selfimport);
196*d83cc019SAndroid Build Coastguard Worker
197*d83cc019SAndroid Build Coastguard Worker /* close dma_buf, check whether nothing disappears. */
198*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd);
199*d83cc019SAndroid Build Coastguard Worker check_bo(fd1, handle, fd2, handle_import1);
200*d83cc019SAndroid Build Coastguard Worker
201*d83cc019SAndroid Build Coastguard Worker gem_close(fd1, handle);
202*d83cc019SAndroid Build Coastguard Worker check_bo(fd2, handle_import1, fd2, handle_import1);
203*d83cc019SAndroid Build Coastguard Worker
204*d83cc019SAndroid Build Coastguard Worker /* re-import into old exporter */
205*d83cc019SAndroid Build Coastguard Worker dma_buf_fd = prime_handle_to_fd(fd2, handle_import1);
206*d83cc019SAndroid Build Coastguard Worker /* but drop all references to the obj in between */
207*d83cc019SAndroid Build Coastguard Worker gem_close(fd2, handle_import1);
208*d83cc019SAndroid Build Coastguard Worker handle = prime_fd_to_handle(fd1, dma_buf_fd);
209*d83cc019SAndroid Build Coastguard Worker handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
210*d83cc019SAndroid Build Coastguard Worker check_bo(fd1, handle, fd2, handle_import1);
211*d83cc019SAndroid Build Coastguard Worker
212*d83cc019SAndroid Build Coastguard Worker /* Completely rip out exporting fd. */
213*d83cc019SAndroid Build Coastguard Worker close(fd1);
214*d83cc019SAndroid Build Coastguard Worker check_bo(fd2, handle_import1, fd2, handle_import1);
215*d83cc019SAndroid Build Coastguard Worker }
216*d83cc019SAndroid Build Coastguard Worker
thread_fn_reimport_vs_close(void * p)217*d83cc019SAndroid Build Coastguard Worker static void *thread_fn_reimport_vs_close(void *p)
218*d83cc019SAndroid Build Coastguard Worker {
219*d83cc019SAndroid Build Coastguard Worker struct drm_gem_close close_bo;
220*d83cc019SAndroid Build Coastguard Worker int *fds = p;
221*d83cc019SAndroid Build Coastguard Worker int fd = fds[0];
222*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd = fds[1];
223*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
224*d83cc019SAndroid Build Coastguard Worker
225*d83cc019SAndroid Build Coastguard Worker while (!pls_die) {
226*d83cc019SAndroid Build Coastguard Worker handle = prime_fd_to_handle(fd, dma_buf_fd);
227*d83cc019SAndroid Build Coastguard Worker
228*d83cc019SAndroid Build Coastguard Worker close_bo.handle = handle;
229*d83cc019SAndroid Build Coastguard Worker ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
230*d83cc019SAndroid Build Coastguard Worker }
231*d83cc019SAndroid Build Coastguard Worker
232*d83cc019SAndroid Build Coastguard Worker return (void *)0;
233*d83cc019SAndroid Build Coastguard Worker }
234*d83cc019SAndroid Build Coastguard Worker
test_reimport_close_race(void)235*d83cc019SAndroid Build Coastguard Worker static void test_reimport_close_race(void)
236*d83cc019SAndroid Build Coastguard Worker {
237*d83cc019SAndroid Build Coastguard Worker pthread_t *threads;
238*d83cc019SAndroid Build Coastguard Worker int r, i, num_threads;
239*d83cc019SAndroid Build Coastguard Worker int fds[2];
240*d83cc019SAndroid Build Coastguard Worker int obj_count;
241*d83cc019SAndroid Build Coastguard Worker void *status;
242*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
243*d83cc019SAndroid Build Coastguard Worker int fake;
244*d83cc019SAndroid Build Coastguard Worker
245*d83cc019SAndroid Build Coastguard Worker /* Allocate exit handler fds in here so that we dont screw
246*d83cc019SAndroid Build Coastguard Worker * up the counts */
247*d83cc019SAndroid Build Coastguard Worker fake = drm_open_driver(DRIVER_INTEL);
248*d83cc019SAndroid Build Coastguard Worker
249*d83cc019SAndroid Build Coastguard Worker obj_count = igt_get_stable_obj_count(fake);
250*d83cc019SAndroid Build Coastguard Worker
251*d83cc019SAndroid Build Coastguard Worker num_threads = sysconf(_SC_NPROCESSORS_ONLN);
252*d83cc019SAndroid Build Coastguard Worker
253*d83cc019SAndroid Build Coastguard Worker threads = calloc(num_threads, sizeof(pthread_t));
254*d83cc019SAndroid Build Coastguard Worker
255*d83cc019SAndroid Build Coastguard Worker fds[0] = drm_open_driver(DRIVER_INTEL);
256*d83cc019SAndroid Build Coastguard Worker
257*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fds[0], BO_SIZE);
258*d83cc019SAndroid Build Coastguard Worker
259*d83cc019SAndroid Build Coastguard Worker fds[1] = prime_handle_to_fd(fds[0], handle);
260*d83cc019SAndroid Build Coastguard Worker
261*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
262*d83cc019SAndroid Build Coastguard Worker r = pthread_create(&threads[i], NULL,
263*d83cc019SAndroid Build Coastguard Worker thread_fn_reimport_vs_close,
264*d83cc019SAndroid Build Coastguard Worker (void *)(uintptr_t)fds);
265*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(r, 0);
266*d83cc019SAndroid Build Coastguard Worker }
267*d83cc019SAndroid Build Coastguard Worker
268*d83cc019SAndroid Build Coastguard Worker sleep(5);
269*d83cc019SAndroid Build Coastguard Worker
270*d83cc019SAndroid Build Coastguard Worker pls_die = 1;
271*d83cc019SAndroid Build Coastguard Worker
272*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
273*d83cc019SAndroid Build Coastguard Worker pthread_join(threads[i], &status);
274*d83cc019SAndroid Build Coastguard Worker igt_assert(status == 0);
275*d83cc019SAndroid Build Coastguard Worker }
276*d83cc019SAndroid Build Coastguard Worker
277*d83cc019SAndroid Build Coastguard Worker close(fds[0]);
278*d83cc019SAndroid Build Coastguard Worker close(fds[1]);
279*d83cc019SAndroid Build Coastguard Worker
280*d83cc019SAndroid Build Coastguard Worker obj_count = igt_get_stable_obj_count(fake) - obj_count;
281*d83cc019SAndroid Build Coastguard Worker
282*d83cc019SAndroid Build Coastguard Worker igt_info("leaked %i objects\n", obj_count);
283*d83cc019SAndroid Build Coastguard Worker
284*d83cc019SAndroid Build Coastguard Worker close(fake);
285*d83cc019SAndroid Build Coastguard Worker
286*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(obj_count, 0);
287*d83cc019SAndroid Build Coastguard Worker }
288*d83cc019SAndroid Build Coastguard Worker
thread_fn_export_vs_close(void * p)289*d83cc019SAndroid Build Coastguard Worker static void *thread_fn_export_vs_close(void *p)
290*d83cc019SAndroid Build Coastguard Worker {
291*d83cc019SAndroid Build Coastguard Worker struct drm_prime_handle prime_h2f;
292*d83cc019SAndroid Build Coastguard Worker struct drm_gem_close close_bo;
293*d83cc019SAndroid Build Coastguard Worker int fd = (uintptr_t)p;
294*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
295*d83cc019SAndroid Build Coastguard Worker
296*d83cc019SAndroid Build Coastguard Worker while (!pls_die) {
297*d83cc019SAndroid Build Coastguard Worker /* We want to race gem close against prime export on handle one.*/
298*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fd, 4096);
299*d83cc019SAndroid Build Coastguard Worker if (handle != 1)
300*d83cc019SAndroid Build Coastguard Worker gem_close(fd, handle);
301*d83cc019SAndroid Build Coastguard Worker
302*d83cc019SAndroid Build Coastguard Worker /* raw ioctl since we expect this to fail */
303*d83cc019SAndroid Build Coastguard Worker
304*d83cc019SAndroid Build Coastguard Worker /* WTF: for gem_flink_race I've unconditionally used handle == 1
305*d83cc019SAndroid Build Coastguard Worker * here, but with prime it seems to help a _lot_ to use
306*d83cc019SAndroid Build Coastguard Worker * something more random. */
307*d83cc019SAndroid Build Coastguard Worker prime_h2f.handle = 1;
308*d83cc019SAndroid Build Coastguard Worker prime_h2f.flags = DRM_CLOEXEC;
309*d83cc019SAndroid Build Coastguard Worker prime_h2f.fd = -1;
310*d83cc019SAndroid Build Coastguard Worker
311*d83cc019SAndroid Build Coastguard Worker ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_h2f);
312*d83cc019SAndroid Build Coastguard Worker
313*d83cc019SAndroid Build Coastguard Worker close_bo.handle = 1;
314*d83cc019SAndroid Build Coastguard Worker ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
315*d83cc019SAndroid Build Coastguard Worker
316*d83cc019SAndroid Build Coastguard Worker close(prime_h2f.fd);
317*d83cc019SAndroid Build Coastguard Worker }
318*d83cc019SAndroid Build Coastguard Worker
319*d83cc019SAndroid Build Coastguard Worker return (void *)0;
320*d83cc019SAndroid Build Coastguard Worker }
321*d83cc019SAndroid Build Coastguard Worker
test_export_close_race(void)322*d83cc019SAndroid Build Coastguard Worker static void test_export_close_race(void)
323*d83cc019SAndroid Build Coastguard Worker {
324*d83cc019SAndroid Build Coastguard Worker pthread_t *threads;
325*d83cc019SAndroid Build Coastguard Worker int r, i, num_threads;
326*d83cc019SAndroid Build Coastguard Worker int fd;
327*d83cc019SAndroid Build Coastguard Worker int obj_count;
328*d83cc019SAndroid Build Coastguard Worker void *status;
329*d83cc019SAndroid Build Coastguard Worker int fake;
330*d83cc019SAndroid Build Coastguard Worker
331*d83cc019SAndroid Build Coastguard Worker num_threads = sysconf(_SC_NPROCESSORS_ONLN);
332*d83cc019SAndroid Build Coastguard Worker
333*d83cc019SAndroid Build Coastguard Worker threads = calloc(num_threads, sizeof(pthread_t));
334*d83cc019SAndroid Build Coastguard Worker
335*d83cc019SAndroid Build Coastguard Worker /* Allocate exit handler fds in here so that we dont screw
336*d83cc019SAndroid Build Coastguard Worker * up the counts */
337*d83cc019SAndroid Build Coastguard Worker fake = drm_open_driver(DRIVER_INTEL);
338*d83cc019SAndroid Build Coastguard Worker
339*d83cc019SAndroid Build Coastguard Worker obj_count = igt_get_stable_obj_count(fake);
340*d83cc019SAndroid Build Coastguard Worker
341*d83cc019SAndroid Build Coastguard Worker fd = drm_open_driver(DRIVER_INTEL);
342*d83cc019SAndroid Build Coastguard Worker
343*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
344*d83cc019SAndroid Build Coastguard Worker r = pthread_create(&threads[i], NULL,
345*d83cc019SAndroid Build Coastguard Worker thread_fn_export_vs_close,
346*d83cc019SAndroid Build Coastguard Worker (void *)(uintptr_t)fd);
347*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(r, 0);
348*d83cc019SAndroid Build Coastguard Worker }
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker sleep(5);
351*d83cc019SAndroid Build Coastguard Worker
352*d83cc019SAndroid Build Coastguard Worker pls_die = 1;
353*d83cc019SAndroid Build Coastguard Worker
354*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < num_threads; i++) {
355*d83cc019SAndroid Build Coastguard Worker pthread_join(threads[i], &status);
356*d83cc019SAndroid Build Coastguard Worker igt_assert(status == 0);
357*d83cc019SAndroid Build Coastguard Worker }
358*d83cc019SAndroid Build Coastguard Worker
359*d83cc019SAndroid Build Coastguard Worker close(fd);
360*d83cc019SAndroid Build Coastguard Worker
361*d83cc019SAndroid Build Coastguard Worker obj_count = igt_get_stable_obj_count(fake) - obj_count;
362*d83cc019SAndroid Build Coastguard Worker
363*d83cc019SAndroid Build Coastguard Worker igt_info("leaked %i objects\n", obj_count);
364*d83cc019SAndroid Build Coastguard Worker
365*d83cc019SAndroid Build Coastguard Worker close(fake);
366*d83cc019SAndroid Build Coastguard Worker
367*d83cc019SAndroid Build Coastguard Worker igt_assert_eq(obj_count, 0);
368*d83cc019SAndroid Build Coastguard Worker }
369*d83cc019SAndroid Build Coastguard Worker
test_llseek_size(void)370*d83cc019SAndroid Build Coastguard Worker static void test_llseek_size(void)
371*d83cc019SAndroid Build Coastguard Worker {
372*d83cc019SAndroid Build Coastguard Worker int fd, i;
373*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
374*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd;
375*d83cc019SAndroid Build Coastguard Worker
376*d83cc019SAndroid Build Coastguard Worker counter = 0;
377*d83cc019SAndroid Build Coastguard Worker
378*d83cc019SAndroid Build Coastguard Worker fd = drm_open_driver(DRIVER_INTEL);
379*d83cc019SAndroid Build Coastguard Worker
380*d83cc019SAndroid Build Coastguard Worker
381*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < 10; i++) {
382*d83cc019SAndroid Build Coastguard Worker int bufsz = 4096 << i;
383*d83cc019SAndroid Build Coastguard Worker
384*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fd, bufsz);
385*d83cc019SAndroid Build Coastguard Worker dma_buf_fd = prime_handle_to_fd(fd, handle);
386*d83cc019SAndroid Build Coastguard Worker
387*d83cc019SAndroid Build Coastguard Worker gem_close(fd, handle);
388*d83cc019SAndroid Build Coastguard Worker
389*d83cc019SAndroid Build Coastguard Worker igt_assert(prime_get_size(dma_buf_fd) == bufsz);
390*d83cc019SAndroid Build Coastguard Worker
391*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd);
392*d83cc019SAndroid Build Coastguard Worker }
393*d83cc019SAndroid Build Coastguard Worker
394*d83cc019SAndroid Build Coastguard Worker close(fd);
395*d83cc019SAndroid Build Coastguard Worker }
396*d83cc019SAndroid Build Coastguard Worker
test_llseek_bad(void)397*d83cc019SAndroid Build Coastguard Worker static void test_llseek_bad(void)
398*d83cc019SAndroid Build Coastguard Worker {
399*d83cc019SAndroid Build Coastguard Worker int fd;
400*d83cc019SAndroid Build Coastguard Worker uint32_t handle;
401*d83cc019SAndroid Build Coastguard Worker int dma_buf_fd;
402*d83cc019SAndroid Build Coastguard Worker
403*d83cc019SAndroid Build Coastguard Worker counter = 0;
404*d83cc019SAndroid Build Coastguard Worker
405*d83cc019SAndroid Build Coastguard Worker fd = drm_open_driver(DRIVER_INTEL);
406*d83cc019SAndroid Build Coastguard Worker
407*d83cc019SAndroid Build Coastguard Worker
408*d83cc019SAndroid Build Coastguard Worker handle = gem_create(fd, BO_SIZE);
409*d83cc019SAndroid Build Coastguard Worker dma_buf_fd = prime_handle_to_fd(fd, handle);
410*d83cc019SAndroid Build Coastguard Worker
411*d83cc019SAndroid Build Coastguard Worker gem_close(fd, handle);
412*d83cc019SAndroid Build Coastguard Worker
413*d83cc019SAndroid Build Coastguard Worker igt_require(lseek(dma_buf_fd, 0, SEEK_END) >= 0);
414*d83cc019SAndroid Build Coastguard Worker
415*d83cc019SAndroid Build Coastguard Worker igt_assert(lseek(dma_buf_fd, -1, SEEK_END) == -1 && errno == EINVAL);
416*d83cc019SAndroid Build Coastguard Worker igt_assert(lseek(dma_buf_fd, 1, SEEK_SET) == -1 && errno == EINVAL);
417*d83cc019SAndroid Build Coastguard Worker igt_assert(lseek(dma_buf_fd, BO_SIZE, SEEK_SET) == -1 && errno == EINVAL);
418*d83cc019SAndroid Build Coastguard Worker igt_assert(lseek(dma_buf_fd, BO_SIZE + 1, SEEK_SET) == -1 && errno == EINVAL);
419*d83cc019SAndroid Build Coastguard Worker igt_assert(lseek(dma_buf_fd, BO_SIZE - 1, SEEK_SET) == -1 && errno == EINVAL);
420*d83cc019SAndroid Build Coastguard Worker
421*d83cc019SAndroid Build Coastguard Worker close(dma_buf_fd);
422*d83cc019SAndroid Build Coastguard Worker
423*d83cc019SAndroid Build Coastguard Worker close(fd);
424*d83cc019SAndroid Build Coastguard Worker }
425*d83cc019SAndroid Build Coastguard Worker
426*d83cc019SAndroid Build Coastguard Worker igt_main
427*d83cc019SAndroid Build Coastguard Worker {
428*d83cc019SAndroid Build Coastguard Worker struct {
429*d83cc019SAndroid Build Coastguard Worker const char *name;
430*d83cc019SAndroid Build Coastguard Worker void (*fn)(void);
431*d83cc019SAndroid Build Coastguard Worker } tests[] = {
432*d83cc019SAndroid Build Coastguard Worker { "basic-with_one_bo", test_with_one_bo },
433*d83cc019SAndroid Build Coastguard Worker { "basic-with_one_bo_two_files", test_with_one_bo_two_files },
434*d83cc019SAndroid Build Coastguard Worker { "basic-with_two_bos", test_with_two_bos },
435*d83cc019SAndroid Build Coastguard Worker { "basic-with_fd_dup", test_with_fd_dup },
436*d83cc019SAndroid Build Coastguard Worker { "export-vs-gem_close-race", test_export_close_race },
437*d83cc019SAndroid Build Coastguard Worker { "reimport-vs-gem_close-race", test_reimport_close_race },
438*d83cc019SAndroid Build Coastguard Worker { "basic-llseek-size", test_llseek_size },
439*d83cc019SAndroid Build Coastguard Worker { "basic-llseek-bad", test_llseek_bad },
440*d83cc019SAndroid Build Coastguard Worker };
441*d83cc019SAndroid Build Coastguard Worker int i;
442*d83cc019SAndroid Build Coastguard Worker
443*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(tests); i++) {
444*d83cc019SAndroid Build Coastguard Worker igt_subtest(tests[i].name)
445*d83cc019SAndroid Build Coastguard Worker tests[i].fn();
446*d83cc019SAndroid Build Coastguard Worker }
447*d83cc019SAndroid Build Coastguard Worker }
448