I'm not sure about the need for this solution, so it's a **DRAFT**. For me it is an academic interest to check whether atomic locks will give advantages over pthread_mutex in games. First impressions are that games have become smoother, but need to think about tests that can actually be measured.
From: Grigory Vasilyev h0tc0d3@gmail.com
--- configure.ac | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/configure.ac b/configure.ac index 4448e781366..39ed7e74150 100644 --- a/configure.ac +++ b/configure.ac @@ -897,26 +897,26 @@ This is an error since --enable-archs=$wine_arch was requested.])]) continue fi
- AS_VAR_PUSHDEF([wine_cv_crosscc_c99],[ac_cv_${wine_arch}_crosscc_c99]) - AC_MSG_CHECKING([for $CC option to enable C99 features]) - AC_CACHE_VAL([wine_cv_crosscc_c99], - [AS_VAR_SET([wine_cv_crosscc_c99],[no]) - for arg in '' '-std=gnu99' '-D__STDC__' + AS_VAR_PUSHDEF([wine_cv_crosscc_c17],[ac_cv_${wine_arch}_crosscc_c17]) + AC_MSG_CHECKING([for $CC option to enable c17 features]) + AC_CACHE_VAL([wine_cv_crosscc_c17], + [AS_VAR_SET([wine_cv_crosscc_c17],[no]) + for arg in '' '-std=gnu17' '-D__STDC__' do test -z "$arg" || CC="$CC $arg" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([$ac_c_conftest_c99_program])], - [AS_VAR_SET([wine_cv_crosscc_c99],[$arg])], - [AS_VAR_SET([wine_cv_crosscc_c99],[no])]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([$ac_c_conftest_c17_program])], + [AS_VAR_SET([wine_cv_crosscc_c17],[$arg])], + [AS_VAR_SET([wine_cv_crosscc_c17],[no])]) AS_VAR_COPY([CC],[${wine_arch}_CC]) - AS_VAR_IF([wine_cv_crosscc_c99],[no],[],[break]) + AS_VAR_IF([wine_cv_crosscc_c17],[no],[],[break]) done]) - AS_VAR_COPY([res],[wine_cv_crosscc_c99]) - AS_VAR_POPDEF([wine_cv_crosscc_c99]) + AS_VAR_COPY([res],[wine_cv_crosscc_c17]) + AS_VAR_POPDEF([wine_cv_crosscc_c17]) case "x$res" in x) AC_MSG_RESULT([none needed]) ;; xno) AC_MSG_RESULT([unsupported]) AS_VAR_SET_IF([enable_archs], - [AC_MSG_ERROR([$wine_arch PE cross-compiler supporting C99 not found. + [AC_MSG_ERROR([$wine_arch PE cross-compiler supporting c17 not found. This is an error since --enable-archs=$wine_arch was requested.])]) continue ;;
From: Grigory Vasilyev h0tc0d3@gmail.com
--- dlls/msxml3/domdoc.c | 4 ++-- dlls/msxml3/main.c | 3 ++- dlls/msxml3/msxml_private.h | 2 +- dlls/msxml3/schema.c | 4 ++-- dlls/msxml3/selection.c | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 2acbffc0a88..e95b5313c16 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -26,7 +26,7 @@ #include <libxml/parser.h> #include <libxml/xmlerror.h> #include <libxml/xpathInternals.h> -# include <libxml/xmlsave.h> +#include <libxml/xmlsave.h> #include <libxml/SAX2.h> #include <libxml/parserInternals.h>
@@ -502,7 +502,7 @@ static void LIBXML2_LOG_CALLBACK sax_warning(void* ctx, char const* msg, ...) va_end(ap); }
-static void sax_serror(void* ctx, xmlErrorPtr err) +static void sax_serror(void* ctx, xmlError* err) { LIBXML2_CALLBACK_SERROR(doparse, err); } diff --git a/dlls/msxml3/main.c b/dlls/msxml3/main.c index 5e8de1676cf..8f9565d7000 100644 --- a/dlls/msxml3/main.c +++ b/dlls/msxml3/main.c @@ -22,6 +22,7 @@ #define COBJMACROS
#include <stdarg.h> +#include <libxml/globals.h> #include <libxml/parser.h> #include <libxml/xmlerror.h> #include <libxslt/pattern.h> @@ -77,7 +78,7 @@ void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, wine_dbg_log(dbcl, &__wine_dbch_msxml, caller, "%s", buff); }
-void wineXmlCallbackError(char const* caller, xmlErrorPtr err) +void wineXmlCallbackError(char const* caller, xmlError* err) { enum __wine_debug_class dbcl;
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 54f54995c76..05f162c3303 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -165,7 +165,7 @@ extern MSXML_VERSION xmldoc_version( xmlDocPtr doc ); extern HRESULT XMLElement_create( xmlNodePtr node, LPVOID *ppObj, BOOL own );
extern void wineXmlCallbackLog(char const* caller, xmlErrorLevel lvl, char const* msg, va_list ap); -extern void wineXmlCallbackError(char const* caller, xmlErrorPtr err); +extern void wineXmlCallbackError(char const* caller, xmlError* err);
#define LIBXML2_LOG_CALLBACK WINAPIV __WINE_PRINTF_ATTR(2,3)
diff --git a/dlls/msxml3/schema.c b/dlls/msxml3/schema.c index b6b790d9894..8be448ebf4b 100644 --- a/dlls/msxml3/schema.c +++ b/dlls/msxml3/schema.c @@ -243,7 +243,7 @@ static void LIBXML2_LOG_CALLBACK parser_warning(void* ctx, char const* msg, ...) va_end(ap); }
-static void parser_serror(void* ctx, xmlErrorPtr err) +static void parser_serror(void* ctx, xmlError* err) { LIBXML2_CALLBACK_SERROR(Schema_parse, err); } @@ -273,7 +273,7 @@ static void LIBXML2_LOG_CALLBACK validate_warning(void* ctx, char const* msg, .. va_end(ap); }
-static void validate_serror(void* ctx, xmlErrorPtr err) +static void validate_serror(void* ctx, xmlError* err) { LIBXML2_CALLBACK_SERROR(Schema_validate_tree, err); } diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index f94b17379d9..aa7d2864907 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -756,7 +756,7 @@ static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs) xmlFree(arg2); }
-static void query_serror(void* ctx, xmlErrorPtr err) +static void query_serror(void* ctx, xmlError* err) { LIBXML2_CALLBACK_SERROR(domselection_create, err); }
From: Grigory Vasilyev h0tc0d3@gmail.com
--- dlls/winewayland.drv/display.c | 4 +-- dlls/winewayland.drv/opengl.c | 38 ++++++++++----------- dlls/winewayland.drv/vulkan.c | 6 ++-- dlls/winewayland.drv/wayland.c | 16 ++++----- dlls/winewayland.drv/wayland_keyboard.c | 44 ++++++++++++------------- dlls/winewayland.drv/wayland_output.c | 12 +++---- dlls/winewayland.drv/wayland_pointer.c | 40 +++++++++++----------- dlls/winewayland.drv/wayland_surface.c | 25 +++++++++----- dlls/winewayland.drv/waylanddrv.h | 42 ++++++++++++++++++++--- dlls/winewayland.drv/window.c | 40 +++++++++++----------- dlls/winewayland.drv/window_surface.c | 4 +-- 11 files changed, 155 insertions(+), 116 deletions(-)
diff --git a/dlls/winewayland.drv/display.c b/dlls/winewayland.drv/display.c index 9b4ebe7cdc1..14056aa279d 100644 --- a/dlls/winewayland.drv/display.c +++ b/dlls/winewayland.drv/display.c @@ -275,7 +275,7 @@ UINT WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manage
wl_array_init(&output_info_array);
- pthread_mutex_lock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.output_mutex);
wl_list_for_each(output, &process_wayland.output_list, link) { @@ -300,7 +300,7 @@ UINT WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manage
wl_array_release(&output_info_array);
- pthread_mutex_unlock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.output_mutex);
return STATUS_SUCCESS; } diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 994154968b3..6f0043cd28a 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -74,7 +74,7 @@ DECL_FUNCPTR(eglSwapInterval); DECL_FUNCPTR(glClear); #undef DECL_FUNCPTR
-static pthread_mutex_t gl_object_mutex = PTHREAD_MUTEX_INITIALIZER; +static WINEWAYLAND_RESOURCE_TYPE gl_object_mutex = WINEWAYLAND_RESOURCE_INIT; static struct list gl_drawables = LIST_INIT(gl_drawables); static struct list gl_contexts = LIST_INIT(gl_contexts);
@@ -120,10 +120,10 @@ static struct wayland_gl_drawable *wayland_gl_drawable_get(HWND hwnd) { struct wayland_gl_drawable *ret;
- pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex); if ((ret = find_drawable_for_hwnd(hwnd))) ret = wayland_gl_drawable_acquire(ret); - pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex);
return ret; } @@ -141,7 +141,7 @@ static void wayland_gl_drawable_release(struct wayland_gl_drawable *gl) if (wayland_client_surface_release(gl->client) && wayland_surface) wayland_surface->client = NULL;
- if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex); + if (wayland_surface) WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex); }
free(gl); @@ -174,7 +174,7 @@ static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int for wayland_surface->window.client_rect.top; if (client_width == 0 || client_height == 0) client_width = client_height = 1; - pthread_mutex_unlock(&wayland_surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex); } else if ((wayland_surface = wayland_surface_create(0))) { @@ -227,7 +227,7 @@ static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *ne { struct wayland_gl_drawable *old;
- pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex);
if ((old = find_drawable_for_hwnd(hwnd))) list_remove(&old->entry); if (new) list_add_head(&gl_drawables, &new->entry); @@ -237,7 +237,7 @@ static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *ne new->swap_interval = old->swap_interval; }
- pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex);
if (old) wayland_gl_drawable_release(old); } @@ -260,7 +260,7 @@ static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl)
wl_egl_window_resize(gl->wl_egl_window, client_width, client_height, 0, 0);
- pthread_mutex_unlock(&wayland_surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex); } }
@@ -281,7 +281,7 @@ static void wayland_gl_drawable_sync_surface_state(struct wayland_gl_drawable *g wl_surface_commit(wayland_surface->wl_surface); }
- pthread_mutex_unlock(&wayland_surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex); }
static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd, @@ -303,7 +303,7 @@ static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd, * perform any pending resizes before calling it. */ if (draw) wayland_gl_drawable_sync_size(draw);
- pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex);
ret = p_eglMakeCurrent(egl_display, draw ? draw->surface : EGL_NO_SURFACE, @@ -325,7 +325,7 @@ static BOOL wgl_context_make_current(struct wgl_context *ctx, HWND draw_hwnd, old_read = read; }
- pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex);
if (old_draw) wayland_gl_drawable_release(old_draw); if (old_read) wayland_gl_drawable_release(old_read); @@ -400,7 +400,7 @@ static void wgl_context_refresh(struct wgl_context *ctx) BOOL refresh = FALSE; struct wayland_gl_drawable *old_draw = NULL, *old_read = NULL;
- pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex);
if (ctx->new_draw) { @@ -422,7 +422,7 @@ static void wgl_context_refresh(struct wgl_context *ctx) if (ctx->draw) p_eglSwapInterval(egl_display, ctx->draw->swap_interval); }
- pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex);
if (old_draw) wayland_gl_drawable_release(old_draw); if (old_read) wayland_gl_drawable_release(old_read); @@ -492,9 +492,9 @@ static struct wgl_context *create_context(HDC hdc, struct wgl_context *share, share ? share->context : EGL_NO_CONTEXT, ctx->attribs);
- pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex); list_add_head(&gl_contexts, &ctx->entry); - pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex);
TRACE("ctx=%p egl_context=%p\n", ctx, ctx->context);
@@ -535,9 +535,9 @@ static struct wgl_context *wayland_wglCreateContextAttribsARB(HDC hdc,
static BOOL wayland_wglDeleteContext(struct wgl_context *ctx) { - pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex); list_remove(&ctx->entry); - pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex); p_eglDestroyContext(egl_display, ctx->context); if (ctx->draw) wayland_gl_drawable_release(ctx->draw); if (ctx->read) wayland_gl_drawable_release(ctx->read); @@ -696,12 +696,12 @@ static BOOL wayland_wglSwapIntervalEXT(int interval)
/* Lock to protect against concurrent access to drawable swap_interval * from wayland_update_gl_drawable */ - pthread_mutex_lock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_LOCK(&gl_object_mutex); if ((ret = p_eglSwapInterval(egl_display, interval))) ctx->draw->swap_interval = interval; else RtlSetLastWin32Error(ERROR_DC_NOT_FOUND); - pthread_mutex_unlock(&gl_object_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&gl_object_mutex);
return ret; } diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 16084175013..31f8bccbcb3 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -73,7 +73,7 @@ static void wine_vk_surface_destroy(struct wayland_client_surface *client) wayland_surface->client = NULL; }
- if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex); + if (wayland_surface) WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex); }
static VkResult wayland_vulkan_surface_create(HWND hwnd, VkInstance instance, VkSurfaceKHR *surface, void **private) @@ -93,7 +93,7 @@ static VkResult wayland_vulkan_surface_create(HWND hwnd, VkInstance instance, Vk }
client = wayland_surface_get_client(wayland_surface); - pthread_mutex_unlock(&wayland_surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex);
if (!client) { @@ -153,7 +153,7 @@ static void wayland_vulkan_surface_presented(HWND hwnd, VkResult result) wl_surface_commit(wayland_surface->wl_surface); }
- pthread_mutex_unlock(&wayland_surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&wayland_surface->mutex); } }
diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index c94b35e173c..c1d6816ec85 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -34,11 +34,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
struct wayland process_wayland = { - .seat.mutex = PTHREAD_MUTEX_INITIALIZER, - .keyboard.mutex = PTHREAD_MUTEX_INITIALIZER, - .pointer.mutex = PTHREAD_MUTEX_INITIALIZER, + .seat.mutex = WINEWAYLAND_RESOURCE_INIT, + .keyboard.mutex = WINEWAYLAND_RESOURCE_INIT, + .pointer.mutex = WINEWAYLAND_RESOURCE_INIT, .output_list = {&process_wayland.output_list, &process_wayland.output_list}, - .output_mutex = PTHREAD_MUTEX_INITIALIZER + .output_mutex = WINEWAYLAND_RESOURCE_INIT };
/********************************************************************** @@ -137,12 +137,12 @@ static void registry_handle_global(void *data, struct wl_registry *registry, WARN("Only a single seat is currently supported, ignoring additional seats.\n"); return; } - pthread_mutex_lock(&seat->mutex); + WINEWAYLAND_RESOURCE_LOCK(&seat->mutex); seat->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, version < 5 ? version : 5); seat->global_id = id; wl_seat_add_listener(seat->wl_seat, &seat_listener, NULL); - pthread_mutex_unlock(&seat->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&seat->mutex); } else if (strcmp(interface, "wp_viewporter") == 0) { @@ -189,11 +189,11 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist { TRACE("removing seat\n"); if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); - pthread_mutex_lock(&seat->mutex); + WINEWAYLAND_RESOURCE_LOCK(&seat->mutex); wl_seat_release(seat->wl_seat); seat->wl_seat = NULL; seat->global_id = 0; - pthread_mutex_unlock(&seat->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&seat->mutex); } }
diff --git a/dlls/winewayland.drv/wayland_keyboard.c b/dlls/winewayland.drv/wayland_keyboard.c index bdef56e8f0c..f1e16b98c3b 100644 --- a/dlls/winewayland.drv/wayland_keyboard.c +++ b/dlls/winewayland.drv/wayland_keyboard.c @@ -69,7 +69,7 @@ struct layout }; };
-static pthread_mutex_t xkb_layouts_mutex = PTHREAD_MUTEX_INITIALIZER; +static WINEWAYLAND_RESOURCE_TYPE xkb_layouts_mutex = WINEWAYLAND_RESOURCE_INIT; static struct list xkb_layouts = LIST_INIT(xkb_layouts);
/* These are only used from the wayland event thread and don't need locking */ @@ -578,7 +578,7 @@ static void set_current_xkb_group(xkb_layout_index_t xkb_group) struct layout *layout; HKL hkl;
- pthread_mutex_lock(&xkb_layouts_mutex); + WINEWAYLAND_RESOURCE_LOCK(&xkb_layouts_mutex);
LIST_FOR_EACH_ENTRY(layout, &xkb_layouts, struct layout, entry) if (layout->xkb_group == xkb_group) break; @@ -590,7 +590,7 @@ static void set_current_xkb_group(xkb_layout_index_t xkb_group) hkl = keyboard_hkl; }
- pthread_mutex_unlock(&xkb_layouts_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&xkb_layouts_mutex);
if (hkl == keyboard_hkl) return; keyboard_hkl = hkl; @@ -670,9 +670,9 @@ static HWND wayland_keyboard_get_focused_hwnd(void) struct wayland_keyboard *keyboard = &process_wayland.keyboard; HWND hwnd;
- pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); hwnd = keyboard->focused_hwnd; - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex);
return hwnd; } @@ -710,7 +710,7 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, return; }
- pthread_mutex_lock(&xkb_layouts_mutex); + WINEWAYLAND_RESOURCE_LOCK(&xkb_layouts_mutex);
LIST_FOR_EACH_ENTRY_SAFE(entry, next, &xkb_layouts, struct layout, entry) { @@ -737,14 +737,14 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard, add_xkb_layout(buffer, xkb_keymap, xkb_group, lang); }
- pthread_mutex_unlock(&xkb_layouts_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&xkb_layouts_mutex);
if ((xkb_state = xkb_state_new(xkb_keymap))) { - pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); xkb_state_unref(keyboard->xkb_state); keyboard->xkb_state = xkb_state; - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex);
set_current_xkb_group(0); } @@ -767,9 +767,9 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, hwnd = wl_surface_get_user_data(wl_surface); TRACE("serial=%u hwnd=%p\n", serial, hwnd);
- pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); keyboard->focused_hwnd = hwnd; - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex);
NtUserPostMessage(keyboard->focused_hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/, (LPARAM)keyboard_hkl); @@ -782,7 +782,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard, * are in the same non-current thread. */ if (surface->window.managed) NtUserPostMessage(hwnd, WM_WAYLAND_SET_FOREGROUND, 0, 0); - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); } }
@@ -799,10 +799,10 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard, hwnd = wl_surface_get_user_data(wl_surface); TRACE("serial=%u hwnd=%p\n", serial, hwnd);
- pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); if (keyboard->focused_hwnd == hwnd) keyboard->focused_hwnd = NULL; - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex);
/* The spec for the leave event tells us to treat all keys as released, * and for any key repetition to stop. */ @@ -857,10 +857,10 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboar TRACE("serial=%u mods_depressed=%#x mods_latched=%#x mods_locked=%#x xkb_group=%d stub!\n", serial, mods_depressed, mods_latched, mods_locked, xkb_group);
- pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); xkb_state_update_mask(keyboard->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, xkb_group); - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex);
set_current_xkb_group(xkb_group);
@@ -917,10 +917,10 @@ void wayland_keyboard_init(struct wl_keyboard *wl_keyboard) }
NtUserCallOneParam(TRUE, NtUserCallOneParam_SetKeyboardAutoRepeat); - pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); keyboard->wl_keyboard = wl_keyboard; keyboard->xkb_context = xkb_context; - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex); wl_keyboard_add_listener(keyboard->wl_keyboard, &keyboard_listener, NULL); }
@@ -931,7 +931,7 @@ void wayland_keyboard_deinit(void) { struct wayland_keyboard *keyboard = &process_wayland.keyboard;
- pthread_mutex_lock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_LOCK(&keyboard->mutex); if (keyboard->wl_keyboard) { wl_keyboard_destroy(keyboard->wl_keyboard); @@ -947,7 +947,7 @@ void wayland_keyboard_deinit(void) xkb_state_unref(keyboard->xkb_state); keyboard->xkb_state = NULL; } - pthread_mutex_unlock(&keyboard->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&keyboard->mutex);
if (rxkb_context) { @@ -965,14 +965,14 @@ const KBDTABLES *WAYLAND_KbdLayerDescriptor(HKL hkl)
TRACE("hkl=%p\n", hkl);
- pthread_mutex_lock(&xkb_layouts_mutex); + WINEWAYLAND_RESOURCE_LOCK(&xkb_layouts_mutex);
LIST_FOR_EACH_ENTRY(layout, &xkb_layouts, struct layout, entry) if (hkl == get_layout_hkl(layout, LOWORD(hkl))) break; if (&layout->entry == &xkb_layouts) layout = NULL; else xkb_layout_addref(layout);
- pthread_mutex_unlock(&xkb_layouts_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&xkb_layouts_mutex);
if (!layout) { diff --git a/dlls/winewayland.drv/wayland_output.c b/dlls/winewayland.drv/wayland_output.c index f76881a1770..498cbf8b698 100644 --- a/dlls/winewayland.drv/wayland_output.c +++ b/dlls/winewayland.drv/wayland_output.c @@ -133,7 +133,7 @@ static void wayland_output_done(struct wayland_output *output) struct wayland_output_mode *mode;
/* Update current state from pending state. */ - pthread_mutex_lock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.output_mutex);
if (output->pending_flags & WAYLAND_OUTPUT_CHANGED_MODES) { @@ -177,7 +177,7 @@ static void wayland_output_done(struct wayland_output *output) output->current.logical_h = output->current.current_mode->height; }
- pthread_mutex_unlock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.output_mutex);
TRACE("name=%s logical=%d,%d+%dx%d\n", output->current.name, output->current.logical_x, output->current.logical_y, @@ -343,9 +343,9 @@ BOOL wayland_output_create(uint32_t id, uint32_t version) if (process_wayland.zxdg_output_manager_v1) wayland_output_use_xdg_extension(output);
- pthread_mutex_lock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.output_mutex); wl_list_insert(process_wayland.output_list.prev, &output->link); - pthread_mutex_unlock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.output_mutex);
return TRUE;
@@ -367,9 +367,9 @@ static void wayland_output_state_deinit(struct wayland_output_state *state) */ void wayland_output_destroy(struct wayland_output *output) { - pthread_mutex_lock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.output_mutex); wl_list_remove(&output->link); - pthread_mutex_unlock(&process_wayland.output_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.output_mutex);
wayland_output_state_deinit(&output->pending); wayland_output_state_deinit(&output->current); diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 1d8acaeabd2..a3aa8799b9c 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -39,9 +39,9 @@ static HWND wayland_pointer_get_focused_hwnd(void) struct wayland_pointer *pointer = &process_wayland.pointer; HWND hwnd;
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); hwnd = pointer->focused_hwnd; - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex);
return hwnd; } @@ -72,7 +72,7 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy) if (screen.y >= window_rect->bottom) screen.y = window_rect->bottom - 1; else if (screen.y < window_rect->top) screen.y = window_rect->top;
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex);
/* Hardware input events are in physical coordinates. */ if (!NtUserLogicalToPerMonitorDPIPhysicalPoint(hwnd, &screen)) return; @@ -116,10 +116,10 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
TRACE("hwnd=%p\n", hwnd);
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); pointer->focused_hwnd = hwnd; pointer->enter_serial = serial; - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex);
/* The cursor is undefined at every enter, so we set it again with * the latest information we have. */ @@ -140,10 +140,10 @@ static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
TRACE("hwnd=%p\n", wl_surface_get_user_data(wl_surface));
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); pointer->focused_hwnd = NULL; pointer->enter_serial = 0; - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex); }
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, @@ -178,10 +178,10 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
if (state == WL_POINTER_BUTTON_STATE_RELEASED) input.mi.dwFlags <<= 1;
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); pointer->button_serial = state == WL_POINTER_BUTTON_STATE_PRESSED ? serial : 0; - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex);
TRACE("hwnd=%p button=%#x state=%u\n", hwnd, button, state);
@@ -270,7 +270,7 @@ static void relative_pointer_v1_relative_motion(void *data, wl_fixed_to_double(dy), (int *)&screen.x, (int *)&screen.y);
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex);
/* We clip the relative motion within the window rectangle so that * the NtUserLogicalToPerMonitorDPIPhysicalPoint calls later succeed. @@ -329,11 +329,11 @@ void wayland_pointer_init(struct wl_pointer *wl_pointer) { struct wayland_pointer *pointer = &process_wayland.pointer;
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); pointer->wl_pointer = wl_pointer; pointer->focused_hwnd = NULL; pointer->enter_serial = 0; - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex); wl_pointer_add_listener(pointer->wl_pointer, &pointer_listener, NULL); }
@@ -341,7 +341,7 @@ void wayland_pointer_deinit(void) { struct wayland_pointer *pointer = &process_wayland.pointer;
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); if (pointer->zwp_confined_pointer_v1) { zwp_confined_pointer_v1_destroy(pointer->zwp_confined_pointer_v1); @@ -361,7 +361,7 @@ void wayland_pointer_deinit(void) pointer->wl_pointer = NULL; pointer->focused_hwnd = NULL; pointer->enter_serial = 0; - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex); }
/*********************************************************************** @@ -680,14 +680,14 @@ static void wayland_set_cursor(HWND hwnd, HCURSOR hcursor, BOOL use_hcursor) if (use_hcursor) surface->hcursor = hcursor; else hcursor = surface->hcursor; use_hcursor = TRUE; - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); } else { scale = 1.0; }
- pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); if (pointer->focused_hwnd == hwnd) { if (use_hcursor) wayland_pointer_update_cursor_buffer(hcursor, scale); @@ -700,7 +700,7 @@ static void wayland_set_cursor(HWND hwnd, HCURSOR hcursor, BOOL use_hcursor) wl_display_flush(process_wayland.wl_display); reapply_clip = TRUE; } - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex);
/* Reapply cursor clip since cursor visibility affects pointer constraint * behavior. */ @@ -911,17 +911,17 @@ BOOL WAYLAND_ClipCursor(const RECT *clip, BOOL reset) wl_surface = surface->wl_surface; if (clip) wayland_surface_calc_confine(surface, clip, &confine_rect); covers_vscreen = wayland_surface_client_covers_vscreen(surface); - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); }
/* Since we are running in the context of the foreground thread we know * that the wl_surface of the foreground HWND will not be invalidated, * so we can access it without having the surface lock. */ - pthread_mutex_lock(&pointer->mutex); + WINEWAYLAND_RESOURCE_LOCK(&pointer->mutex); wayland_pointer_update_constraint(wl_surface, (clip && wl_surface) ? &confine_rect : NULL, covers_vscreen); - pthread_mutex_unlock(&pointer->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&pointer->mutex);
wl_display_flush(process_wayland.wl_display);
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 39c3976cdfd..a2dd248da2c 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -27,6 +27,9 @@ #include <assert.h> #include <stdlib.h> #include <unistd.h> +#ifdef WINEWAYLAND_USE_ATOMIC +#include <stdatomic.h> +#endif
#include "waylanddrv.h" #include "wine/debug.h" @@ -60,7 +63,7 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0); }
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex);
/* Flush the window surface in case there is content that we weren't * able to flush before due to the lack of the initial configure. */ @@ -117,7 +120,7 @@ static void xdg_toplevel_handle_configure(void *data, surface->pending.state = config_state; }
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); }
static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) @@ -149,7 +152,11 @@ struct wayland_surface *wayland_surface_create(HWND hwnd)
TRACE("surface=%p\n", surface);
+#ifdef WINEWAYLAND_USE_ATOMIC + atomic_store(&surface->mutex, 0); +#else pthread_mutex_init(&surface->mutex, NULL); +#endif
surface->hwnd = hwnd; surface->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor); @@ -183,7 +190,7 @@ err: */ void wayland_surface_destroy(struct wayland_surface *surface) { - pthread_mutex_lock(&process_wayland.pointer.mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.pointer.mutex); if (process_wayland.pointer.focused_hwnd == surface->hwnd) { process_wayland.pointer.focused_hwnd = NULL; @@ -191,14 +198,14 @@ void wayland_surface_destroy(struct wayland_surface *surface) } if (process_wayland.pointer.constraint_hwnd == surface->hwnd) wayland_pointer_clear_constraint(); - pthread_mutex_unlock(&process_wayland.pointer.mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.pointer.mutex);
- pthread_mutex_lock(&process_wayland.keyboard.mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.keyboard.mutex); if (process_wayland.keyboard.focused_hwnd == surface->hwnd) process_wayland.keyboard.focused_hwnd = NULL; - pthread_mutex_unlock(&process_wayland.keyboard.mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.keyboard.mutex);
- pthread_mutex_lock(&surface->mutex); + WINEWAYLAND_RESOURCE_LOCK(&surface->mutex);
if (surface->wp_viewport) { @@ -224,14 +231,14 @@ void wayland_surface_destroy(struct wayland_surface *surface) surface->wl_surface = NULL; }
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex);
if (surface->latest_window_buffer) wayland_shm_buffer_unref(surface->latest_window_buffer);
wl_display_flush(process_wayland.wl_display);
- pthread_mutex_destroy(&surface->mutex); + WINEWAYLAND_RESOURCE_DESTROY(&surface->mutex);
free(surface); } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index efb13821696..a4bcf8ba35a 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -47,6 +47,38 @@ /* We only use 4 byte formats. */ #define WINEWAYLAND_BYTES_PER_PIXEL 4
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if defined(__STDC_NO_ATOMICS__) +# error C11 Atomic Operations not support. +#else +#include <stdatomic.h> +#include <stdint.h> +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> +#define WINEWAYLAND_USE_ATOMIC +#define WINEWAYLAND_RESOURCE_TYPE _Atomic unsigned char +#define WINEWAYLAND_RESOURCE_INIT ATOMIC_VAR_INIT(0) +#define WINEWAYLAND_RESOURCE_LOCK(RESOURCE) { \ + unsigned char expected = 0; \ + while(!atomic_compare_exchange_weak(RESOURCE, &expected, 1)) { \ + syscall(SYS_futex, RESOURCE, FUTEX_WAIT, 1, NULL, NULL, 0); \ + } \ +} +#define WINEWAYLAND_RESOURCE_UNLOCK(RESOURCE) { \ + atomic_store(RESOURCE, 0); \ + syscall(SYS_futex, RESOURCE, FUTEX_WAKE, 1, NULL, NULL, 0); \ +} +#define WINEWAYLAND_RESOURCE_DESTROY(RESOURCE) {} +#endif +#else +# error C11 Atomic Operations not support. C version is lower than C11. +#define WINEWAYLAND_RESOURCE_TYPE pthread_mutex_t +#define WINEWAYLAND_RESOURCE_INIT PTHREAD_MUTEX_INITIALIZER +#define WINEWAYLAND_RESOURCE_LOCK(RESOURCE) pthread_mutex_lock(RESOURCE) +#define WINEWAYLAND_RESOURCE_UNLOCK(RESOURCE) pthread_mutex_unlock(RESOURCE) +#define WINEWAYLAND_RESOURCE_DESTROY(RESOURCE) pthread_mutex_destroy(RESOURCE) +#endif /********************************************************************** * Globals */ @@ -79,7 +111,7 @@ struct wayland_keyboard struct xkb_context *xkb_context; struct xkb_state *xkb_state; HWND focused_hwnd; - pthread_mutex_t mutex; + WINEWAYLAND_RESOURCE_TYPE mutex; };
struct wayland_cursor @@ -101,14 +133,14 @@ struct wayland_pointer uint32_t enter_serial; uint32_t button_serial; struct wayland_cursor cursor; - pthread_mutex_t mutex; + WINEWAYLAND_RESOURCE_TYPE mutex; };
struct wayland_seat { struct wl_seat *wl_seat; uint32_t global_id; - pthread_mutex_t mutex; + WINEWAYLAND_RESOURCE_TYPE mutex; };
struct wayland @@ -130,7 +162,7 @@ struct wayland struct wayland_pointer pointer; struct wl_list output_list; /* Protects the output_list and the wayland_output.current states. */ - pthread_mutex_t output_mutex; + WINEWAYLAND_RESOURCE_TYPE output_mutex; };
struct wayland_output_mode @@ -196,7 +228,7 @@ struct wayland_surface struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; struct wp_viewport *wp_viewport; - pthread_mutex_t mutex; + WINEWAYLAND_RESOURCE_TYPE mutex; struct wayland_surface_config pending, requested, processing, current; struct wayland_shm_buffer *latest_window_buffer; BOOL resizing; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index dc6a6b7e03a..2765d224291 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -68,7 +68,7 @@ static int wayland_win_data_cmp_rb(const void *key, return 0; }
-static pthread_mutex_t win_data_mutex = PTHREAD_MUTEX_INITIALIZER; +static WINEWAYLAND_RESOURCE_TYPE win_data_mutex = WINEWAYLAND_RESOURCE_INIT; static struct rb_tree win_data_rb = { wayland_win_data_cmp_rb };
/*********************************************************************** @@ -95,7 +95,7 @@ static struct wayland_win_data *wayland_win_data_create(HWND hwnd, data->window_rect = *window_rect; data->client_rect = *client_rect;
- pthread_mutex_lock(&win_data_mutex); + WINEWAYLAND_RESOURCE_LOCK(&win_data_mutex);
/* Check that another thread hasn't already created the wayland_win_data. */ if ((rb_entry = rb_get(&win_data_rb, hwnd))) @@ -120,7 +120,7 @@ static void wayland_win_data_destroy(struct wayland_win_data *data)
rb_remove(&win_data_rb, &data->entry);
- pthread_mutex_unlock(&win_data_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&win_data_mutex);
if (data->window_surface) { @@ -140,12 +140,12 @@ struct wayland_win_data *wayland_win_data_get(HWND hwnd) { struct rb_entry *rb_entry;
- pthread_mutex_lock(&win_data_mutex); + WINEWAYLAND_RESOURCE_LOCK(&win_data_mutex);
if ((rb_entry = rb_get(&win_data_rb, hwnd))) return RB_ENTRY_VALUE(rb_entry, struct wayland_win_data, entry);
- pthread_mutex_unlock(&win_data_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&win_data_mutex);
return NULL; } @@ -158,7 +158,7 @@ struct wayland_win_data *wayland_win_data_get(HWND hwnd) void wayland_win_data_release(struct wayland_win_data *data) { assert(data); - pthread_mutex_unlock(&win_data_mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&win_data_mutex); }
static void wayland_win_data_get_config(struct wayland_win_data *data, @@ -225,7 +225,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; xdg_visible = surface->xdg_toplevel != NULL;
- pthread_mutex_lock(&surface->mutex); + WINEWAYLAND_RESOURCE_LOCK(&surface->mutex);
if (visible != xdg_visible) { @@ -248,7 +248,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
wayland_win_data_get_config(data, &surface->window);
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex);
if (data->window_surface) wayland_window_surface_update_wayland_surface(data->window_surface, visible_rect, surface); @@ -267,7 +267,7 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) struct wayland_surface *surface = data->wayland_surface; BOOL processing_config;
- pthread_mutex_lock(&surface->mutex); + WINEWAYLAND_RESOURCE_LOCK(&surface->mutex);
if (!surface->xdg_toplevel) goto out;
@@ -313,7 +313,7 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) }
out: - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); wl_display_flush(process_wayland.wl_display); }
@@ -503,14 +503,14 @@ static void wayland_configure_window(HWND hwnd) if (!surface->xdg_toplevel) { TRACE("missing xdg_toplevel, returning\n"); - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); return; }
if (!surface->requested.serial) { TRACE("requested configure event already handled, returning\n"); - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); return; }
@@ -572,7 +572,7 @@ static void wayland_configure_window(HWND hwnd) wayland_surface_coords_to_window(surface, width, height, &window_width, &window_height);
- pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex);
TRACE("processing=%dx%d,%#x\n", width, height, state);
@@ -658,7 +658,7 @@ void WAYLAND_SetWindowText(HWND hwnd, LPCWSTR text) if (surface) { if (surface->xdg_toplevel) wayland_surface_set_title(surface, text); - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); } }
@@ -676,18 +676,18 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) TRACE("cmd=%lx hwnd=%p, %lx, %lx\n", (long)command, hwnd, (long)wparam, lparam);
- pthread_mutex_lock(&process_wayland.pointer.mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.pointer.mutex); if (process_wayland.pointer.focused_hwnd == hwnd) button_serial = process_wayland.pointer.button_serial; else button_serial = 0; - pthread_mutex_unlock(&process_wayland.pointer.mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.pointer.mutex);
if (command == SC_MOVE || command == SC_SIZE) { if ((surface = wayland_surface_lock_hwnd(hwnd))) { - pthread_mutex_lock(&process_wayland.seat.mutex); + WINEWAYLAND_RESOURCE_LOCK(&process_wayland.seat.mutex); wl_seat = process_wayland.seat.wl_seat; if (wl_seat && surface->xdg_toplevel && button_serial) { @@ -701,8 +701,8 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) hittest_to_resize_edge(wparam & 0x0f)); } } - pthread_mutex_unlock(&process_wayland.seat.mutex); - pthread_mutex_unlock(&surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&process_wayland.seat.mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&surface->mutex); ret = 0; } } @@ -738,7 +738,7 @@ struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd)
if (!data) return NULL;
- if ((surface = data->wayland_surface)) pthread_mutex_lock(&surface->mutex); + if ((surface = data->wayland_surface)) WINEWAYLAND_RESOURCE_LOCK(&surface->mutex);
wayland_win_data_release(data);
diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index e9eb74b17ca..2535a7e2a5d 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -386,7 +386,7 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface,
wayland_shm_buffer_copy_data(shm_buffer, color_bits, &surface_rect, copy_from_window_region);
- pthread_mutex_lock(&wws->wayland_surface->mutex); + WINEWAYLAND_RESOURCE_LOCK(&wws->wayland_surface->mutex); if (wayland_surface_reconfigure(wws->wayland_surface)) { wayland_surface_attach_shm(wws->wayland_surface, shm_buffer, @@ -398,7 +398,7 @@ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, { TRACE("Wayland surface not configured yet, not flushing\n"); } - pthread_mutex_unlock(&wws->wayland_surface->mutex); + WINEWAYLAND_RESOURCE_UNLOCK(&wws->wayland_surface->mutex); wl_display_flush(process_wayland.wl_display);
NtGdiSetRectRgn(shm_buffer->damage_region, 0, 0, 0, 0);
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/waylanddrv.h:
/* We only use 4 byte formats. */ #define WINEWAYLAND_BYTES_PER_PIXEL 4
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if defined(__STDC_NO_ATOMICS__) +# error C11 Atomic Operations not support. +#else +#include <stdatomic.h> +#include <stdint.h> +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> +#define WINEWAYLAND_USE_ATOMIC +#define WINEWAYLAND_RESOURCE_TYPE _Atomic unsigned char
Please name your mutex type something involving mutex, lock, or similar.
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/waylanddrv.h:
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if defined(__STDC_NO_ATOMICS__) +# error C11 Atomic Operations not support. +#else +#include <stdatomic.h> +#include <stdint.h> +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> +#define WINEWAYLAND_USE_ATOMIC +#define WINEWAYLAND_RESOURCE_TYPE _Atomic unsigned char +#define WINEWAYLAND_RESOURCE_INIT ATOMIC_VAR_INIT(0) +#define WINEWAYLAND_RESOURCE_LOCK(RESOURCE) { \
- unsigned char expected = 0; \
- while(!atomic_compare_exchange_weak(RESOURCE, &expected, 1)) { \
syscall(SYS_futex, RESOURCE, FUTEX_WAIT, 1, NULL, NULL, 0); \
The futex syscall takes a pointer to int, not unsigned char.
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/waylanddrv.h:
+#include <stdint.h> +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> +#define WINEWAYLAND_USE_ATOMIC +#define WINEWAYLAND_RESOURCE_TYPE _Atomic unsigned char +#define WINEWAYLAND_RESOURCE_INIT ATOMIC_VAR_INIT(0) +#define WINEWAYLAND_RESOURCE_LOCK(RESOURCE) { \
- unsigned char expected = 0; \
- while(!atomic_compare_exchange_weak(RESOURCE, &expected, 1)) { \
syscall(SYS_futex, RESOURCE, FUTEX_WAIT, 1, NULL, NULL, 0); \
- } \
+} +#define WINEWAYLAND_RESOURCE_UNLOCK(RESOURCE) { \
- atomic_store(RESOURCE, 0); \
- syscall(SYS_futex, RESOURCE, FUTEX_WAKE, 1, NULL, NULL, 0); \
An unconditional syscall in the wake path? I'm pretty sure that will make it slower than pthread mutex.
I completely agree with benchmarking and testing this thing before de-drafting it. I don't trust eyeball measurements for this kind of stuff, I suspect they'll measure mostly placebo.
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/waylanddrv.h:
+# error C11 Atomic Operations not support. +#else +#include <stdatomic.h> +#include <stdint.h> +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> +#define WINEWAYLAND_USE_ATOMIC +#define WINEWAYLAND_RESOURCE_TYPE _Atomic unsigned char +#define WINEWAYLAND_RESOURCE_INIT ATOMIC_VAR_INIT(0) +#define WINEWAYLAND_RESOURCE_LOCK(RESOURCE) { \
- unsigned char expected = 0; \
- while(!atomic_compare_exchange_weak(RESOURCE, &expected, 1)) { \
syscall(SYS_futex, RESOURCE, FUTEX_WAIT, 1, NULL, NULL, 0); \
- } \
+}
Please wrap function-like macros in `do { body; } while(0)`, so they don't screw up if used in if-else cases without braces.
Or even better, make them static inline functions. (Don't worry about function call overhead, it'll get inlined.)
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/wayland_surface.c:
TRACE("surface=%p\n", surface);
+#ifdef WINEWAYLAND_USE_ATOMIC
- atomic_store(&surface->mutex, 0);
WINEWAYLAND_RESOURCE_DESTROY is defined in the header, but this operation isn't? I don't think that's right.
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/waylanddrv.h:
/* We only use 4 byte formats. */ #define WINEWAYLAND_BYTES_PER_PIXEL 4
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if defined(__STDC_NO_ATOMICS__) +# error C11 Atomic Operations not support. +#else +#include <stdatomic.h>
Better use InterlockedCompareExchange/etc, so you won't need to bump the C version.
InterlockedAbc works fine from Unix-side code, we use them for futexes already, for example in https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/unix/sync.c#L25...
Alfred Agrell (@Alcaro) commented about dlls/winewayland.drv/waylanddrv.h:
+#define WINEWAYLAND_RESOURCE_TYPE _Atomic unsigned char +#define WINEWAYLAND_RESOURCE_INIT ATOMIC_VAR_INIT(0) +#define WINEWAYLAND_RESOURCE_LOCK(RESOURCE) { \
- unsigned char expected = 0; \
- while(!atomic_compare_exchange_weak(RESOURCE, &expected, 1)) { \
syscall(SYS_futex, RESOURCE, FUTEX_WAIT, 1, NULL, NULL, 0); \
- } \
+} +#define WINEWAYLAND_RESOURCE_UNLOCK(RESOURCE) { \
- atomic_store(RESOURCE, 0); \
- syscall(SYS_futex, RESOURCE, FUTEX_WAKE, 1, NULL, NULL, 0); \
+} +#define WINEWAYLAND_RESOURCE_DESTROY(RESOURCE) {} +#endif +#else +# error C11 Atomic Operations not support. C version is lower than C11.
Are C11 atomics mandatory? If yes, the below #defines are unnecessary; if no, this #error doesn't belong.
Alfred Agrell (@Alcaro) commented about dlls/msxml3/domdoc.c:
#include <libxml/parser.h> #include <libxml/xmlerror.h> #include <libxml/xpathInternals.h> -# include <libxml/xmlsave.h> +#include <libxml/xmlsave.h>
I agree that these msxml changes are improvements, but I think you submitted them to wrong MR.
I'm not a Wine maintainer, so feel free to ignore me if you feel I'm talking nonsense
On Wed Jul 10 08:43:01 2024 +0000, Alfred Agrell wrote:
I agree that these msxml changes are improvements, but I think you submitted them to wrong MR.
This is Draft Mr. Usually, all related changes are collected in one place, and then this mr is divided into several separate ones.
On Wed Jul 10 08:44:48 2024 +0000, Alfred Agrell wrote:
Are C11 atomics mandatory? If yes, the below #defines are unnecessary; if no, this #error doesn't belong.
This is a debugging and development error that will be removed later, it only signals that mutex will use pthread instead of atomic.
On Wed Jul 10 08:48:05 2024 +0000, Alfred Agrell wrote:
Better use InterlockedCompareExchange/etc, so you won't need to bump the C version. InterlockedAbc works fine from Unix-side code, we use them for futexes already, for example in https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/unix/sync.c#L25...
There are advantages to using C11 - better error control in the code. But C11 ambiguously interprets some points of the standard, and C17 is the same as C11, but brings more clarity and is a bug fix for C11. Modern compilers use C17 when specifying C11.
On Wed Jul 10 08:57:19 2024 +0000, Alfred Agrell wrote:
WINEWAYLAND_RESOURCE_DESTROY is defined in the header, but this operation isn't? I don't think that's right.
It seems that when initializing pthread, mutex uses something like malloc, and destroy is needed to free up memory. But I'm not sure. Atomic uses a simple variable. And there are many places in the code where pthread_mutex does not call destroy. I also rewrote the ntdll code to an atomic lock, and destroy is only called in one place in winewayland. For ntdll, the recursive mutex remains to be completed. In terms of doing the same for winevulkan and win32u. Currently, atomic lock in Apex Legends gave +10 FPS. I also moved everything into a separate header file for better code unification.
On Wed Jul 10 00:18:13 2024 +0000, Alfred Agrell wrote:
Please wrap function-like macros in `do { body; } while(0)`, so they don't screw up if used in if-else cases without braces. Or even better, make them static inline functions. (Don't worry about function call overhead, it'll get inlined.)
Thank you, you are right, for now I will use macro, in the future I may transfer the code to an inline function.
On Wed Jul 10 00:18:13 2024 +0000, Alfred Agrell wrote:
An unconditional syscall in the wake path? I'm pretty sure that will make it slower than pthread mutex. I completely agree with benchmarking and testing this thing before de-drafting it. I don't trust eyeball measurements for this kind of stuff, I suspect they'll measure mostly placebo.
@Alcaro I don’t quite understand you here, because futex_wake should wake up one listener who fell asleep while lock. Perhaps I made a mistake somewhere, but I looked at other people's atomic lock implementations. It is unlikely that the code will be slower than pthread because pthread uses expensive scheduler context switching. We can remove futex from the code, but then we will waste extra CPU cycles. But yes, we need to come up with tests.
https://inria.hal.science/hal-01236734/document https://github.com/tchajed/futex-tutorial/tree/main
On Wed Jul 10 00:18:12 2024 +0000, Alfred Agrell wrote:
The futex syscall takes a pointer to int, not unsigned char.
Thanks. I'll fix it.
On Wed Jul 10 00:18:12 2024 +0000, Alfred Agrell wrote:
Please name your mutex type something involving mutex, lock, or similar.
I'll fix it.