Skip to content

Commit 487a42e

Browse files
author
msieben
committed
[mesa3d]: Workaround for leaking file descriptors and interleaving synchronization primitives in v3d.
- Leaking file descriptors render the system inoperable when the thresholds of open file descriptors have been reached. - Implementation of blocking synchronization primitives is best not executed in interleaving execution fashion.
1 parent 88af8e4 commit 487a42e

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
--- a/src/gallium/drivers/v3d/v3d_context.c
2+
+++ b/src/gallium/drivers/v3d/v3d_context.c
3+
@@ -379,6 +379,8 @@
4+
5+
v3d->fd = screen->fd;
6+
7+
+ v3d->fence = NULL;
8+
+
9+
slab_create_child(&v3d->transfer_pool, &screen->transfer_pool);
10+
11+
v3d->uploader = u_upload_create_default(&v3d->base);
12+
--- a/src/gallium/drivers/v3d/v3d_context.h
13+
+++ b/src/gallium/drivers/v3d/v3d_context.h
14+
@@ -555,6 +555,9 @@
15+
uint32_t prim_counts_offset;
16+
struct pipe_debug_callback debug;
17+
/** @} */
18+
+
19+
+ // Custom field to track fence destruction
20+
+ struct v3d_fence * fence;
21+
};
22+
23+
struct v3d_rasterizer_state {
24+
--- a/src/gallium/frontends/dri/dri_drawable.c
25+
+++ b/src/gallium/frontends/dri/dri_drawable.c
26+
@@ -523,14 +523,22 @@
27+
struct pipe_screen *screen = drawable->screen->base.screen;
28+
struct pipe_fence_handle *new_fence = NULL;
29+
30+
+ /* bool */ screen->fence_lock();
31+
+
32+
st->flush(st, flush_flags, &new_fence, args.ctx ? notify_before_flush_cb : NULL, &args);
33+
+ screen->fence_finish(screen, NULL, new_fence, PIPE_TIMEOUT_INFINITE);
34+
+ screen->fence_reference(screen, &new_fence, NULL);
35+
+
36+
+ /* bool */ screen->fence_unlock();
37+
38+
+#ifdef _0
39+
/* throttle on the previous fence */
40+
if (drawable->throttle_fence) {
41+
screen->fence_finish(screen, NULL, drawable->throttle_fence, PIPE_TIMEOUT_INFINITE);
42+
screen->fence_reference(screen, &drawable->throttle_fence, NULL);
43+
}
44+
drawable->throttle_fence = new_fence;
45+
+#endif
46+
}
47+
else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) {
48+
st->flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args);
49+
--- a/src/gallium/include/pipe/p_screen.h
50+
+++ b/src/gallium/include/pipe/p_screen.h
51+
@@ -604,6 +604,10 @@
52+
unsigned int (*get_dmabuf_modifier_planes)(struct pipe_screen *screen,
53+
uint64_t modifier,
54+
enum pipe_format format);
55+
+
56+
+ // (Un)lock the flow create, finish, reference
57+
+ bool (* fence_lock) (void);
58+
+ bool (* fence_unlock) (void);
59+
};
60+
61+
62+
--- a/src/mesa/state_tracker/st_cb_flush.c
63+
+++ b/src/mesa/state_tracker/st_cb_flush.c
64+
@@ -70,6 +70,9 @@
65+
struct pipe_fence_handle *fence = NULL;
66+
67+
st_flush_bitmap_cache(st);
68+
+
69+
+ /* bool */ st->screen->fence_lock ();
70+
+
71+
st_flush(st, &fence, PIPE_FLUSH_ASYNC | PIPE_FLUSH_HINT_FINISH);
72+
73+
if (fence) {
74+
@@ -78,6 +81,8 @@
75+
st->screen->fence_reference(st->screen, &fence, NULL);
76+
}
77+
78+
+ /* bool */ st->screen->fence_unlock ();
79+
+
80+
st_manager_flush_swapbuffers();
81+
}
82+
83+
--- a/src/gallium/drivers/v3d/v3d_fence.c
84+
+++ b/src/gallium/drivers/v3d/v3d_fence.c
85+
@@ -43,8 +43,12 @@
86+
struct v3d_fence {
87+
struct pipe_reference reference;
88+
int fd;
89+
+ struct v3d_context * ctx;
90+
};
91+
92+
+static bool v3d_fence_lock (void);
93+
+static bool v3d_fence_unlock (void);
94+
+
95+
static void
96+
v3d_fence_reference(struct pipe_screen *pscreen,
97+
struct pipe_fence_handle **pp,
98+
@@ -55,8 +59,19 @@
99+
struct v3d_fence *old = *p;
100+
101+
if (pipe_reference(&(*p)->reference, &f->reference)) {
102+
- close(old->fd);
103+
+ /* bool */ v3d_fence_lock ();
104+
+
105+
+ assert (old->ctx != NULL);
106+
+ assert (old->ctx->fence->fd == old->fd || old->ctx->fence->fd == -1);
107+
+
108+
+ old->ctx->fence = NULL;
109+
+
110+
+ /* int */ close(old->fd);
111+
free(old);
112+
+
113+
+ /* bool */ v3d_fence_unlock ();
114+
+
115+
+ fprintf(stderr, "Sync file destructed\n");
116+
}
117+
*p = f;
118+
}
119+
@@ -103,6 +118,19 @@
120+
if (!f)
121+
return NULL;
122+
123+
+ /* bool */ v3d_fence_lock ();
124+
+
125+
+ if (v3d->fence != NULL) {
126+
+ fprintf(stderr, "Sync file iNOT properly destructed\n");
127+
+
128+
+ /* int */ close (v3d->fence->fd);
129+
+ free (v3d->fence);
130+
+
131+
+ v3d->fence = NULL;
132+
+ }
133+
+
134+
+ /* bool */ v3d_fence_unlock ();
135+
+
136+
/* Snapshot the last V3D rendering's out fence. We'd rather have
137+
* another syncobj instead of a sync file, but this is all we get.
138+
* (HandleToFD/FDToHandle just gives you another syncobj ID for the
139+
@@ -115,14 +143,43 @@
140+
return NULL;
141+
}
142+
143+
+ // Update our custom fields in the v3d_context and v3d_fence
144+
+
145+
+ /* bool */ v3d_fence_lock ();
146+
+
147+
+ v3d->fence = f;
148+
+
149+
+ f->ctx = v3d;
150+
+
151+
+ /* bool */ v3d_fence_unlock ();
152+
+
153+
pipe_reference_init(&f->reference, 1);
154+
155+
return f;
156+
}
157+
158+
+pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
159+
+
160+
+/* static */ bool v3d_fence_lock (void)
161+
+{
162+
+ bool ret = pthread_mutex_lock (& mutex) == 0;
163+
+ assert (ret != false);
164+
+ return ret;
165+
+}
166+
+
167+
+/* static */ bool v3d_fence_unlock (void)
168+
+{
169+
+ bool ret = pthread_mutex_unlock (& mutex) == 0;
170+
+ assert (ret != false);
171+
+ return ret;
172+
+}
173+
+
174+
void
175+
v3d_fence_init(struct v3d_screen *screen)
176+
{
177+
screen->base.fence_reference = v3d_fence_reference;
178+
screen->base.fence_finish = v3d_fence_finish;
179+
+
180+
+ screen->base.fence_lock = v3d_fence_lock;
181+
+ screen->base.fence_unlock = v3d_fence_unlock;
182+
}

0 commit comments

Comments
 (0)