diff --git a/patches/12-FD_Cache/0001-ntdll-Use-lockfree-implementation-for-get_cached_fd.patch b/patches/12-FD_Cache/0001-ntdll-Use-lockfree-implementation-for-get_cached_fd.patch index 7e83835f..2ea016da 100644 --- a/patches/12-FD_Cache/0001-ntdll-Use-lockfree-implementation-for-get_cached_fd.patch +++ b/patches/12-FD_Cache/0001-ntdll-Use-lockfree-implementation-for-get_cached_fd.patch @@ -1,128 +1,127 @@ -From b02cb296f5b0c7b6e358e882e820edf079f6e81b Mon Sep 17 00:00:00 2001 +From 9124129971336d0e76deb76a8eb0396e1f4aa6a9 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner -Date: Sat, 31 May 2014 03:21:39 +0200 +Date: Sat, 31 May 2014 21:02:04 +0200 Subject: ntdll: Use lockfree implementation for get_cached_fd. --- - dlls/ntdll/server.c | 57 ++++++++++++++++++++++++++++++++++++--------------- - 1 file changed, 41 insertions(+), 16 deletions(-) + dlls/ntdll/server.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c -index f3c6b38..749eda5 100644 +index f3c6b38..cda0896 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c -@@ -787,17 +787,27 @@ static int receive_fd( obj_handle_t *handle ) - /***********************************************************************/ - /* fd cache support */ +@@ -73,6 +73,8 @@ -+union fd_cache_entry_attrs -+{ -+ int value; -+ struct -+ { -+ enum server_fd_type type : 5; -+ unsigned int access : 3; -+ unsigned int options : 24; -+ } s; -+}; -+ - struct fd_cache_entry - { - int fd; -- enum server_fd_type type : 5; -- unsigned int access : 3; -- unsigned int options : 24; -+ union fd_cache_entry_attrs attrs; + #include "ntstatus.h" + #define WIN32_NO_STATUS ++#include "windef.h" ++#include "winnt.h" + #include "wine/library.h" + #include "wine/server.h" + #include "wine/debug.h" +@@ -795,6 +797,10 @@ struct fd_cache_entry + unsigned int options : 24; }; ++#if !defined(__powerpc__) ++C_ASSERT( sizeof(struct fd_cache_entry) == sizeof(LONG64) ); ++#endif ++ #define FD_CACHE_BLOCK_SIZE (65536 / sizeof(struct fd_cache_entry)) #define FD_CACHE_ENTRIES 128 -+static int fd_cache_epoch; - static struct fd_cache_entry *fd_cache[FD_CACHE_ENTRIES]; - static struct fd_cache_entry fd_cache_initial_block[FD_CACHE_BLOCK_SIZE]; - -@@ -818,7 +828,7 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type, +@@ -818,7 +824,6 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type, unsigned int access, unsigned int options ) { unsigned int entry, idx = handle_to_index( handle, &entry ); - int prev_fd; -+ union fd_cache_entry_attrs attrs; if (entry >= FD_CACHE_ENTRIES) { -@@ -837,33 +847,44 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type, +@@ -837,12 +842,29 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type, fd_cache[entry] = ptr; } } + -+ attrs.s.type = type; -+ attrs.s.access = access; -+ attrs.s.options = options; -+ ++#if defined(__powerpc__) /* store fd+1 so that 0 can be used as the unset value */ - prev_fd = interlocked_xchg( &fd_cache[entry][idx].fd, fd + 1 ) - 1; -- fd_cache[entry][idx].type = type; -- fd_cache[entry][idx].access = access; -- fd_cache[entry][idx].options = options; ++ assert( !interlocked_xchg( &fd_cache[entry][idx].fd, fd + 1 ) ); + fd_cache[entry][idx].type = type; + fd_cache[entry][idx].access = access; + fd_cache[entry][idx].options = options; - if (prev_fd != -1) close( prev_fd ); -+ assert( !fd_cache[entry][idx].fd ); -+ interlocked_xchg_add( &fd_cache_epoch, 1 ); -+ fd_cache[entry][idx].attrs.value = attrs.value; -+ fd_cache[entry][idx].fd = fd + 1; ++#else ++ { ++ struct fd_cache_entry old_cache, new_cache; ++ ++ /* store fd+1 so that 0 can be used as the unset value */ ++ new_cache.fd = fd + 1; ++ new_cache.type = type; ++ new_cache.access = access; ++ new_cache.options = options; ++ ++ /* we're holding the lock and have checked the content before, so the cache always contains the latest value */ ++ old_cache = fd_cache[entry][idx]; ++ assert( !old_cache.fd ); ++ assert( interlocked_cmpxchg64( (LONG64 *)&fd_cache[entry][idx], *(LONG64 *)&new_cache, *(LONG64 *)&old_cache ) == *(LONG64 *)&old_cache ); ++ } ++#endif return TRUE; } - +@@ -850,7 +872,7 @@ static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type, /*********************************************************************** * get_cached_fd -- * + * - * Caller must hold fd_cache_section. ++ * Caller must hold fd_cache_section on PowerPC processor architecture. */ static inline int get_cached_fd( HANDLE handle, enum server_fd_type *type, unsigned int *access, unsigned int *options ) - { - unsigned int entry, idx = handle_to_index( handle, &entry ); -- int fd = -1; -+ union fd_cache_entry_attrs attrs; -+ int epoch, fd = -1; +@@ -860,10 +882,21 @@ static inline int get_cached_fd( HANDLE handle, enum server_fd_type *type, if (entry < FD_CACHE_ENTRIES && fd_cache[entry]) { -- fd = fd_cache[entry][idx].fd - 1; -- if (type) *type = fd_cache[entry][idx].type; -- if (access) *access = fd_cache[entry][idx].access; -- if (options) *options = fd_cache[entry][idx].options; -+ do ++ #if defined(__powerpc__) + fd = fd_cache[entry][idx].fd - 1; + if (type) *type = fd_cache[entry][idx].type; + if (access) *access = fd_cache[entry][idx].access; + if (options) *options = fd_cache[entry][idx].options; ++ #else + { -+ epoch = fd_cache_epoch; -+ attrs.value = fd_cache[entry][idx].attrs.value; -+ fd = fd_cache[entry][idx].fd - 1; -+ __asm__ __volatile__( "" : : : "memory" ); ++ struct fd_cache_entry cache; ++ *(LONG64 *)&cache = interlocked_cmpxchg64( (LONG64 *)&fd_cache[entry][idx], 0, 0 ); ++ fd = cache.fd - 1; ++ if (type) *type = cache.type; ++ if (access) *access = cache.access; ++ if (options) *options = cache.options; + } -+ while (epoch != fd_cache_epoch); -+ -+ if (type) *type = attrs.s.type; -+ if (access) *access = attrs.s.access; -+ if (options) *options = attrs.s.options; ++ #endif } return fd; } -@@ -901,6 +922,9 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, +@@ -901,6 +934,11 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, *needs_close = 0; wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA; ++#if !defined(__powerpc__) + fd = get_cached_fd( handle, type, &access, options ); + if (fd != -1) goto done_unlocked; ++#endif + server_enter_uninterrupted_section( &fd_cache_section, &sigset ); fd = get_cached_fd( handle, type, &access, options ); -@@ -928,6 +952,7 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, +@@ -928,6 +966,10 @@ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, done: server_leave_uninterrupted_section( &fd_cache_section, &sigset ); ++ ++#if !defined(__powerpc__) +done_unlocked: ++#endif if (!ret && ((access & wanted_access) != wanted_access)) { ret = STATUS_ACCESS_DENIED; diff --git a/patches/12-FD_Cache/e7581ed7-12b3-4ed3-835b-5a62afbf9c85.def b/patches/12-FD_Cache/e7581ed7-12b3-4ed3-835b-5a62afbf9c85.def index 695eeb29..cec748a0 100644 --- a/patches/12-FD_Cache/e7581ed7-12b3-4ed3-835b-5a62afbf9c85.def +++ b/patches/12-FD_Cache/e7581ed7-12b3-4ed3-835b-5a62afbf9c85.def @@ -1,3 +1,3 @@ -Revision: 2 +Revision: 3 Author: Sebastian Lackner Title: Use lockfree implementation for get_cached_fd. diff --git a/patches/patch-list.patch b/patches/patch-list.patch index d7363e12..50d532ef 100644 --- a/patches/patch-list.patch +++ b/patches/patch-list.patch @@ -29,7 +29,7 @@ index a273502..5fa0cd5 100644 + { "5fb1f5c8-7f17-11e3-9b62-0090f5c75ad5:1", "Erich E. Hoover", "Implement TransmitFile." }, + { "3d7c4774-9e7f-11e3-9cfc-0090f5c75ad5:1", "Erich E. Hoover", "Implement missing fonts expected by Silverlight." }, + { "c0ac8f22-1483-4e1f-8136-88e5fb99a41f:1", "Michael Müller", "Add stub for TokenAppContainerSid in NtQueryInformationToken." }, -+ { "e7581ed7-12b3-4ed3-835b-5a62afbf9c85:2", "Sebastian Lackner", "Use lockfree implementation for get_cached_fd." }, ++ { "e7581ed7-12b3-4ed3-835b-5a62afbf9c85:3", "Sebastian Lackner", "Use lockfree implementation for get_cached_fd." }, + { "0b21d7ac-0387-4493-aa38-fbafe3e749f5:2", "Michael Müller", "Decrease minimum SetTimer interval to 5 ms." }, + { "2394843e-2bc4-4fa4-8368-1ef32093b89e:1", "Michael Müller", "Allow changing strict draw ordering through an exported function." }, + { "59bd38b7-bbdc-4cfd-9ccd-1c72c4ed84c0:1", "Sebastian Lackner", "Implement X11DRV_FLUSH_GDI_DISPLAY ExtEscape command." },