Removed
Link Here
|
1 |
--- src/wayland-shm.c.orig 2020-02-11 23:46:03 UTC |
2 |
+++ src/wayland-shm.c |
3 |
@@ -32,6 +32,8 @@ |
4 |
|
5 |
#include "config.h" |
6 |
|
7 |
+#include "../config.h" |
8 |
+ |
9 |
#include <stdbool.h> |
10 |
#include <stdio.h> |
11 |
#include <stdlib.h> |
12 |
@@ -64,6 +66,9 @@ struct wl_shm_pool { |
13 |
int32_t size; |
14 |
int32_t new_size; |
15 |
bool sigbus_is_impossible; |
16 |
+#ifdef HAVE_SYS_UCRED_H |
17 |
+ int fd; |
18 |
+#endif |
19 |
}; |
20 |
|
21 |
struct wl_shm_buffer { |
22 |
@@ -81,15 +86,24 @@ struct wl_shm_sigbus_data { |
23 |
int fallback_mapping_used; |
24 |
}; |
25 |
|
26 |
+static void *mremap_compat_maymove(void *, size_t, size_t, int, int, int); |
27 |
+ |
28 |
static void |
29 |
shm_pool_finish_resize(struct wl_shm_pool *pool) |
30 |
{ |
31 |
void *data; |
32 |
+ int fd = -1; |
33 |
|
34 |
if (pool->size == pool->new_size) |
35 |
return; |
36 |
|
37 |
- data = mremap(pool->data, pool->size, pool->new_size, MREMAP_MAYMOVE); |
38 |
+#ifdef HAVE_SYS_UCRED_H |
39 |
+ fd = pool->fd; |
40 |
+#endif |
41 |
+ |
42 |
+ data = mremap_compat_maymove(pool->data, pool->size, pool->new_size, |
43 |
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd); |
44 |
+ |
45 |
if (data == MAP_FAILED) { |
46 |
wl_resource_post_error(pool->resource, |
47 |
WL_SHM_ERROR_INVALID_FD, |
48 |
@@ -115,6 +129,10 @@ shm_pool_unref(struct wl_shm_pool *pool, bool external |
49 |
if (pool->internal_refcount + pool->external_refcount) |
50 |
return; |
51 |
|
52 |
+#ifdef HAVE_SYS_UCRED_H |
53 |
+ close(pool->fd); |
54 |
+#endif |
55 |
+ |
56 |
munmap(pool->data, pool->size); |
57 |
free(pool); |
58 |
} |
59 |
@@ -228,6 +246,73 @@ shm_pool_destroy(struct wl_client *client, struct wl_r |
60 |
wl_resource_destroy(resource); |
61 |
} |
62 |
|
63 |
+#ifdef HAVE_MREMAP |
64 |
+static void * |
65 |
+mremap_compat_maymove(void *old_address, size_t old_size, size_t new_size, |
66 |
+ int old_prot, int old_flags, int old_fd) |
67 |
+{ |
68 |
+ return mremap(old_address, old_size, new_size, MREMAP_MAYMOVE); |
69 |
+} |
70 |
+#else |
71 |
+static void * |
72 |
+mremap_compat_maymove(void *old_address, size_t old_size, size_t new_size, |
73 |
+ int old_prot, int old_flags, int old_fd) |
74 |
+{ |
75 |
+ /* FreeBSD doesn't support mremap() yet, so we have to emulate it. |
76 |
+ * This assumes MREMAP_MAYMOVE is the only flag in use. */ |
77 |
+ if (new_size == old_size) { |
78 |
+ return old_address; |
79 |
+ } else if (new_size < old_size) { |
80 |
+ /* Shrinking: munmap() the spare region. */ |
81 |
+ munmap(old_address + old_size, new_size - old_size); |
82 |
+ return old_address; |
83 |
+ } else { |
84 |
+ void *ret; |
85 |
+ |
86 |
+ /* Growing. Try and mmap() the extra region at the end of |
87 |
+ * our existing allocation. If that gets mapped in the |
88 |
+ * wrong place, fall back to mmap()ing an entirely new |
89 |
+ * region of new_size and copying the data across. */ |
90 |
+ ret = mmap(old_address + old_size, new_size - old_size, |
91 |
+ old_prot, old_flags, old_fd, 0); |
92 |
+ |
93 |
+/* FIXME TODO: msync() before munmap()? */ |
94 |
+ if (ret == MAP_FAILED) { |
95 |
+ /* Total failure! */ |
96 |
+ return ret; |
97 |
+ } else if (ret == old_address + old_size) { |
98 |
+ /* Success. */ |
99 |
+ return old_address; |
100 |
+ } else if (ret != old_address + old_size) { |
101 |
+ /* Partial failure. Fall back to mapping an |
102 |
+ * entirely new region. Unmap the region we |
103 |
+ * just mapped first. */ |
104 |
+ munmap(ret, new_size - old_size); |
105 |
+ |
106 |
+ /* Map an entirely new region. */ |
107 |
+ ret = mmap(NULL, new_size, |
108 |
+ old_prot, old_flags, old_fd, 0); |
109 |
+ if (ret == MAP_FAILED) { |
110 |
+ /* Total failure! */ |
111 |
+ return ret; |
112 |
+ } |
113 |
+ |
114 |
+ /* Copy the old data across. Implicit assumption |
115 |
+ * that the old and new regions don't overlap. */ |
116 |
+ memcpy(ret, old_address, old_size); |
117 |
+ |
118 |
+ /* Unmap the old region. */ |
119 |
+ munmap(old_address, old_size); |
120 |
+ |
121 |
+ return ret; |
122 |
+ } |
123 |
+ } |
124 |
+ |
125 |
+ /* Unreachable. */ |
126 |
+ return MAP_FAILED; |
127 |
+} |
128 |
+#endif |
129 |
+ |
130 |
static void |
131 |
shm_pool_resize(struct wl_client *client, struct wl_resource *resource, |
132 |
int32_t size) |
133 |
@@ -300,7 +385,14 @@ shm_create_pool(struct wl_client *client, struct wl_re |
134 |
strerror(errno)); |
135 |
goto err_free; |
136 |
} |
137 |
+ |
138 |
+#ifdef HAVE_SYS_UCRED_H |
139 |
+ /* We need to keep the FD around on FreeBSD so we can implement |
140 |
+ * mremap(). See: mremap_compat_maymove(). */ |
141 |
+ pool->fd = fd; |
142 |
+#else |
143 |
close(fd); |
144 |
+#endif |
145 |
|
146 |
pool->resource = |
147 |
wl_resource_create(client, &wl_shm_pool_interface, 1, id); |