lib/igt.cocci: Add stanza for for_each_pipe
[platform/upstream/intel-gpu-tools.git] / tests / prime_self_import.c
1 /*
2  * Copyright © 2012-2013 Intel Corporation
3  *
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:
10  *
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
13  * Software.
14  *
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
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Daniel Vetter <daniel.vetter@ffwll.ch>
25  *
26  */
27
28 /*
29  * Testcase: Check whether prime import/export works on the same device
30  *
31  * ... but with different fds, i.e. the wayland usecase.
32  */
33
34 #define _GNU_SOURCE
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <fcntl.h>
40 #include <inttypes.h>
41 #include <errno.h>
42 #include <sys/stat.h>
43 #include <sys/ioctl.h>
44 #include <pthread.h>
45
46 #include "drm.h"
47 #include "ioctl_wrappers.h"
48 #include "drmtest.h"
49 #include "igt_debugfs.h"
50
51 #define BO_SIZE (16*1024)
52
53 static char counter;
54 volatile int pls_die = 0;
55
56 static void
57 check_bo(int fd1, uint32_t handle1, int fd2, uint32_t handle2)
58 {
59         char *ptr1, *ptr2;
60         int i;
61
62         ptr1 = gem_mmap(fd1, handle1, BO_SIZE, PROT_READ | PROT_WRITE);
63         ptr2 = gem_mmap(fd2, handle2, BO_SIZE, PROT_READ | PROT_WRITE);
64
65         igt_assert(ptr1);
66
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);
71         }
72
73         counter++;
74
75         memset(ptr1, counter, BO_SIZE);
76         igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
77
78         munmap(ptr1, BO_SIZE);
79         munmap(ptr2, BO_SIZE);
80 }
81
82 static void test_with_fd_dup(void)
83 {
84         int fd1, fd2;
85         uint32_t handle, handle_import;
86         int dma_buf_fd1, dma_buf_fd2;
87
88         counter = 0;
89
90         fd1 = drm_open_any();
91         fd2 = drm_open_any();
92
93         handle = gem_create(fd1, BO_SIZE);
94
95         dma_buf_fd1 = prime_handle_to_fd(fd1, handle);
96         gem_close(fd1, handle);
97
98         dma_buf_fd2 = dup(dma_buf_fd1);
99         close(dma_buf_fd1);
100         handle_import = prime_fd_to_handle(fd2, dma_buf_fd2);
101         check_bo(fd2, handle_import, fd2, handle_import);
102
103         close(dma_buf_fd2);
104         check_bo(fd2, handle_import, fd2, handle_import);
105
106         close(fd1);
107         close(fd2);
108 }
109
110 static void test_with_two_bos(void)
111 {
112         int fd1, fd2;
113         uint32_t handle1, handle2, handle_import;
114         int dma_buf_fd;
115
116         counter = 0;
117
118         fd1 = drm_open_any();
119         fd2 = drm_open_any();
120
121         handle1 = gem_create(fd1, BO_SIZE);
122         handle2 = gem_create(fd1, BO_SIZE);
123
124         dma_buf_fd = prime_handle_to_fd(fd1, handle1);
125         handle_import = prime_fd_to_handle(fd2, dma_buf_fd);
126
127         close(dma_buf_fd);
128         gem_close(fd1, handle1);
129
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);
133
134         gem_close(fd1, handle2);
135         close(dma_buf_fd);
136
137         check_bo(fd2, handle_import, fd2, handle_import);
138
139         close(fd1);
140         close(fd2);
141 }
142
143 static void test_with_one_bo_two_files(void)
144 {
145         int fd1, fd2;
146         uint32_t handle_import, handle_open, handle_orig, flink_name;
147         int dma_buf_fd1, dma_buf_fd2;
148
149         fd1 = drm_open_any();
150         fd2 = drm_open_any();
151
152         handle_orig = gem_create(fd1, BO_SIZE);
153         dma_buf_fd1 = prime_handle_to_fd(fd1, handle_orig);
154
155         flink_name = gem_flink(fd1, handle_orig);
156         handle_open = gem_open(fd2, flink_name);
157
158         dma_buf_fd2 = prime_handle_to_fd(fd2, handle_open);
159         handle_import = prime_fd_to_handle(fd2, dma_buf_fd2);
160
161         /* dma-buf selfimporting an flink bo should give the same handle */
162         igt_assert(handle_import == handle_open);
163
164         close(fd1);
165         close(fd2);
166         close(dma_buf_fd1);
167         close(dma_buf_fd2);
168 }
169
170 static void test_with_one_bo(void)
171 {
172         int fd1, fd2;
173         uint32_t handle, handle_import1, handle_import2, handle_selfimport;
174         int dma_buf_fd;
175
176         fd1 = drm_open_any();
177         fd2 = drm_open_any();
178
179         handle = gem_create(fd1, BO_SIZE);
180
181         dma_buf_fd = prime_handle_to_fd(fd1, handle);
182         handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
183
184         check_bo(fd1, handle, fd2, handle_import1);
185
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);
190
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);
194
195         /* close dma_buf, check whether nothing disappears. */
196         close(dma_buf_fd);
197         check_bo(fd1, handle, fd2, handle_import1);
198
199         gem_close(fd1, handle);
200         check_bo(fd2, handle_import1, fd2, handle_import1);
201
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);
209
210         /* Completely rip out exporting fd. */
211         close(fd1);
212         check_bo(fd2, handle_import1, fd2, handle_import1);
213 }
214
215 static int get_object_count(void)
216 {
217         FILE *file;
218         int ret, scanned;
219         int device = drm_get_card();
220         char *path;
221
222         igt_drop_caches_set(DROP_RETIRE);
223
224         ret = asprintf(&path, "/sys/kernel/debug/dri/%d/i915_gem_objects", device);
225         igt_assert(ret != -1);
226
227         file = fopen(path, "r");
228
229         scanned = fscanf(file, "%i objects", &ret);
230         igt_assert(scanned == 1);
231
232         return ret;
233 }
234
235 static void *thread_fn_reimport_vs_close(void *p)
236 {
237         struct drm_gem_close close_bo;
238         int *fds = p;
239         int fd = fds[0];
240         int dma_buf_fd = fds[1];
241         uint32_t handle;
242
243         while (!pls_die) {
244                 handle = prime_fd_to_handle(fd, dma_buf_fd);
245
246                 close_bo.handle = handle;
247                 ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
248         }
249
250         return (void *)0;
251 }
252
253 static void test_reimport_close_race(void)
254 {
255         pthread_t *threads;
256         int r, i, num_threads;
257         int fds[2];
258         int obj_count;
259         void *status;
260         uint32_t handle;
261         int fake;
262
263         /* Allocate exit handler fds in here so that we dont screw
264          * up the counts */
265         fake = drm_open_any();
266
267         obj_count = get_object_count();
268
269         num_threads = sysconf(_SC_NPROCESSORS_ONLN);
270
271         threads = calloc(num_threads, sizeof(pthread_t));
272
273         fds[0] = drm_open_any();
274         igt_assert(fds[0] >= 0);
275
276         handle = gem_create(fds[0], BO_SIZE);
277
278         fds[1] = prime_handle_to_fd(fds[0], handle);
279
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);
284                 igt_assert(r == 0);
285         }
286
287         sleep(5);
288
289         pls_die = 1;
290
291         for (i = 0;  i < num_threads; i++) {
292                 pthread_join(threads[i], &status);
293                 igt_assert(status == 0);
294         }
295
296         close(fds[0]);
297         close(fds[1]);
298
299         obj_count = get_object_count() - obj_count;
300
301         igt_info("leaked %i objects\n", obj_count);
302
303         close(fake);
304
305         igt_assert_cmpint(obj_count, ==, 0);
306 }
307
308 static void *thread_fn_export_vs_close(void *p)
309 {
310         struct drm_prime_handle prime_h2f;
311         struct drm_gem_close close_bo;
312         int fd = (uintptr_t)p;
313         uint32_t handle;
314
315         while (!pls_die) {
316                 /* We want to race gem close against prime export on handle one.*/
317                 handle = gem_create(fd, 4096);
318                 if (handle != 1)
319                         gem_close(fd, handle);
320
321                 /* raw ioctl since we expect this to fail */
322
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;
328                 prime_h2f.fd = -1;
329
330                 ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_h2f);
331
332                 close_bo.handle = 1;
333                 ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close_bo);
334
335                 close(prime_h2f.fd);
336         }
337
338         return (void *)0;
339 }
340
341 static void test_export_close_race(void)
342 {
343         pthread_t *threads;
344         int r, i, num_threads;
345         int fd;
346         int obj_count;
347         void *status;
348
349         obj_count = get_object_count();
350
351         num_threads = sysconf(_SC_NPROCESSORS_ONLN);
352
353         threads = calloc(num_threads, sizeof(pthread_t));
354
355         fd = drm_open_any();
356         igt_assert(fd >= 0);
357
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);
362                 igt_assert(r == 0);
363         }
364
365         sleep(5);
366
367         pls_die = 1;
368
369         for (i = 0;  i < num_threads; i++) {
370                 pthread_join(threads[i], &status);
371                 igt_assert(status == 0);
372         }
373
374         close(fd);
375
376         obj_count = get_object_count() - obj_count;
377
378         igt_info("leaked %i objects\n", obj_count);
379         igt_assert_cmpint(obj_count, ==, 0);
380 }
381
382 static void test_llseek_size(void)
383 {
384         int fd, i;
385         uint32_t handle;
386         int dma_buf_fd;
387
388         counter = 0;
389
390         fd = drm_open_any();
391
392
393         for (i = 0; i < 10; i++) {
394                 int bufsz = 4096 << i;
395
396                 handle = gem_create(fd, bufsz);
397                 dma_buf_fd = prime_handle_to_fd(fd, handle);
398
399                 gem_close(fd, handle);
400
401                 igt_assert(prime_get_size(dma_buf_fd) == bufsz);
402
403                 close(dma_buf_fd);
404         }
405
406         close(fd);
407 }
408
409 static void test_llseek_bad(void)
410 {
411         int fd;
412         uint32_t handle;
413         int dma_buf_fd;
414
415         counter = 0;
416
417         fd = drm_open_any();
418
419
420         handle = gem_create(fd, BO_SIZE);
421         dma_buf_fd = prime_handle_to_fd(fd, handle);
422
423         gem_close(fd, handle);
424
425         igt_require(lseek(dma_buf_fd, 0, SEEK_END) >= 0);
426
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);
432
433         close(dma_buf_fd);
434
435         close(fd);
436 }
437
438 igt_main
439 {
440         struct {
441                 const char *name;
442                 void (*fn)(void);
443         } tests[] = {
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 },
452         };
453         int i;
454
455         for (i = 0; i < ARRAY_SIZE(tests); i++) {
456                 igt_subtest(tests[i].name)
457                         tests[i].fn();
458         }
459 }