2019-06-12 20:08:54 +02:00
|
|
|
#include "shm.h"
|
|
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
#include <stdio.h>
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
#include <string.h>
|
2020-02-25 19:07:23 +01:00
|
|
|
#include <errno.h>
|
2020-03-25 18:26:58 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <limits.h>
|
2019-06-12 20:08:54 +02:00
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/mman.h>
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
#include <sys/time.h>
|
2021-01-19 14:20:55 +00:00
|
|
|
#include <sys/mman.h>
|
2020-02-15 19:46:00 +01:00
|
|
|
#include <fcntl.h>
|
2019-06-12 20:08:54 +02:00
|
|
|
|
2019-08-16 20:40:32 +02:00
|
|
|
#include <pixman.h>
|
|
|
|
|
|
2019-12-01 14:03:24 +01:00
|
|
|
#include <fcft/stride.h>
|
2019-11-17 19:19:55 +01:00
|
|
|
#include <tllist.h>
|
|
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
#define LOG_MODULE "shm"
|
2019-11-02 00:33:37 +01:00
|
|
|
#define LOG_ENABLE_DBG 0
|
2019-06-12 20:08:54 +02:00
|
|
|
#include "log.h"
|
2021-01-15 20:39:45 +00:00
|
|
|
#include "debug.h"
|
2020-08-07 20:42:34 +01:00
|
|
|
#include "macros.h"
|
2020-08-08 20:34:30 +01:00
|
|
|
#include "xmalloc.h"
|
2019-06-12 20:08:54 +02:00
|
|
|
|
2020-10-10 11:29:04 +02:00
|
|
|
#if !defined(MAP_UNINITIALIZED)
|
|
|
|
|
#define MAP_UNINITIALIZED 0
|
|
|
|
|
#endif
|
|
|
|
|
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
#define TIME_SCROLL 0
|
|
|
|
|
|
2020-03-24 17:46:48 +01:00
|
|
|
/*
|
|
|
|
|
* Maximum memfd size allowed.
|
|
|
|
|
*
|
|
|
|
|
* On 64-bit, we could in theory use up to 2GB (wk_shm_create_pool()
|
|
|
|
|
* is limited to int32_t), since we never mmap() the entire region.
|
|
|
|
|
*
|
|
|
|
|
* The compositor is different matter - it needs to mmap() the entire
|
|
|
|
|
* range, and *keep* the mapping for as long as is has buffers
|
|
|
|
|
* referencing it (thus - always). And if we open multiple terminals,
|
|
|
|
|
* then the required address space multiples...
|
|
|
|
|
*
|
|
|
|
|
* That said, 128TB (the total amount of available user address space
|
|
|
|
|
* on 64-bit) is *a lot*; we can fit 67108864 2GB memfds into
|
|
|
|
|
* that. But, let's be conservative for now.
|
|
|
|
|
*
|
|
|
|
|
* On 32-bit the available address space is too small and SHM
|
|
|
|
|
* scrolling is disabled.
|
2020-03-25 20:48:02 +01:00
|
|
|
*
|
|
|
|
|
* Note: this is the _default_ size. It can be overridden by calling
|
|
|
|
|
* shm_set_max_pool_size();
|
2020-03-24 17:46:48 +01:00
|
|
|
*/
|
2020-03-25 20:48:02 +01:00
|
|
|
static off_t max_pool_size = 512 * 1024 * 1024;
|
2020-03-24 17:46:48 +01:00
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
static tll(struct buffer) buffers;
|
|
|
|
|
|
2020-03-22 20:36:15 +01:00
|
|
|
static bool can_punch_hole = false;
|
|
|
|
|
static bool can_punch_hole_initialized = false;
|
|
|
|
|
|
2020-04-18 12:24:40 +02:00
|
|
|
#undef MEASURE_SHM_ALLOCS
|
|
|
|
|
#if defined(MEASURE_SHM_ALLOCS)
|
|
|
|
|
static size_t max_alloced = 0;
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-25 20:48:02 +01:00
|
|
|
void
|
|
|
|
|
shm_set_max_pool_size(off_t _max_pool_size)
|
|
|
|
|
{
|
|
|
|
|
max_pool_size = _max_pool_size;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 00:35:02 +01:00
|
|
|
static void
|
2020-03-24 17:46:48 +01:00
|
|
|
buffer_destroy_dont_close(struct buffer *buf)
|
2019-11-02 00:35:02 +01:00
|
|
|
{
|
2020-06-04 15:39:19 +02:00
|
|
|
if (buf->pix != NULL) {
|
|
|
|
|
for (size_t i = 0; i < buf->pix_instances; i++)
|
|
|
|
|
if (buf->pix[i] != NULL)
|
|
|
|
|
pixman_image_unref(buf->pix[i]);
|
|
|
|
|
}
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
if (buf->wl_buf != NULL)
|
|
|
|
|
wl_buffer_destroy(buf->wl_buf);
|
2020-03-24 17:46:48 +01:00
|
|
|
|
2020-06-04 15:39:19 +02:00
|
|
|
free(buf->pix);
|
2020-03-24 17:46:48 +01:00
|
|
|
buf->pix = NULL;
|
|
|
|
|
buf->wl_buf = NULL;
|
|
|
|
|
buf->mmapped = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
buffer_destroy(struct buffer *buf)
|
|
|
|
|
{
|
|
|
|
|
buffer_destroy_dont_close(buf);
|
2020-03-25 18:26:58 +01:00
|
|
|
if (buf->real_mmapped != MAP_FAILED)
|
|
|
|
|
munmap(buf->real_mmapped, buf->mmap_size);
|
|
|
|
|
if (buf->pool != NULL)
|
|
|
|
|
wl_shm_pool_destroy(buf->pool);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
if (buf->fd >= 0)
|
|
|
|
|
close(buf->fd);
|
2020-03-25 18:26:58 +01:00
|
|
|
|
|
|
|
|
buf->real_mmapped = MAP_FAILED;
|
|
|
|
|
buf->pool = NULL;
|
2020-03-24 17:46:48 +01:00
|
|
|
buf->fd = -1;
|
2019-11-02 00:35:02 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-25 20:48:02 +01:00
|
|
|
void
|
|
|
|
|
shm_fini(void)
|
|
|
|
|
{
|
|
|
|
|
tll_foreach(buffers, it) {
|
|
|
|
|
buffer_destroy(&it->item);
|
|
|
|
|
tll_remove(buffers, it);
|
|
|
|
|
}
|
2020-04-18 12:24:40 +02:00
|
|
|
|
|
|
|
|
#if defined(MEASURE_SHM_ALLOCS) && MEASURE_SHM_ALLOCS
|
|
|
|
|
LOG_INFO("max total allocations was: %zu MB", max_alloced / 1024 / 1024);
|
|
|
|
|
#endif
|
2020-03-25 20:48:02 +01:00
|
|
|
}
|
|
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
static void
|
|
|
|
|
buffer_release(void *data, struct wl_buffer *wl_buffer)
|
|
|
|
|
{
|
|
|
|
|
struct buffer *buffer = data;
|
2020-08-23 07:50:27 +02:00
|
|
|
LOG_DBG("release: cookie=%lx (buf=%p)", buffer->cookie, (void *)buffer);
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(buffer->wl_buf == wl_buffer);
|
|
|
|
|
xassert(buffer->busy);
|
2019-06-12 20:08:54 +02:00
|
|
|
buffer->busy = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct wl_buffer_listener buffer_listener = {
|
|
|
|
|
.release = &buffer_release,
|
|
|
|
|
};
|
|
|
|
|
|
2021-01-21 12:39:51 +01:00
|
|
|
#if __SIZEOF_POINTER__ == 8
|
2020-03-24 17:46:48 +01:00
|
|
|
static size_t
|
|
|
|
|
page_size(void)
|
|
|
|
|
{
|
|
|
|
|
static size_t size = 0;
|
|
|
|
|
if (size == 0) {
|
2020-08-25 19:39:17 +01:00
|
|
|
long n = sysconf(_SC_PAGE_SIZE);
|
|
|
|
|
if (n <= 0) {
|
2020-03-24 17:46:48 +01:00
|
|
|
LOG_ERRNO("failed to get page size");
|
|
|
|
|
size = 4096;
|
2020-08-25 19:39:17 +01:00
|
|
|
} else {
|
|
|
|
|
size = (size_t)n;
|
2020-03-24 17:46:48 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(size > 0);
|
2020-03-24 17:46:48 +01:00
|
|
|
return size;
|
|
|
|
|
}
|
2021-01-19 15:17:38 +00:00
|
|
|
#endif
|
2020-03-24 17:46:48 +01:00
|
|
|
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
static bool
|
2020-03-24 17:46:48 +01:00
|
|
|
instantiate_offset(struct wl_shm *shm, struct buffer *buf, off_t new_offset)
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
{
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(buf->fd >= 0);
|
|
|
|
|
xassert(buf->mmapped == NULL);
|
|
|
|
|
xassert(buf->wl_buf == NULL);
|
|
|
|
|
xassert(buf->pix == NULL);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
|
|
|
|
void *mmapped = MAP_FAILED;
|
|
|
|
|
struct wl_buffer *wl_buf = NULL;
|
2020-08-08 20:34:30 +01:00
|
|
|
pixman_image_t **pix = xcalloc(buf->pix_instances, sizeof(*pix));
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
mmapped = (uint8_t *)buf->real_mmapped + new_offset;
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
|
|
|
|
wl_buf = wl_shm_pool_create_buffer(
|
2020-03-25 18:26:58 +01:00
|
|
|
buf->pool, new_offset, buf->width, buf->height, buf->stride, WL_SHM_FORMAT_ARGB8888);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
if (wl_buf == NULL) {
|
|
|
|
|
LOG_ERR("failed to create SHM buffer");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* One pixman image for each worker thread (do we really need multiple?) */
|
2020-06-04 15:39:19 +02:00
|
|
|
for (size_t i = 0; i < buf->pix_instances; i++) {
|
|
|
|
|
pix[i] = pixman_image_create_bits_no_clear(
|
|
|
|
|
PIXMAN_a8r8g8b8, buf->width, buf->height, (uint32_t *)mmapped, buf->stride);
|
|
|
|
|
if (pix[i] == NULL) {
|
|
|
|
|
LOG_ERR("failed to create pixman image");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf->offset = new_offset;
|
|
|
|
|
buf->mmapped = mmapped;
|
|
|
|
|
buf->wl_buf = wl_buf;
|
|
|
|
|
buf->pix = pix;
|
|
|
|
|
|
|
|
|
|
wl_buffer_add_listener(wl_buf, &buffer_listener, buf);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
err:
|
2020-06-04 15:39:19 +02:00
|
|
|
if (pix != NULL) {
|
|
|
|
|
for (size_t i = 0; i < buf->pix_instances; i++)
|
|
|
|
|
if (pix[i] != NULL)
|
|
|
|
|
pixman_image_unref(pix[i]);
|
|
|
|
|
}
|
|
|
|
|
free(pix);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
if (wl_buf != NULL)
|
|
|
|
|
wl_buffer_destroy(wl_buf);
|
|
|
|
|
|
|
|
|
|
abort();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
struct buffer *
|
2020-06-04 15:39:19 +02:00
|
|
|
shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie, bool scrollable, size_t pix_instances)
|
2019-06-12 20:08:54 +02:00
|
|
|
{
|
2019-11-02 01:27:05 +01:00
|
|
|
/* Purge buffers marked for purging */
|
|
|
|
|
tll_foreach(buffers, it) {
|
|
|
|
|
if (it->item.cookie != cookie)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!it->item.purge)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(!it->item.busy);
|
2019-11-02 01:27:05 +01:00
|
|
|
|
2020-03-18 16:41:38 +01:00
|
|
|
LOG_DBG("cookie=%lx: purging buffer %p (width=%d, height=%d): %zu KB",
|
2020-08-23 07:50:27 +02:00
|
|
|
cookie, (void *)&it->item, it->item.width, it->item.height,
|
2020-03-18 16:41:38 +01:00
|
|
|
it->item.size / 1024);
|
2019-11-02 01:27:05 +01:00
|
|
|
|
|
|
|
|
buffer_destroy(&it->item);
|
|
|
|
|
tll_remove(buffers, it);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 01:31:48 +01:00
|
|
|
tll_foreach(buffers, it) {
|
|
|
|
|
if (it->item.width != width)
|
|
|
|
|
continue;
|
|
|
|
|
if (it->item.height != height)
|
|
|
|
|
continue;
|
|
|
|
|
if (it->item.cookie != cookie)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!it->item.busy) {
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
LOG_DBG("cookie=%lx: re-using buffer from cache (buf=%p)",
|
2020-08-23 07:50:27 +02:00
|
|
|
cookie, (void *)&it->item);
|
2019-11-02 01:31:48 +01:00
|
|
|
it->item.busy = true;
|
|
|
|
|
it->item.purge = false;
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(it->item.pix_instances == pix_instances);
|
2019-11-02 01:31:48 +01:00
|
|
|
return &it->item;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-02 00:35:02 +01:00
|
|
|
/* Purge old buffers associated with this cookie */
|
|
|
|
|
tll_foreach(buffers, it) {
|
|
|
|
|
if (it->item.cookie != cookie)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (it->item.busy)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (it->item.width == width && it->item.height == height)
|
|
|
|
|
continue;
|
|
|
|
|
|
2020-08-23 07:50:27 +02:00
|
|
|
LOG_DBG("cookie=%lx: marking buffer %p for purging", cookie, (void *)&it->item);
|
2019-11-02 01:27:05 +01:00
|
|
|
it->item.purge = true;
|
2019-11-02 00:35:02 +01:00
|
|
|
}
|
|
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
/*
|
|
|
|
|
* No existing buffer available. Create a new one by:
|
|
|
|
|
*
|
|
|
|
|
* 1. open a memory backed "file" with memfd_create()
|
2019-08-16 22:11:22 +02:00
|
|
|
* 2. mmap() the memory file, to be used by the pixman image
|
2019-06-12 20:08:54 +02:00
|
|
|
* 3. create a wayland shm buffer for the same memory file
|
|
|
|
|
*
|
2019-08-16 22:11:22 +02:00
|
|
|
* The pixman image and the wayland buffer are now sharing memory.
|
2019-06-12 20:08:54 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int pool_fd = -1;
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
const int stride = stride_for_format_and_width(PIXMAN_a8r8g8b8, width);
|
|
|
|
|
const size_t size = stride * height;
|
2019-06-12 20:08:54 +02:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
void *real_mmapped = MAP_FAILED;
|
|
|
|
|
struct wl_shm_pool *pool = NULL;
|
|
|
|
|
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
LOG_DBG("cookie=%lx: allocating new buffer: %zu KB", cookie, size / 1024);
|
2019-06-12 20:08:54 +02:00
|
|
|
|
|
|
|
|
/* Backing memory for SHM */
|
2021-01-19 14:20:55 +00:00
|
|
|
#if defined(MEMFD_CREATE)
|
2020-03-25 18:26:58 +01:00
|
|
|
pool_fd = memfd_create("foot-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
2021-01-19 14:20:55 +00:00
|
|
|
#elif defined(__FreeBSD__)
|
|
|
|
|
// memfd_create on FreeBSD 13 is SHM_ANON without sealing support
|
|
|
|
|
pool_fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600);
|
|
|
|
|
#else
|
|
|
|
|
char name[] = "/tmp/foot-wayland-shm-buffer-pool-XXXXXX";
|
|
|
|
|
pool_fd = mkostemp(name, O_CLOEXEC);
|
|
|
|
|
unlink(name);
|
|
|
|
|
#endif
|
2019-06-12 20:08:54 +02:00
|
|
|
if (pool_fd == -1) {
|
|
|
|
|
LOG_ERRNO("failed to create SHM backing memory file");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 12:39:51 +01:00
|
|
|
#if __SIZEOF_POINTER__ == 8
|
2020-03-26 18:04:30 +01:00
|
|
|
off_t initial_offset = scrollable && max_pool_size > 0 ? (max_pool_size / 4) & ~(page_size() - 1) : 0;
|
|
|
|
|
off_t memfd_size = scrollable && max_pool_size > 0 ? max_pool_size : size;
|
2021-01-21 12:39:51 +01:00
|
|
|
#else
|
|
|
|
|
off_t initial_offset = 0;
|
|
|
|
|
off_t memfd_size = size;
|
2020-03-25 18:26:58 +01:00
|
|
|
#endif
|
2020-03-24 17:46:48 +01:00
|
|
|
|
2020-03-25 20:48:02 +01:00
|
|
|
LOG_DBG("memfd-size: %lu, initial offset: %lu", memfd_size, initial_offset);
|
|
|
|
|
|
2020-03-24 17:46:48 +01:00
|
|
|
if (ftruncate(pool_fd, memfd_size) == -1) {
|
2020-03-25 18:26:58 +01:00
|
|
|
LOG_ERRNO("failed to set size of SHM backing memory file");
|
2019-06-12 20:08:54 +02:00
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 20:36:15 +01:00
|
|
|
if (!can_punch_hole_initialized) {
|
|
|
|
|
can_punch_hole_initialized = true;
|
2021-01-21 12:39:51 +01:00
|
|
|
#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE)
|
2020-03-22 20:36:15 +01:00
|
|
|
can_punch_hole = fallocate(
|
|
|
|
|
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
|
2020-03-22 21:04:00 +01:00
|
|
|
|
|
|
|
|
if (!can_punch_hole) {
|
|
|
|
|
LOG_WARN(
|
|
|
|
|
"fallocate(FALLOC_FL_PUNCH_HOLE) not "
|
|
|
|
|
"supported (%s): expect lower performance", strerror(errno));
|
|
|
|
|
}
|
2020-08-11 17:22:12 +02:00
|
|
|
#else
|
|
|
|
|
/* This is mostly to make sure we skip the warning issued
|
|
|
|
|
* above */
|
|
|
|
|
can_punch_hole = false;
|
|
|
|
|
#endif
|
2020-03-22 20:36:15 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
if (scrollable && !can_punch_hole) {
|
|
|
|
|
initial_offset = 0;
|
|
|
|
|
memfd_size = size;
|
|
|
|
|
scrollable = false;
|
2020-03-25 18:32:41 +01:00
|
|
|
|
|
|
|
|
if (ftruncate(pool_fd, memfd_size) < 0) {
|
|
|
|
|
LOG_ERRNO("failed to set size of SHM backing memory file");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
2020-03-25 18:26:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
real_mmapped = mmap(
|
|
|
|
|
NULL, memfd_size, PROT_READ | PROT_WRITE,
|
|
|
|
|
MAP_SHARED | MAP_UNINITIALIZED, pool_fd, 0);
|
|
|
|
|
|
|
|
|
|
if (real_mmapped == MAP_FAILED) {
|
|
|
|
|
LOG_ERRNO("failed to mmap SHM backing memory file");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 14:20:55 +00:00
|
|
|
#if defined(MEMFD_CREATE)
|
2020-03-25 18:30:21 +01:00
|
|
|
/* Seal file - we no longer allow any kind of resizing */
|
|
|
|
|
/* TODO: wayland mmaps(PROT_WRITE), for some unknown reason, hence we cannot use F_SEAL_FUTURE_WRITE */
|
|
|
|
|
if (fcntl(pool_fd, F_ADD_SEALS,
|
|
|
|
|
F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERRNO("failed to seal SHM backing memory file");
|
2020-04-03 20:14:53 +02:00
|
|
|
/* This is not a fatal error */
|
2020-03-25 18:30:21 +01:00
|
|
|
}
|
2021-01-19 14:20:55 +00:00
|
|
|
#endif
|
2020-03-25 18:30:21 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
pool = wl_shm_create_pool(shm, pool_fd, memfd_size);
|
|
|
|
|
if (pool == NULL) {
|
|
|
|
|
LOG_ERR("failed to create SHM pool");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
/* Push to list of available buffers, but marked as 'busy' */
|
|
|
|
|
tll_push_back(
|
|
|
|
|
buffers,
|
|
|
|
|
((struct buffer){
|
2019-11-02 00:33:37 +01:00
|
|
|
.cookie = cookie,
|
2019-06-12 20:08:54 +02:00
|
|
|
.width = width,
|
|
|
|
|
.height = height,
|
2019-08-16 20:40:32 +02:00
|
|
|
.stride = stride,
|
2019-06-12 20:08:54 +02:00
|
|
|
.busy = true,
|
|
|
|
|
.size = size,
|
2020-06-04 15:39:19 +02:00
|
|
|
.pix_instances = pix_instances,
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
.fd = pool_fd,
|
2020-03-25 18:26:58 +01:00
|
|
|
.pool = pool,
|
|
|
|
|
.scrollable = scrollable,
|
|
|
|
|
.real_mmapped = real_mmapped,
|
|
|
|
|
.mmap_size = memfd_size,
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
.offset = 0}
|
2019-06-12 20:08:54 +02:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
struct buffer *ret = &tll_back(buffers);
|
2020-03-24 17:46:48 +01:00
|
|
|
if (!instantiate_offset(shm, ret, initial_offset))
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
goto err;
|
2020-04-18 12:24:40 +02:00
|
|
|
|
|
|
|
|
#if defined(MEASURE_SHM_ALLOCS) && MEASURE_SHM_ALLOCS
|
|
|
|
|
{
|
|
|
|
|
size_t currently_alloced = 0;
|
|
|
|
|
tll_foreach(buffers, it)
|
|
|
|
|
currently_alloced += it->item.size;
|
|
|
|
|
if (currently_alloced > max_alloced)
|
|
|
|
|
max_alloced = currently_alloced;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-06-12 20:08:54 +02:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
err:
|
2020-03-25 18:26:58 +01:00
|
|
|
if (pool != NULL)
|
|
|
|
|
wl_shm_pool_destroy(pool);
|
|
|
|
|
if (real_mmapped != MAP_FAILED)
|
|
|
|
|
munmap(real_mmapped, memfd_size);
|
2019-06-12 20:08:54 +02:00
|
|
|
if (pool_fd != -1)
|
|
|
|
|
close(pool_fd);
|
|
|
|
|
|
2020-03-10 18:02:10 +01:00
|
|
|
/* We don't handle this */
|
|
|
|
|
abort();
|
2019-06-12 20:08:54 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-23 19:31:05 +01:00
|
|
|
bool
|
2020-03-25 18:26:58 +01:00
|
|
|
shm_can_scroll(const struct buffer *buf)
|
2020-03-23 19:31:05 +01:00
|
|
|
{
|
2021-01-21 12:39:51 +01:00
|
|
|
#if __SIZEOF_POINTER__ == 8
|
|
|
|
|
return can_punch_hole && max_pool_size > 0 && buf->scrollable;
|
|
|
|
|
#else
|
2020-03-24 17:46:48 +01:00
|
|
|
/* Not enough virtual address space in 32-bit */
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-21 12:39:51 +01:00
|
|
|
#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE)
|
2020-03-24 17:46:48 +01:00
|
|
|
static bool
|
|
|
|
|
wrap_buffer(struct wl_shm *shm, struct buffer *buf, off_t new_offset)
|
|
|
|
|
{
|
2020-03-25 18:26:58 +01:00
|
|
|
/* We don't allow overlapping offsets */
|
2020-08-07 20:42:34 +01:00
|
|
|
off_t UNUSED diff =
|
2020-03-25 18:26:58 +01:00
|
|
|
new_offset < buf->offset ? buf->offset - new_offset : new_offset - buf->offset;
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(diff > buf->size);
|
2020-03-25 18:26:58 +01:00
|
|
|
|
|
|
|
|
memcpy((uint8_t *)buf->real_mmapped + new_offset, buf->mmapped, buf->size);
|
|
|
|
|
|
|
|
|
|
off_t trim_ofs, trim_len;
|
|
|
|
|
if (new_offset > buf->offset) {
|
|
|
|
|
/* Trim everything *before* the new offset */
|
|
|
|
|
trim_ofs = 0;
|
|
|
|
|
trim_len = new_offset;
|
|
|
|
|
} else {
|
|
|
|
|
/* Trim everything *after* the new buffer location */
|
|
|
|
|
trim_ofs = new_offset + buf->size;
|
|
|
|
|
trim_len = buf->mmap_size - trim_ofs;
|
|
|
|
|
}
|
2020-03-24 17:46:48 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
if (fallocate(
|
|
|
|
|
buf->fd,
|
|
|
|
|
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
|
|
|
|
trim_ofs, trim_len) < 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERRNO("failed to trim SHM backing memory file");
|
2020-03-24 17:46:48 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Re-instantiate pixman+wl_buffer+raw pointersw */
|
|
|
|
|
buffer_destroy_dont_close(buf);
|
|
|
|
|
return instantiate_offset(shm, buf, new_offset);
|
2020-03-23 19:31:05 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-23 21:14:51 +01:00
|
|
|
static bool
|
|
|
|
|
shm_scroll_forward(struct wl_shm *shm, struct buffer *buf, int rows,
|
|
|
|
|
int top_margin, int top_keep_rows,
|
|
|
|
|
int bottom_margin, int bottom_keep_rows)
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
{
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(can_punch_hole);
|
|
|
|
|
xassert(buf->busy);
|
|
|
|
|
xassert(buf->pix);
|
|
|
|
|
xassert(buf->wl_buf);
|
|
|
|
|
xassert(buf->fd >= 0);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
|
|
|
|
LOG_DBG("scrolling %d rows (%d bytes)", rows, rows * buf->stride);
|
|
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
const off_t diff = rows * buf->stride;
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(rows > 0);
|
|
|
|
|
xassert(diff < buf->size);
|
2020-03-24 17:46:48 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
if (buf->offset + diff + buf->size > max_pool_size) {
|
|
|
|
|
LOG_DBG("memfd offset wrap around");
|
2020-03-24 17:46:48 +01:00
|
|
|
if (!wrap_buffer(shm, buf, 0))
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
off_t new_offset = buf->offset + diff;
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(new_offset > buf->offset);
|
|
|
|
|
xassert(new_offset + buf->size <= max_pool_size);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
|
|
|
|
struct timeval time1;
|
|
|
|
|
gettimeofday(&time1, NULL);
|
|
|
|
|
|
2020-03-23 20:45:27 +01:00
|
|
|
struct timeval time2 = time1;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (top_keep_rows > 0) {
|
|
|
|
|
/* Copy current 'top' region to its new location */
|
|
|
|
|
memmove(
|
|
|
|
|
(uint8_t *)buf->mmapped + (top_margin + rows) * buf->stride,
|
|
|
|
|
(uint8_t *)buf->mmapped + (top_margin + 0) * buf->stride,
|
|
|
|
|
top_keep_rows * buf->stride);
|
|
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
|
|
|
|
gettimeofday(&time2, NULL);
|
|
|
|
|
timersub(&time2, &time1, &tot);
|
|
|
|
|
LOG_INFO("memmove (top region): %lds %ldus", tot.tv_sec, tot.tv_usec);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
#endif
|
2020-03-23 20:45:27 +01:00
|
|
|
}
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
|
|
|
|
/* Destroy old objects (they point to the old offset) */
|
2020-03-24 17:46:48 +01:00
|
|
|
buffer_destroy_dont_close(buf);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
/* Free unused memory - everything up until the new offset */
|
|
|
|
|
const off_t trim_ofs = 0;
|
|
|
|
|
const off_t trim_len = new_offset;
|
|
|
|
|
|
|
|
|
|
if (fallocate(
|
|
|
|
|
buf->fd,
|
|
|
|
|
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
|
|
|
|
trim_ofs, trim_len) < 0)
|
2020-03-24 17:46:48 +01:00
|
|
|
{
|
2020-03-25 18:26:58 +01:00
|
|
|
LOG_ERRNO("failed to trim SHM backing memory file");
|
2020-03-24 17:46:48 +01:00
|
|
|
goto err;
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
2020-03-23 20:45:27 +01:00
|
|
|
struct timeval time3;
|
|
|
|
|
gettimeofday(&time3, NULL);
|
|
|
|
|
timersub(&time3, &time2, &tot);
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
LOG_INFO("PUNCH HOLE: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-24 17:46:48 +01:00
|
|
|
/* Re-instantiate pixman+wl_buffer+raw pointersw */
|
2020-03-23 20:45:27 +01:00
|
|
|
bool ret = instantiate_offset(shm, buf, new_offset);
|
|
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
#if TIME_SCROLL
|
|
|
|
|
struct timeval time4;
|
|
|
|
|
gettimeofday(&time4, NULL);
|
|
|
|
|
timersub(&time4, &time3, &tot);
|
|
|
|
|
LOG_INFO("instantiate offset: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-23 20:45:27 +01:00
|
|
|
if (ret && bottom_keep_rows > 0) {
|
|
|
|
|
/* Copy 'bottom' region to its new location */
|
|
|
|
|
memmove(
|
|
|
|
|
(uint8_t *)buf->mmapped + buf->size - (bottom_margin + bottom_keep_rows) * buf->stride,
|
|
|
|
|
(uint8_t *)buf->mmapped + buf->size - (bottom_margin + rows + bottom_keep_rows) * buf->stride,
|
|
|
|
|
bottom_keep_rows * buf->stride);
|
|
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
2020-03-25 18:26:58 +01:00
|
|
|
struct timeval time5;
|
|
|
|
|
gettimeofday(&time5, NULL);
|
2020-03-23 20:45:27 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
timersub(&time5, &time4, &tot);
|
2020-03-23 20:45:27 +01:00
|
|
|
LOG_INFO("memmove (bottom region): %lds %ldus", tot.tv_sec, tot.tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2020-03-24 17:46:48 +01:00
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
abort();
|
|
|
|
|
return false;
|
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.
The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).
Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.
Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.
Some notes:
* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
to drop is large.
* all normal fallocate() usages have been replaced with ftruncate(),
as this is *much* faster. fallocate() guarantees subsequent writes
wont fail. I.e. it actually reserves (disk) space. While it doesn't
allocate on-disk blocks for on-disk files, it *does* zero-initialize
the in-memory blocks. And this is slow. ftruncate() doesn't do this.
TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
|
|
|
}
|
|
|
|
|
|
2020-03-23 21:14:51 +01:00
|
|
|
static bool
|
|
|
|
|
shm_scroll_reverse(struct wl_shm *shm, struct buffer *buf, int rows,
|
|
|
|
|
int top_margin, int top_keep_rows,
|
|
|
|
|
int bottom_margin, int bottom_keep_rows)
|
|
|
|
|
{
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(rows > 0);
|
2020-03-23 21:14:51 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
const off_t diff = rows * buf->stride;
|
2020-03-24 17:46:48 +01:00
|
|
|
if (diff > buf->offset) {
|
2020-03-25 18:26:58 +01:00
|
|
|
LOG_DBG("memfd offset reverse wrap-around");
|
2020-03-24 17:46:48 +01:00
|
|
|
if (!wrap_buffer(shm, buf, (max_pool_size - buf->size) & ~(page_size() - 1)))
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
2020-03-23 21:14:51 +01:00
|
|
|
|
2020-03-24 17:46:48 +01:00
|
|
|
off_t new_offset = buf->offset - diff;
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(new_offset < buf->offset);
|
|
|
|
|
xassert(new_offset <= max_pool_size);
|
2020-03-23 21:14:51 +01:00
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
|
|
|
|
struct timeval time0;
|
|
|
|
|
gettimeofday(&time0, NULL);
|
|
|
|
|
|
|
|
|
|
struct timeval tot;
|
|
|
|
|
struct timeval time1 = time0;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (bottom_keep_rows > 0) {
|
|
|
|
|
/* Copy 'bottom' region to its new location */
|
|
|
|
|
memmove(
|
|
|
|
|
(uint8_t *)buf->mmapped + buf->size - (bottom_margin + rows + bottom_keep_rows) * buf->stride,
|
|
|
|
|
(uint8_t *)buf->mmapped + buf->size - (bottom_margin + bottom_keep_rows) * buf->stride,
|
|
|
|
|
bottom_keep_rows * buf->stride);
|
|
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
|
|
|
|
gettimeofday(&time1, NULL);
|
|
|
|
|
timersub(&time1, &time0, &tot);
|
|
|
|
|
LOG_INFO("memmove (bottom region): %lds %ldus", tot.tv_sec, tot.tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Destroy old objects (they point to the old offset) */
|
2020-03-24 17:46:48 +01:00
|
|
|
buffer_destroy_dont_close(buf);
|
2020-03-23 21:14:51 +01:00
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
/* Free unused memory - everything after the relocated buffer */
|
|
|
|
|
const off_t trim_ofs = new_offset + buf->size;
|
|
|
|
|
const off_t trim_len = buf->mmap_size - trim_ofs;
|
|
|
|
|
|
|
|
|
|
if (fallocate(
|
|
|
|
|
buf->fd,
|
|
|
|
|
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
|
|
|
|
trim_ofs, trim_len) < 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_ERRNO("failed to trim SHM backing memory");
|
2020-03-24 17:46:48 +01:00
|
|
|
goto err;
|
2020-03-23 21:14:51 +01:00
|
|
|
}
|
|
|
|
|
#if TIME_SCROLL
|
|
|
|
|
struct timeval time2;
|
|
|
|
|
gettimeofday(&time2, NULL);
|
|
|
|
|
timersub(&time2, &time1, &tot);
|
2020-03-25 18:26:58 +01:00
|
|
|
LOG_INFO("fallocate: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
2020-03-23 21:14:51 +01:00
|
|
|
#endif
|
|
|
|
|
|
2020-03-24 17:46:48 +01:00
|
|
|
/* Re-instantiate pixman+wl_buffer+raw pointers */
|
2020-03-23 21:14:51 +01:00
|
|
|
bool ret = instantiate_offset(shm, buf, new_offset);
|
|
|
|
|
|
2020-03-25 18:26:58 +01:00
|
|
|
#if TIME_SCROLL
|
|
|
|
|
struct timeval time3;
|
|
|
|
|
gettimeofday(&time3, NULL);
|
|
|
|
|
timersub(&time3, &time2, &tot);
|
|
|
|
|
LOG_INFO("instantiate offset: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-23 21:14:51 +01:00
|
|
|
if (ret && top_keep_rows > 0) {
|
|
|
|
|
/* Copy current 'top' region to its new location */
|
|
|
|
|
memmove(
|
|
|
|
|
(uint8_t *)buf->mmapped + (top_margin + 0) * buf->stride,
|
|
|
|
|
(uint8_t *)buf->mmapped + (top_margin + rows) * buf->stride,
|
|
|
|
|
top_keep_rows * buf->stride);
|
|
|
|
|
|
|
|
|
|
#if TIME_SCROLL
|
2020-03-25 18:26:58 +01:00
|
|
|
struct timeval time4;
|
|
|
|
|
gettimeofday(&time4, NULL);
|
|
|
|
|
timersub(&time4, &time2, &tot);
|
2020-03-23 21:14:51 +01:00
|
|
|
LOG_INFO("memmove (top region): %lds %ldus", tot.tv_sec, tot.tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2020-03-24 17:46:48 +01:00
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
abort();
|
|
|
|
|
return false;
|
2020-03-23 21:14:51 +01:00
|
|
|
}
|
shm: disable fallocate optimization if not supported
shm.c:301:26: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
can_punch_hole = fallocate(
^
shm.c:302:22: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
^
shm.c:302:45: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
^
shm.c:432:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:434:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:434:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:501:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:503:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:503:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:597:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:599:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:599:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
2021-01-19 15:22:51 +00:00
|
|
|
#endif /* FALLOC_FL_PUNCH_HOLE */
|
2020-03-23 21:14:51 +01:00
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows,
|
|
|
|
|
int top_margin, int top_keep_rows,
|
|
|
|
|
int bottom_margin, int bottom_keep_rows)
|
|
|
|
|
{
|
2021-01-21 12:39:51 +01:00
|
|
|
#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE)
|
2020-03-26 18:04:30 +01:00
|
|
|
if (!shm_can_scroll(buf))
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(rows != 0);
|
2020-03-23 21:14:51 +01:00
|
|
|
return rows > 0
|
|
|
|
|
? shm_scroll_forward(shm, buf, rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows)
|
|
|
|
|
: shm_scroll_reverse(shm, buf, -rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows);
|
shm: disable fallocate optimization if not supported
shm.c:301:26: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
can_punch_hole = fallocate(
^
shm.c:302:22: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
^
shm.c:302:45: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
pool_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1) == 0;
^
shm.c:432:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:434:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:434:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:501:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:503:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:503:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:597:9: error: implicit declaration of function 'fallocate' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (fallocate(
^
shm.c:599:13: error: use of undeclared identifier 'FALLOC_FL_PUNCH_HOLE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
shm.c:599:36: error: use of undeclared identifier 'FALLOC_FL_KEEP_SIZE'
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
^
2021-01-19 15:22:51 +00:00
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
2020-03-23 21:14:51 +01:00
|
|
|
}
|
|
|
|
|
|
2020-12-04 18:42:16 +01:00
|
|
|
void
|
2019-11-02 00:49:00 +01:00
|
|
|
shm_purge(struct wl_shm *shm, unsigned long cookie)
|
|
|
|
|
{
|
|
|
|
|
LOG_DBG("cookie=%lx: purging all buffers", cookie);
|
|
|
|
|
|
|
|
|
|
/* Purge old buffers associated with this cookie */
|
|
|
|
|
tll_foreach(buffers, it) {
|
|
|
|
|
if (it->item.cookie != cookie)
|
|
|
|
|
continue;
|
|
|
|
|
|
2021-01-16 20:16:00 +00:00
|
|
|
xassert(!it->item.busy);
|
2019-11-02 00:49:00 +01:00
|
|
|
|
|
|
|
|
buffer_destroy(&it->item);
|
|
|
|
|
tll_remove(buffers, it);
|
|
|
|
|
}
|
|
|
|
|
}
|