1 /*
2 * Copyright © 2014 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 <[email protected]>
25 */
26
27 #include "igt.h"
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <drm.h>
35 #include <i915_drm.h>
36 #include <xf86drm.h>
37 #include <intel_bufmgr.h>
38 #include <errno.h>
39 #include <pthread.h>
40 #include <unistd.h>
41 #include <sys/syscall.h>
42
43
44 int fd;
45 drm_intel_bufmgr *bufmgr;
46 int fd1;
47 drm_intel_bufmgr *bufmgr1;
48
49 bool use_flink;
50
new_buffers(void)51 static void new_buffers(void)
52 {
53 unsigned int *buf1;
54 drm_intel_bo *bo1, *bo2;
55
56
57 bo1 = drm_intel_bo_alloc(bufmgr, "buf1",16384, 4096);
58 igt_assert(bo1);
59 drm_intel_bo_map(bo1, 1);
60 bo2 = drm_intel_bo_alloc(bufmgr, "buf2", 16384, 4096);
61 igt_assert(bo2);
62 drm_intel_bo_map(bo2, 1);
63
64 buf1 = (unsigned int *)bo1->virtual;
65 igt_assert(buf1);
66 memset(buf1, 0, 16384);
67 buf1[4000]=0x05000000;
68
69 drm_intel_bo_exec(bo1, 16384, NULL, 0,0);
70 drm_intel_bo_wait_rendering(bo1);
71
72 drm_intel_bo_unmap( bo1 );
73 drm_intel_bo_unreference(bo1);
74
75 drm_intel_bo_unmap( bo2 );
76 drm_intel_bo_unreference(bo2);
77 }
78
test_surfaces(drm_intel_bo * bo_shared)79 static void test_surfaces(drm_intel_bo *bo_shared)
80 {
81 drm_intel_bo * bo;
82 int loop=2;
83
84 while(loop--) {
85 if (use_flink) {
86 uint32_t name;
87 drm_intel_bo_flink(bo_shared, &name);
88 bo = drm_intel_bo_gem_create_from_name(bufmgr,
89 "shared resource",
90 name);
91 } else {
92 int prime_fd;
93
94 drm_intel_bo_gem_export_to_prime(bo_shared, &prime_fd);
95 bo = drm_intel_bo_gem_create_from_prime(bufmgr,
96 prime_fd, 4096);
97 close(prime_fd);
98 }
99
100 igt_assert(bo);
101 new_buffers();
102 drm_intel_bo_unreference(bo);
103 }
104 }
105
start_test(void)106 static void start_test(void)
107 {
108 int i;
109
110 for (i=0; i < 16384; i++)
111 {
112 drm_intel_bo * bo_shared;
113
114 bo_shared = drm_intel_bo_alloc(bufmgr1, "buf-shared",16384, 4096);
115 test_surfaces(bo_shared);
116 drm_intel_bo_unreference(bo_shared);
117 }
118 }
119
test_thread(void * par)120 static void * test_thread(void * par)
121 {
122 #ifdef __linux__
123 igt_debug("start %ld\n", (long) gettid());
124 #else
125 igt_debug("start %ld\n", (long) pthread_self());
126 #endif
127 start_test();
128
129 return NULL;
130 }
131
132 struct import_race_thread_data {
133 int prime_fd;
134 uint32_t flink_name;
135 unsigned int stop;
136 pthread_mutex_t mutex;
137 };
138
139 /*
140 * Attempt to import the bo. It is possible that GEM_CLOSE was already called
141 * in different thread and from i915 point of view the handle is no longer
142 * valid (thus create_from_prime/name should fail).
143 */
import_close_thread(void * data)144 static void *import_close_thread(void *data)
145 {
146 struct import_race_thread_data *t = (struct import_race_thread_data *)data;
147 drm_intel_bo *bo;
148 pthread_mutex_lock(&t->mutex);
149 while (!t->stop) {
150 pthread_mutex_unlock(&t->mutex);
151 bo = NULL;
152 if (use_flink)
153 bo = drm_intel_bo_gem_create_from_name(bufmgr, "buf-shared", t->flink_name);
154 else {
155 pthread_mutex_lock(&t->mutex);
156 if (t->prime_fd != -1) {
157 bo = drm_intel_bo_gem_create_from_prime(bufmgr, t->prime_fd, 4096);
158 pthread_mutex_unlock(&t->mutex);
159 }
160 else
161 /* Lock should be held on entering the loop */
162 continue;
163 }
164
165 if (bo == NULL) {
166 /*
167 * If the bo is NULL it means that we've unreferenced in other
168 * thread - therefore we should expect ENOENT
169 */
170 igt_assert_eq(errno, ENOENT);
171 } else {
172 drm_intel_bo_unreference(bo);
173 }
174
175 pthread_mutex_lock(&t->mutex);
176 }
177 pthread_mutex_unlock(&t->mutex);
178
179 return NULL;
180 }
181
182 /*
183 * It is possible to race between unreference of the underlying BO and importing
184 * it from prime_fd/name. Verify that the behaviour of libdrm is consistent for
185 * prime/flink.
186 */
test_import_close_race(void)187 static void test_import_close_race(void)
188 {
189 pthread_t t;
190 drm_intel_bo *bo;
191 struct import_race_thread_data t_data;
192
193 memset(&t_data, 0, sizeof(t_data));
194 pthread_mutex_init(&t_data.mutex, NULL);
195 t_data.prime_fd = -1;
196
197 igt_assert_eq(pthread_create(&t, NULL, import_close_thread , &t_data), 0);
198
199 igt_until_timeout(15) {
200 bo = drm_intel_bo_alloc(bufmgr, "buf-shared", 4096, 4096);
201 igt_assert(bo != NULL);
202 /*
203 * We setup the test in such way, that create_from_* can race between
204 * unreference. If we're using prime, prime_fd is always a valid fd.
205 */
206 if (use_flink)
207 igt_assert_eq(drm_intel_bo_flink(bo, &(t_data.flink_name)), 0);
208 else {
209 pthread_mutex_lock(&t_data.mutex);
210 igt_assert_eq(drm_intel_bo_gem_export_to_prime(bo, &(t_data.prime_fd)), 0);
211 igt_assert_neq(t_data.prime_fd, -1);
212 pthread_mutex_unlock(&t_data.mutex);
213 }
214
215 drm_intel_bo_unreference(bo);
216
217 pthread_mutex_lock(&t_data.mutex);
218 close(t_data.prime_fd);
219 t_data.prime_fd = -1;
220 pthread_mutex_unlock(&t_data.mutex);
221 }
222
223 pthread_mutex_lock(&t_data.mutex);
224 t_data.stop = 1;
225 pthread_mutex_unlock(&t_data.mutex);
226
227 pthread_join(t, NULL);
228 pthread_mutex_destroy(&t_data.mutex);
229 }
230
231 pthread_t test_thread_id1;
232 pthread_t test_thread_id2;
233 pthread_t test_thread_id3;
234 pthread_t test_thread_id4;
235
236 igt_main {
237 igt_fixture {
238 fd1 = drm_open_driver(DRIVER_INTEL);
239 igt_assert(fd1 >= 0);
240 bufmgr1 = drm_intel_bufmgr_gem_init(fd1, 8 *1024);
241 igt_assert(bufmgr1);
242
243 drm_intel_bufmgr_gem_enable_reuse(bufmgr1);
244
245 fd = drm_open_driver(DRIVER_INTEL);
246 igt_assert(fd >= 0);
247 bufmgr = drm_intel_bufmgr_gem_init(fd, 8 *1024);
248 igt_assert(bufmgr);
249
250 drm_intel_bufmgr_gem_enable_reuse(bufmgr);
251 }
252
253 igt_subtest("import-close-race-flink") {
254 use_flink = true;
255 test_import_close_race();
256 }
257
258 igt_subtest("import-close-race-prime") {
259 use_flink = false;
260 test_import_close_race();
261 }
262
263 igt_subtest("flink") {
264 use_flink = true;
265
266 pthread_create(&test_thread_id1, NULL, test_thread, NULL);
267 pthread_create(&test_thread_id2, NULL, test_thread, NULL);
268 pthread_create(&test_thread_id3, NULL, test_thread, NULL);
269 pthread_create(&test_thread_id4, NULL, test_thread, NULL);
270
271 pthread_join(test_thread_id1, NULL);
272 pthread_join(test_thread_id2, NULL);
273 pthread_join(test_thread_id3, NULL);
274 pthread_join(test_thread_id4, NULL);
275 }
276
277 igt_subtest("prime") {
278 use_flink = false;
279
280 pthread_create(&test_thread_id1, NULL, test_thread, NULL);
281 pthread_create(&test_thread_id2, NULL, test_thread, NULL);
282 pthread_create(&test_thread_id3, NULL, test_thread, NULL);
283 pthread_create(&test_thread_id4, NULL, test_thread, NULL);
284
285 pthread_join(test_thread_id1, NULL);
286 pthread_join(test_thread_id2, NULL);
287 pthread_join(test_thread_id3, NULL);
288 pthread_join(test_thread_id4, NULL);
289 }
290 }
291