Update fd cache patches (use slightly slower interlocked commands, which should also work well on less usual processor architectures).

This commit is contained in:
Sebastian Lackner 2014-05-31 22:10:09 +02:00
parent 1800d1f853
commit 229eb9bba5
3 changed files with 68 additions and 69 deletions

View File

@ -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 <sebastian@fds-team.de>
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;

View File

@ -1,3 +1,3 @@
Revision: 2
Revision: 3
Author: Sebastian Lackner
Title: Use lockfree implementation for get_cached_fd.

View File

@ -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." },