"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/wayland-shm.c" between
wayland-1.17.0.tar.xz and wayland-1.18.0.tar.xz

About: Wayland is a computer display server protocol for a compositor to talk to its clients and a library for Linux implementing that protocol.

wayland-shm.c  (wayland-1.17.0.tar.xz):wayland-shm.c  (wayland-1.18.0.tar.xz)
skipping to change at line 33 skipping to change at line 33
* SOFTWARE. * SOFTWARE.
* *
* Authors: * Authors:
* Kristian Høgsberg <krh@bitplanet.net> * Kristian Høgsberg <krh@bitplanet.net>
* Benjamin Franzke <benjaminfranzke@googlemail.com> * Benjamin Franzke <benjaminfranzke@googlemail.com>
* *
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include <signal.h> #include <signal.h>
#include <pthread.h> #include <pthread.h>
#include <errno.h>
#include <fcntl.h>
#include "wayland-util.h" #include "wayland-util.h"
#include "wayland-private.h" #include "wayland-private.h"
#include "wayland-server.h" #include "wayland-server.h"
/* This once_t is used to synchronize installing the SIGBUS handler /* This once_t is used to synchronize installing the SIGBUS handler
* and creating the TLS key. This will be done in the first call * and creating the TLS key. This will be done in the first call
* wl_shm_buffer_begin_access which can happen from any thread */ * wl_shm_buffer_begin_access which can happen from any thread */
static pthread_once_t wl_shm_sigbus_once = PTHREAD_ONCE_INIT; static pthread_once_t wl_shm_sigbus_once = PTHREAD_ONCE_INIT;
static pthread_key_t wl_shm_sigbus_data_key; static pthread_key_t wl_shm_sigbus_data_key;
static struct sigaction wl_shm_old_sigbus_action; static struct sigaction wl_shm_old_sigbus_action;
struct wl_shm_pool { struct wl_shm_pool {
struct wl_resource *resource; struct wl_resource *resource;
int internal_refcount; int internal_refcount;
int external_refcount; int external_refcount;
char *data; char *data;
int32_t size; int32_t size;
int32_t new_size; int32_t new_size;
bool sigbus_is_impossible;
}; };
struct wl_shm_buffer { struct wl_shm_buffer {
struct wl_resource *resource; struct wl_resource *resource;
int32_t width, height; int32_t width, height;
int32_t stride; int32_t stride;
uint32_t format; uint32_t format;
int offset; int offset;
struct wl_shm_pool *pool; struct wl_shm_pool *pool;
}; };
skipping to change at line 261 skipping to change at line 266
shm_pool_create_buffer, shm_pool_create_buffer,
shm_pool_destroy, shm_pool_destroy,
shm_pool_resize shm_pool_resize
}; };
static void static void
shm_create_pool(struct wl_client *client, struct wl_resource *resource, shm_create_pool(struct wl_client *client, struct wl_resource *resource,
uint32_t id, int fd, int32_t size) uint32_t id, int fd, int32_t size)
{ {
struct wl_shm_pool *pool; struct wl_shm_pool *pool;
int seals;
if (size <= 0) { if (size <= 0) {
wl_resource_post_error(resource, wl_resource_post_error(resource,
WL_SHM_ERROR_INVALID_STRIDE, WL_SHM_ERROR_INVALID_STRIDE,
"invalid size (%d)", size); "invalid size (%d)", size);
goto err_close; goto err_close;
} }
pool = malloc(sizeof *pool); pool = malloc(sizeof *pool);
if (pool == NULL) { if (pool == NULL) {
wl_client_post_no_memory(client); wl_client_post_no_memory(client);
goto err_close; goto err_close;
} }
#ifdef HAVE_MEMFD_CREATE
seals = fcntl(fd, F_GET_SEALS);
if (seals == -1)
seals = 0;
pool->sigbus_is_impossible = (seals & F_SEAL_SHRINK) ? true : false;
#else
pool->sigbus_is_impossible = false;
#endif
pool->internal_refcount = 1; pool->internal_refcount = 1;
pool->external_refcount = 0; pool->external_refcount = 0;
pool->size = size; pool->size = size;
pool->new_size = size; pool->new_size = size;
pool->data = mmap(NULL, size, pool->data = mmap(NULL, size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (pool->data == MAP_FAILED) { if (pool->data == MAP_FAILED) {
wl_resource_post_error(resource, wl_resource_post_error(resource,
WL_SHM_ERROR_INVALID_FD, WL_SHM_ERROR_INVALID_FD,
"failed mmap fd %d: %m", fd); "failed mmap fd %d: %s", fd,
strerror(errno));
goto err_free; goto err_free;
} }
close(fd); close(fd);
pool->resource = pool->resource =
wl_resource_create(client, &wl_shm_pool_interface, 1, id); wl_resource_create(client, &wl_shm_pool_interface, 1, id);
if (!pool->resource) { if (!pool->resource) {
wl_client_post_no_memory(client); wl_client_post_no_memory(client);
munmap(pool->data, pool->size); munmap(pool->data, pool->size);
free(pool); free(pool);
skipping to change at line 571 skipping to change at line 587
* buffer from multiple threads. * buffer from multiple threads.
* *
* \memberof wl_shm_buffer * \memberof wl_shm_buffer
*/ */
WL_EXPORT void WL_EXPORT void
wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer) wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
{ {
struct wl_shm_pool *pool = buffer->pool; struct wl_shm_pool *pool = buffer->pool;
struct wl_shm_sigbus_data *sigbus_data; struct wl_shm_sigbus_data *sigbus_data;
if (pool->sigbus_is_impossible)
return;
pthread_once(&wl_shm_sigbus_once, init_sigbus_data_key); pthread_once(&wl_shm_sigbus_once, init_sigbus_data_key);
sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key); sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
if (sigbus_data == NULL) { if (sigbus_data == NULL) {
sigbus_data = zalloc(sizeof *sigbus_data); sigbus_data = zalloc(sizeof *sigbus_data);
if (sigbus_data == NULL) if (sigbus_data == NULL)
return; return;
pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data); pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
} }
skipping to change at line 603 skipping to change at line 622
* This should be called after wl_shm_buffer_begin_access once the * This should be called after wl_shm_buffer_begin_access once the
* buffer is no longer being accessed. If a SIGBUS signal was * buffer is no longer being accessed. If a SIGBUS signal was
* generated in-between these two calls then the resource for the * generated in-between these two calls then the resource for the
* given buffer will be sent an error. * given buffer will be sent an error.
* *
* \memberof wl_shm_buffer * \memberof wl_shm_buffer
*/ */
WL_EXPORT void WL_EXPORT void
wl_shm_buffer_end_access(struct wl_shm_buffer *buffer) wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
{ {
struct wl_shm_sigbus_data *sigbus_data = struct wl_shm_pool *pool = buffer->pool;
pthread_getspecific(wl_shm_sigbus_data_key); struct wl_shm_sigbus_data *sigbus_data;
if (pool->sigbus_is_impossible)
return;
sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
assert(sigbus_data && sigbus_data->access_count >= 1); assert(sigbus_data && sigbus_data->access_count >= 1);
if (--sigbus_data->access_count == 0) { if (--sigbus_data->access_count == 0) {
if (sigbus_data->fallback_mapping_used) { if (sigbus_data->fallback_mapping_used) {
wl_resource_post_error(buffer->resource, wl_resource_post_error(buffer->resource,
WL_SHM_ERROR_INVALID_FD, WL_SHM_ERROR_INVALID_FD,
"error accessing SHM buffer"); "error accessing SHM buffer");
sigbus_data->fallback_mapping_used = 0; sigbus_data->fallback_mapping_used = 0;
} }
 End of changes. 9 change blocks. 
3 lines changed or deleted 26 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)