xref: /aosp_15_r20/external/igt-gpu-tools/tests/prime_self_import.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
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