eventfd_synchronization: Rebase and reënable.

This commit is contained in:
Zebediah Figura 2020-10-17 16:57:58 -05:00
parent 80498dd440
commit ed56966feb
110 changed files with 3493 additions and 7254 deletions

View File

@ -1,4 +1,4 @@
From e0719eabba7a7c187767441b361acedd50766234 Mon Sep 17 00:00:00 2001
From 723ccff12d0b9516490e34519e244a6486d11b8b Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Wed, 13 Jun 2018 10:44:49 -0500
Subject: [PATCH] configure: Check for sys/eventfd.h, ppoll(), and shm_open().
@ -7,14 +7,16 @@ We use ppoll() instead of poll() for the better time granularity.
Although perhaps we shouldn't since the server doesn't do this.
---
configure.ac | 12 ++++++++++++
1 file changed, 12 insertions(+)
configure | 68 +++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 12 ++++++++
include/config.h.in | 9 ++++++
3 files changed, 89 insertions(+)
diff --git a/configure.ac b/configure.ac
index da5f24aba5f..6c2653c4c82 100644
--- a/configure.ac
+++ b/configure.ac
@@ -509,6 +509,7 @@ AC_CHECK_HEADERS(\
diff --git a/configure b/configure
index 5672688a0d7..24ae489c3a9 100755
--- a/configure
+++ b/configure
@@ -7467,6 +7467,7 @@ for ac_header in \
sys/cdio.h \
sys/epoll.h \
sys/event.h \
@ -22,7 +24,7 @@ index da5f24aba5f..6c2653c4c82 100644
sys/filio.h \
sys/ioctl.h \
sys/ipc.h \
@@ -2191,6 +2192,7 @@ AC_CHECK_FUNCS(\
@@ -17815,6 +17816,7 @@ for ac_func in \
pipe2 \
poll \
port_create \
@ -30,7 +32,100 @@ index da5f24aba5f..6c2653c4c82 100644
prctl \
pread \
proc_pidinfo \
@@ -2265,6 +2267,16 @@ case $host_os in
@@ -18224,6 +18226,72 @@ fi
;;
esac
+if test "$ac_cv_header_sys_mman_h" = "yes" -a "x$RT_LIBS" = "x"
+then
+ ac_save_LIBS=$LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing shm_open" >&5
+$as_echo_n "checking for library containing shm_open... " >&6; }
+if ${ac_cv_search_shm_open+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shm_open ();
+int
+main ()
+{
+return shm_open ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_shm_open=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_shm_open+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_shm_open+:} false; then :
+
+else
+ ac_cv_search_shm_open=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_shm_open" >&5
+$as_echo "$ac_cv_search_shm_open" >&6; }
+ac_res=$ac_cv_search_shm_open
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_SHM_OPEN 1" >>confdefs.h
+
+ test "$ac_res" = "none required" || RT_LIBS="$ac_res"
+
+fi
+
+fi
+LIBS=$ac_save_LIBS
+
if test "x$with_ldap" != "xno"
then
if ${LDAP_CFLAGS:+false} :; then :
diff --git a/configure.ac b/configure.ac
index 7a03cbc1cab..bfa64a8d68a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -494,6 +494,7 @@ AC_CHECK_HEADERS(\
sys/cdio.h \
sys/epoll.h \
sys/event.h \
+ sys/eventfd.h \
sys/filio.h \
sys/ioctl.h \
sys/ipc.h \
@@ -2207,6 +2208,7 @@ AC_CHECK_FUNCS(\
pipe2 \
poll \
port_create \
+ ppoll \
prctl \
pread \
proc_pidinfo \
@@ -2271,6 +2273,16 @@ case $host_os in
;;
esac
@ -47,6 +142,40 @@ index da5f24aba5f..6c2653c4c82 100644
dnl **** Check for OpenLDAP ***
if test "x$with_ldap" != "xno"
then
diff --git a/include/config.h.in b/include/config.h.in
index 4adb6325e14..6f1323311d9 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -687,6 +687,9 @@
/* Define to 1 if you have the <port.h> header file. */
#undef HAVE_PORT_H
+/* Define to 1 if you have the `ppoll' function. */
+#undef HAVE_PPOLL
+
/* Define to 1 if you have the `prctl' function. */
#undef HAVE_PRCTL
@@ -804,6 +807,9 @@
/* Define to 1 if `interface_id' is a member of `sg_io_hdr_t'. */
#undef HAVE_SG_IO_HDR_T_INTERFACE_ID
+/* Define to 1 if you have the `shm_open' function. */
+#undef HAVE_SHM_OPEN
+
/* Define if sigaddset is supported */
#undef HAVE_SIGADDSET
@@ -1004,6 +1010,9 @@
/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
+/* Define to 1 if you have the <sys/eventfd.h> header file. */
+#undef HAVE_SYS_EVENTFD_H
+
/* Define to 1 if you have the <sys/event.h> header file. */
#undef HAVE_SYS_EVENT_H
--
2.25.1
2.28.0

View File

@ -1,4 +1,4 @@
From d407857d923dd08446cf38f83549c0b76442cc81 Mon Sep 17 00:00:00 2001
From d10e2324d1295c27e00975526420375a338b5eb1 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 20:09:59 -0500
Subject: [PATCH] server: Create server objects for eventfd-based
@ -6,13 +6,16 @@ Subject: [PATCH] server: Create server objects for eventfd-based
---
server/Makefile.in | 1 +
server/esync.c | 137 ++++++++++++++++++++++++++++++++++++++++++++
server/protocol.def | 10 ++++
3 files changed, 148 insertions(+)
server/esync.c | 320 ++++++++++++++++++++++++++++++++++++++++++++
server/esync.h | 22 +++
server/main.c | 4 +
server/protocol.def | 24 ++++
5 files changed, 371 insertions(+)
create mode 100644 server/esync.c
create mode 100644 server/esync.h
diff --git a/server/Makefile.in b/server/Makefile.in
index 60ecca706..2c895bcec 100644
index 9a695cefc30..8bd612b4728 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -11,6 +11,7 @@ C_SRCS = \
@ -25,10 +28,10 @@ index 60ecca706..2c895bcec 100644
file.c \
diff --git a/server/esync.c b/server/esync.c
new file mode 100644
index 000000000..147fb7724
index 00000000000..b8b257281bf
--- /dev/null
+++ b/server/esync.c
@@ -0,0 +1,137 @@
@@ -0,0 +1,320 @@
+/*
+ * eventfd-based synchronization objects
+ *
@ -52,11 +55,19 @@ index 000000000..147fb7724
+#include "config.h"
+#include "wine/port.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#ifdef HAVE_SYS_EVENTFD_H
+# include <sys/eventfd.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#include <unistd.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
@ -67,10 +78,72 @@ index 000000000..147fb7724
+#include "request.h"
+#include "file.h"
+
+int do_esync(void)
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ static int do_esync_cached = -1;
+
+ if (do_esync_cached == -1)
+ do_esync_cached = getenv("WINEESYNC") && atoi(getenv("WINEESYNC"));
+
+ return do_esync_cached;
+#else
+ return 0;
+#endif
+}
+
+static char shm_name[29];
+static int shm_fd;
+static off_t shm_size;
+static void **shm_addrs;
+static int shm_addrs_size; /* length of the allocated shm_addrs array */
+static long pagesize;
+
+static void shm_cleanup(void)
+{
+ close( shm_fd );
+ if (shm_unlink( shm_name ) == -1)
+ perror( "shm_unlink" );
+}
+
+void esync_init(void)
+{
+ struct stat st;
+
+ if (fstat( config_dir_fd, &st ) == -1)
+ fatal_error( "cannot stat config dir\n" );
+
+ if (st.st_ino != (unsigned long)st.st_ino)
+ sprintf( shm_name, "/wine-%lx%08lx-esync", (unsigned long)((unsigned long long)st.st_ino >> 32), (unsigned long)st.st_ino );
+ else
+ sprintf( shm_name, "/wine-%lx-esync", (unsigned long)st.st_ino );
+
+ shm_unlink( shm_name );
+
+ shm_fd = shm_open( shm_name, O_RDWR | O_CREAT | O_EXCL, 0644 );
+ if (shm_fd == -1)
+ perror( "shm_open" );
+
+ pagesize = sysconf( _SC_PAGESIZE );
+
+ shm_addrs = calloc( 128, sizeof(shm_addrs[0]) );
+ shm_addrs_size = 128;
+
+ shm_size = pagesize;
+ if (ftruncate( shm_fd, shm_size ) == -1)
+ perror( "ftruncate" );
+
+ fprintf( stderr, "esync: up and running.\n" );
+
+ atexit( shm_cleanup );
+}
+
+struct esync
+{
+ struct object obj; /* object header */
+ int fd; /* eventfd file descriptor */
+ struct object obj; /* object header */
+ int fd; /* eventfd file descriptor */
+ enum esync_type type;
+ unsigned int shm_idx; /* index into the shared memory section */
+};
+
+static void esync_dump( struct object *obj, int verbose );
@ -90,6 +163,7 @@ index 000000000..147fb7724
+ no_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ default_get_full_name, /* get_full_name */
+ no_lookup_name, /* lookup_name */
+ directory_link_name, /* link_name */
+ default_unlink_name, /* unlink_name */
@ -112,8 +186,58 @@ index 000000000..147fb7724
+ close( esync->fd );
+}
+
+static int type_matches( enum esync_type type1, enum esync_type type2 )
+{
+ return (type1 == type2) ||
+ ((type1 == ESYNC_AUTO_EVENT || type1 == ESYNC_MANUAL_EVENT) &&
+ (type2 == ESYNC_AUTO_EVENT || type2 == ESYNC_MANUAL_EVENT));
+}
+
+static void *get_shm( unsigned int idx )
+{
+ int entry = (idx * 8) / pagesize;
+ int offset = (idx * 8) % pagesize;
+
+ if (entry >= shm_addrs_size)
+ {
+ int new_size = max(shm_addrs_size * 2, entry + 1);
+
+ if (!(shm_addrs = realloc( shm_addrs, new_size * sizeof(shm_addrs[0]) )))
+ fprintf( stderr, "esync: couldn't expand shm_addrs array to size %d\n", entry + 1 );
+
+ memset( shm_addrs + shm_addrs_size, 0, (new_size - shm_addrs_size) * sizeof(shm_addrs[0]) );
+
+ shm_addrs_size = new_size;
+ }
+
+ if (!shm_addrs[entry])
+ {
+ void *addr = mmap( NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, entry * pagesize );
+ if (addr == (void *)-1)
+ {
+ fprintf( stderr, "esync: failed to map page %d (offset %#lx): ", entry, entry * pagesize );
+ perror( "mmap" );
+ }
+
+ if (debug_level)
+ fprintf( stderr, "esync: Mapping page %d at %p.\n", entry, addr );
+
+ if (__sync_val_compare_and_swap( &shm_addrs[entry], 0, addr ))
+ munmap( addr, pagesize ); /* someone beat us to it */
+ }
+
+ return (void *)((unsigned long)shm_addrs[entry] + offset);
+}
+
+struct semaphore
+{
+ int max;
+ int count;
+};
+C_ASSERT(sizeof(struct semaphore) == 8);
+
+struct esync *create_esync( struct object *root, const struct unicode_str *name,
+ unsigned int attr, int initval, int flags,
+ unsigned int attr, int initval, int max, enum esync_type type,
+ const struct security_descriptor *sd )
+{
+#ifdef HAVE_SYS_EVENTFD_H
@ -123,8 +247,13 @@ index 000000000..147fb7724
+ {
+ if (get_error() != STATUS_OBJECT_NAME_EXISTS)
+ {
+ int flags = EFD_CLOEXEC | EFD_NONBLOCK;
+
+ if (type == ESYNC_SEMAPHORE)
+ flags |= EFD_SEMAPHORE;
+
+ /* initialize it if it didn't already exist */
+ esync->fd = eventfd( initval, flags | EFD_CLOEXEC | EFD_NONBLOCK );
+ esync->fd = eventfd( initval, flags );
+ if (esync->fd == -1)
+ {
+ perror( "eventfd" );
@ -132,6 +261,49 @@ index 000000000..147fb7724
+ release_object( esync );
+ return NULL;
+ }
+ esync->type = type;
+
+ /* Use the fd as index, since that'll be unique across all
+ * processes, but should hopefully end up also allowing reuse. */
+ esync->shm_idx = esync->fd + 1; /* we keep index 0 reserved */
+ while (esync->shm_idx * 8 >= shm_size)
+ {
+ /* Better expand the shm section. */
+ shm_size += pagesize;
+ if (ftruncate( shm_fd, shm_size ) == -1)
+ {
+ fprintf( stderr, "esync: couldn't expand %s to size %ld: ",
+ shm_name, (long)shm_size );
+ perror( "ftruncate" );
+ }
+ }
+
+ /* Initialize the shared memory portion. We want to do this on the
+ * server side to avoid a potential though unlikely race whereby
+ * the same object is opened and used between the time it's created
+ * and the time its shared memory portion is initialized. */
+ switch (type)
+ {
+ case ESYNC_SEMAPHORE:
+ {
+ struct semaphore *semaphore = get_shm( esync->shm_idx );
+ semaphore->max = max;
+ semaphore->count = initval;
+ break;
+ }
+ default:
+ assert( 0 );
+ }
+ }
+ else
+ {
+ /* validate the type */
+ if (!type_matches( type, esync->type ))
+ {
+ release_object( &esync->obj );
+ set_error( STATUS_OBJECT_TYPE_MISMATCH );
+ return NULL;
+ }
+ }
+ }
+ return esync;
@ -150,9 +322,21 @@ index 000000000..147fb7724
+ const struct security_descriptor *sd;
+ const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
+
+ if (!do_esync())
+ {
+ set_error( STATUS_NOT_IMPLEMENTED );
+ return;
+ }
+
+ if (!req->type)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (!objattr) return;
+
+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->flags, sd )))
+ if ((esync = create_esync( root, &name, objattr->attributes, req->initval, req->max, req->type, sd )))
+ {
+ if (get_error() == STATUS_OBJECT_NAME_EXISTS)
+ reply->handle = alloc_handle( current->process, esync, req->access, objattr->attributes );
@ -160,30 +344,96 @@ index 000000000..147fb7724
+ reply->handle = alloc_handle_no_access_check( current->process, esync,
+ req->access, objattr->attributes );
+
+ reply->type = esync->type;
+ reply->shm_idx = esync->shm_idx;
+ send_client_fd( current->process, esync->fd, reply->handle );
+ release_object( esync );
+ }
+
+ if (root) release_object( root );
+}
diff --git a/server/esync.h b/server/esync.h
new file mode 100644
index 00000000000..7ca4ca89394
--- /dev/null
+++ b/server/esync.h
@@ -0,0 +1,22 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern int do_esync(void);
+void esync_init(void);
diff --git a/server/main.c b/server/main.c
index 2b5065e1852..385ae5ee370 100644
--- a/server/main.c
+++ b/server/main.c
@@ -36,6 +36,7 @@
#include "file.h"
#include "thread.h"
#include "request.h"
+#include "esync.h"
/* command-line options */
int debug_level = 0;
@@ -140,6 +141,9 @@ int main( int argc, char *argv[] )
sock_init();
open_master_socket();
+ if (do_esync())
+ esync_init();
+
if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() );
set_current_time();
init_scheduler();
diff --git a/server/protocol.def b/server/protocol.def
index 007ef1f67..cd97ba008 100644
index 5ca762fdabf..552d504cc8d 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4021,3 +4021,13 @@ struct handle_info
unsigned int threads; /* number of threads */
unsigned int handles; /* number of handles */
@@ -3665,3 +3665,27 @@ struct handle_info
@REQ(resume_process)
obj_handle_t handle; /* process handle */
@END
+
+enum esync_type
+{
+ ESYNC_SEMAPHORE = 1,
+ ESYNC_AUTO_EVENT,
+ ESYNC_MANUAL_EVENT,
+ ESYNC_MUTEX,
+ ESYNC_AUTO_SERVER,
+ ESYNC_MANUAL_SERVER,
+ ESYNC_QUEUE,
+};
+
+/* Create a new eventfd-based synchronization object */
+@REQ(create_esync)
+ unsigned int access; /* wanted access rights */
+ int initval; /* initial value */
+ int flags; /* flags (EFD_SEMAPHORE or 0) */
+ int type; /* type of esync object */
+ int max; /* maximum count on a semaphore */
+ VARARG(objattr,object_attributes); /* object attributes */
+@REPLY
+ obj_handle_t handle; /* handle to the object */
+ int type; /* actual type (may be different for events) */
+ unsigned int shm_idx;
+@END
--
2.21.0
2.28.0

View File

@ -0,0 +1,108 @@
From e5a3456cde339352e78b10fed8a2fc65ca560041 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:16:34 -0500
Subject: [PATCH] ntdll: Implement NtReleaseSemaphore().
---
dlls/ntdll/unix/esync.c | 43 +++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 3 +++
3 files changed, 47 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 7c409c7a9ca..8f28a36d93f 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -28,6 +28,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
@@ -173,6 +174,16 @@ static struct esync *add_to_list( HANDLE handle, enum esync_type type, int fd, v
return &esync_list[entry][idx];
}
+static struct esync *get_cached_object( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL;
+ if (!esync_list[entry][idx].type) return NULL;
+
+ return &esync_list[entry][idx];
+}
+
static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int max )
{
@@ -228,6 +239,38 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
return create_esync( ESYNC_SEMAPHORE, handle, access, attr, initial, max );
}
+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
+{
+ struct esync *obj;
+ struct semaphore *semaphore;
+ uint64_t count64 = count;
+ ULONG current;
+
+ TRACE("%p, %d, %p.\n", handle, count, prev);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+ semaphore = obj->shm;
+
+ do
+ {
+ current = semaphore->count;
+
+ if (count + current > semaphore->max)
+ return STATUS_SEMAPHORE_LIMIT_EXCEEDED;
+ } while (InterlockedCompareExchange( &semaphore->count, count + current, current ) != current);
+
+ if (prev) *prev = current;
+
+ /* We don't have to worry about a race between increasing the count and
+ * write(). The fact that we were able to increase the count means that we
+ * have permission to actually write that many releases to the semaphore. */
+
+ if (write( obj->fd, &count64, sizeof(count64) ) == -1)
+ return errno_to_status( errno );
+
+ return STATUS_SUCCESS;
+}
+
void esync_init(void)
{
struct stat st;
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index a50a755149a..09838e95535 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -23,6 +23,7 @@ extern void esync_init(void) DECLSPEC_HIDDEN;
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 663a170fc61..f4bcda4b473 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -407,6 +407,9 @@ NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, ULONG *previous
{
NTSTATUS ret;
+ if (do_esync())
+ return esync_release_semaphore( handle, count, previous );
+
SERVER_START_REQ( release_semaphore )
{
req->handle = wine_server_obj_handle( handle );
--
2.28.0

View File

@ -1,123 +0,0 @@
From 3f6f2c22a0ee8e7c9067b74aef67018ed0739484 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 20:45:57 -0500
Subject: [PATCH 04/83] ntdll: Store esync objects locally.
Slight tweak for optimization: return UINT_PTR instead, and remove a useless
cmpxchg.
---
dlls/ntdll/esync.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index da35bdf85..2bb85d910 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -19,6 +19,7 @@
*/
#include "config.h"
+#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
@@ -26,6 +27,9 @@
#ifdef HAVE_SYS_EVENTFD_H
# include <sys/eventfd.h>
#endif
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -34,6 +38,7 @@
#include "winternl.h"
#include "wine/server.h"
#include "wine/debug.h"
+#include "wine/library.h"
#include "ntdll_misc.h"
#include "esync.h"
@@ -78,6 +83,59 @@ struct semaphore
int max;
};
+/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
+ * This is copied and adapted from the fd cache code. */
+
+#define ESYNC_LIST_BLOCK_SIZE (65536 / sizeof(struct esync *))
+#define ESYNC_LIST_ENTRIES 128
+
+static struct esync * *esync_list[ESYNC_LIST_ENTRIES];
+static struct esync * esync_list_initial_block[ESYNC_LIST_BLOCK_SIZE];
+
+static inline UINT_PTR handle_to_index( HANDLE handle, UINT_PTR *entry )
+{
+ UINT_PTR idx = (((UINT_PTR)handle) >> 2) - 1;
+ *entry = idx / ESYNC_LIST_BLOCK_SIZE;
+ return idx % ESYNC_LIST_BLOCK_SIZE;
+}
+
+static BOOL add_to_list( HANDLE handle, struct esync *obj )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES)
+ {
+ FIXME( "too many allocated handles, not caching %p\n", handle );
+ return FALSE;
+ }
+
+ if (!esync_list[entry]) /* do we need to allocate a new block of entries? */
+ {
+ if (!entry) esync_list[0] = esync_list_initial_block;
+ else
+ {
+ void *ptr = wine_anon_mmap( NULL, ESYNC_LIST_BLOCK_SIZE * sizeof(struct esync *),
+ PROT_READ | PROT_WRITE, 0 );
+ if (ptr == MAP_FAILED) return FALSE;
+ esync_list[entry] = ptr;
+ }
+ }
+
+ obj = InterlockedExchangePointer((void **)&esync_list[entry][idx], obj);
+ assert(!obj);
+ return TRUE;
+}
+
+static void *esync_get_object( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ if (entry >= ESYNC_LIST_ENTRIES || !esync_list[entry]) return NULL;
+
+ return esync_list[entry][idx];
+}
+
+
static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int flags)
{
@@ -115,7 +173,7 @@ static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
return ret;
}
-extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
+NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max)
{
struct semaphore *semaphore;
@@ -135,6 +193,8 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
semaphore->obj.type = ESYNC_SEMAPHORE;
semaphore->obj.fd = fd;
semaphore->max = max;
+
+ add_to_list( *handle, &semaphore->obj );
}
return ret;
--
2.20.1

View File

@ -0,0 +1,77 @@
From f0d0cdcb048b4af8003ba5279bd90293ecc7f8ba Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:20:44 -0500
Subject: [PATCH] ntdll: Implement NtClose().
---
dlls/ntdll/unix/esync.c | 18 ++++++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/server.c | 4 ++++
3 files changed, 23 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 8f28a36d93f..02b07bf36be 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -184,6 +184,24 @@ static struct esync *get_cached_object( HANDLE handle )
return &esync_list[entry][idx];
}
+NTSTATUS esync_close( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+
+ TRACE("%p.\n", handle);
+
+ if (entry < ESYNC_LIST_ENTRIES && esync_list[entry])
+ {
+ if (InterlockedExchange((int *)&esync_list[entry][idx].type, 0))
+ {
+ close( esync_list[entry][idx].fd );
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_HANDLE;
+}
+
static NTSTATUS create_esync( enum esync_type type, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int max )
{
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 09838e95535..14e52416764 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -20,6 +20,7 @@
extern int do_esync(void) DECLSPEC_HIDDEN;
extern void esync_init(void) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 971341bf6e0..d8837f6fde0 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -88,6 +88,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "unix_private.h"
+#include "esync.h"
#include "ddk/wdm.h"
WINE_DEFAULT_DEBUG_CHANNEL(server);
@@ -1644,6 +1645,9 @@ NTSTATUS WINAPI NtClose( HANDLE handle )
NTSTATUS ret;
int fd = remove_fd_from_cache( handle );
+ if (do_esync())
+ esync_close( handle );
+
SERVER_START_REQ( close_handle )
{
req->handle = wine_server_obj_handle( handle );
--
2.28.0

View File

@ -1,78 +0,0 @@
From eb0273dfd273f1f6c48db45b444ec318fe514699 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 21:02:14 -0500
Subject: [PATCH 05/83] ntdll: Implement NtReleaseSemaphore().
---
dlls/ntdll/esync.c | 22 ++++++++++++++++++++++
dlls/ntdll/esync.h | 1 +
dlls/ntdll/sync.c | 4 ++++
3 files changed, 27 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 2bb85d910..bca95b9b2 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -23,6 +23,7 @@
#include <assert.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#ifdef HAVE_SYS_EVENTFD_H
# include <sys/eventfd.h>
@@ -199,3 +200,24 @@ NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
return ret;
}
+
+NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
+{
+ struct semaphore *semaphore = esync_get_object( handle );
+ uint64_t count64 = count;
+
+ TRACE("%p, %d, %p.\n", handle, count, prev);
+
+ if (!semaphore) return STATUS_INVALID_HANDLE;
+
+ if (prev)
+ {
+ FIXME("Can't write previous value.\n");
+ *prev = 1;
+ }
+
+ if (write( semaphore->obj.fd, &count64, sizeof(count64) ) == -1)
+ return FILE_GetNtStatus();
+
+ return STATUS_SUCCESS;
+}
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index 1a88170cf..fec0b68e8 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -22,6 +22,7 @@ extern int do_esync(void) DECLSPEC_HIDDEN;
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
/* We have to synchronize on the fd cache CS so that our calls to receive_fd
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index c259267fb..93052ddb5 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -333,6 +333,10 @@ NTSTATUS WINAPI NtQuerySemaphore( HANDLE handle, SEMAPHORE_INFORMATION_CLASS cla
NTSTATUS WINAPI NtReleaseSemaphore( HANDLE handle, ULONG count, PULONG previous )
{
NTSTATUS ret;
+
+ if (do_esync())
+ return esync_release_semaphore( handle, count, previous );
+
SERVER_START_REQ( release_semaphore )
{
req->handle = wine_server_obj_handle( handle );
--
2.20.1

View File

@ -1,78 +0,0 @@
From 2aba7f5090f92b609f6d2763603dbeb761f9c65a Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 21:07:51 -0500
Subject: [PATCH] ntdll: Close esync objects.
---
dlls/ntdll/esync.c | 19 +++++++++++++++++++
dlls/ntdll/esync.h | 1 +
dlls/ntdll/om.c | 4 ++++
3 files changed, 24 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index bca95b9b2d9..f7a427425b7 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -136,6 +136,25 @@ static void *esync_get_object( HANDLE handle )
return esync_list[entry][idx];
}
+NTSTATUS esync_close( HANDLE handle )
+{
+ UINT_PTR entry, idx = handle_to_index( handle, &entry );
+ struct esync *obj;
+
+ TRACE("%p.\n", handle);
+
+ if (entry < ESYNC_LIST_ENTRIES && esync_list[entry])
+ {
+ if ((obj = InterlockedExchangePointer( (void **)&esync_list[entry][idx], 0 )))
+ {
+ close( obj->fd );
+ RtlFreeHeap( GetProcessHeap(), 0, obj );
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_HANDLE;
+}
static NTSTATUS create_esync(int *fd, HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, int initval, int flags)
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index fec0b68e8d5..a22618de849 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -19,6 +19,7 @@
*/
extern int do_esync(void) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index f8f0760de70..b8d73a982b2 100644
--- a/dlls/ntdll/om.c
+++ b/dlls/ntdll/om.c
@@ -34,6 +34,7 @@
#include "windef.h"
#include "winternl.h"
#include "ntdll_misc.h"
+#include "esync.h"
#include "wine/server.h"
#include "wine/exception.h"
@@ -387,6 +388,9 @@ NTSTATUS close_handle( HANDLE handle )
NTSTATUS ret;
int fd = server_remove_fd_from_cache( handle );
+ if (do_esync())
+ esync_close( handle );
+
SERVER_START_REQ( close_handle )
{
req->handle = wine_server_obj_handle( handle );
--
2.26.0

View File

@ -1,39 +1,48 @@
From bb968ec541ccdcd1b04b4b967065d5ee81f3fd78 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Thu, 7 Jun 2018 21:23:52 -0500
Subject: [PATCH] ntdll: Implement waiting on esync objects.
From 908363daafc3b5220967d31e2e878f617d465026 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 12:34:42 -0500
Subject: [PATCH] ntdll: Implement NtWaitForMultipleObjects().
This is the most basic case: WAIT_ANY. We use poll() (actually ppoll(), for
the better granularity) to select on all of the handles that we can.
---
dlls/ntdll/esync.c | 161 +++++++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/esync.h | 3 +
dlls/ntdll/sync.c | 7 ++
3 files changed, 171 insertions(+)
dlls/ntdll/unix/esync.c | 170 ++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 3 +
dlls/ntdll/unix/sync.c | 7 ++
3 files changed, 180 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index f7a427425..f6ceefe53 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -22,6 +22,13 @@
#include "wine/port.h"
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 02b07bf36be..1b71105491c 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -22,17 +22,25 @@
#pragma makedep unix
#endif
+#define _GNU_SOURCE
+
#include "config.h"
#include <assert.h>
+#include <errno.h>
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
@@ -240,3 +247,157 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
@@ -289,6 +297,168 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
return STATUS_SUCCESS;
}
+
+#define TICKSPERSEC 10000000
+#define TICKSPERMSEC 10000
+
@ -68,6 +77,19 @@ index f7a427425..f6ceefe53 100644
+ return poll( fds, nfds, -1 );
+}
+
+static void update_grabbed_object( struct esync *obj )
+{
+ if (obj->type == ESYNC_SEMAPHORE)
+ {
+ struct semaphore *semaphore = obj->shm;
+ /* We don't have to worry about a race between this and read(); the
+ * fact that we were able to grab it at all means the count is nonzero,
+ * and if someone else grabbed it then the count must have been >= 2,
+ * etc. */
+ InterlockedExchangeAdd( &semaphore->count, -1 );
+ }
+}
+
+/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
+ * need to delegate to server_select(). */
+NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
@ -79,8 +101,7 @@ index f7a427425..f6ceefe53 100644
+ LONGLONG timeleft;
+ LARGE_INTEGER now;
+ ULONGLONG end;
+ int ret;
+ int i;
+ int i, ret;
+
+ NtQuerySystemTime( &now );
+ if (timeout)
@ -95,23 +116,16 @@ index f7a427425..f6ceefe53 100644
+
+ for (i = 0; i < count; i++)
+ {
+ objs[i] = esync_get_object( handles[i] );
+ if (objs[i])
+ if ((objs[i] = get_cached_object( handles[i] )))
+ has_esync = 1;
+ else
+ has_server = 1;
+ }
+
+ if (has_esync && has_server)
+ {
+ FIXME("Can't wait on esync and server objects at the same time!\n");
+ /* Wait on just the eventfds; it's the best we can do. */
+ }
+ else if (has_server)
+ {
+ /* It's just server objects, so delegate to the server. */
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ if (TRACE_ON(esync))
+ {
@ -145,13 +159,15 @@ index f7a427425..f6ceefe53 100644
+ /* Find out which object triggered the wait. */
+ for (i = 0; i < count; i++)
+ {
+ struct esync *obj = objs[i];
+
+ if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ ERR("Polling on fd %d returned %#x.\n", fds[i].fd, fds[i].revents);
+ return STATUS_INVALID_HANDLE;
+ }
+
+ if (objs[i])
+ if (obj)
+ {
+ int64_t value;
+ ssize_t size;
@ -160,6 +176,7 @@ index f7a427425..f6ceefe53 100644
+ {
+ /* We found our object. */
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
+ update_grabbed_object( obj );
+ return i;
+ }
+ }
@ -176,8 +193,8 @@ index f7a427425..f6ceefe53 100644
+ }
+ else
+ {
+ ERR("ppoll failed: %s\n", strerror(errno));
+ return FILE_GetNtStatus();
+ ERR("ppoll failed: %s\n", strerror( errno ));
+ return errno_to_status( errno );
+ }
+ }
+ }
@ -187,11 +204,15 @@ index f7a427425..f6ceefe53 100644
+ return STATUS_NOT_IMPLEMENTED;
+ }
+}
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index a22618de8..8f7f9b030 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -25,6 +25,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
+
void esync_init(void)
{
struct stat st;
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 14e52416764..87516e7597a 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
@ -199,13 +220,13 @@ index a22618de8..8f7f9b030 100644
+ BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
+
/* We have to synchronize on the fd cache CS so that our calls to receive_fd
/* We have to synchronize on the fd cache mutex so that our calls to receive_fd
* don't race with theirs. It looks weird, I know.
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 93052ddb5..40bc619a2 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -1089,6 +1089,13 @@ static NTSTATUS wait_objects( DWORD count, const HANDLE *handles,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index f4bcda4b473..445c2a4324d 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -1273,6 +1273,13 @@ NTSTATUS WINAPI NtWaitForMultipleObjects( DWORD count, const HANDLE *handles, BO
if (!count || count > MAXIMUM_WAIT_OBJECTS) return STATUS_INVALID_PARAMETER_1;
@ -220,5 +241,5 @@ index 93052ddb5..40bc619a2 100644
select_op.wait.op = wait_any ? SELECT_WAIT : SELECT_WAIT_ALL;
for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
--
2.21.0
2.28.0

View File

@ -0,0 +1,128 @@
From d8cf82ba904cfa956dc5e2146ab98afa6efc46ff Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:40:43 -0500
Subject: [PATCH] ntdll, server: Implement NtCreateEvent().
---
dlls/ntdll/unix/esync.c | 27 +++++++++++++++++++++++++++
dlls/ntdll/unix/esync.h | 3 +++
dlls/ntdll/unix/sync.c | 3 +++
server/esync.c | 15 +++++++++++++++
4 files changed, 48 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 1b71105491c..e440e9baa4a 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -91,6 +91,13 @@ struct semaphore
};
C_ASSERT(sizeof(struct semaphore) == 8);
+struct event
+{
+ int signaled;
+ int locked;
+};
+C_ASSERT(sizeof(struct event) == 8);
+
static char shm_name[29];
static int shm_fd;
static void **shm_addrs;
@@ -297,6 +304,18 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
return STATUS_SUCCESS;
}
+NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE event_type, BOOLEAN initial )
+{
+ enum esync_type type = (event_type == SynchronizationEvent ? ESYNC_AUTO_EVENT : ESYNC_MANUAL_EVENT);
+
+ TRACE("name %s, %s-reset, initial %d.\n",
+ attr ? debugstr_us(attr->ObjectName) : "<no name>",
+ event_type == NotificationEvent ? "manual" : "auto", initial);
+
+ return create_esync( type, handle, access, attr, initial, 0 );
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
@@ -342,6 +361,14 @@ static void update_grabbed_object( struct esync *obj )
* etc. */
InterlockedExchangeAdd( &semaphore->count, -1 );
}
+ else if (obj->type == ESYNC_AUTO_EVENT)
+ {
+ struct event *event = obj->shm;
+ /* We don't have to worry about a race between this and read(), since
+ * this is just a hint, and the real state is in the kernel object.
+ * This might already be 0, but that's okay! */
+ event->signaled = 0;
+ }
}
/* A value of STATUS_NOT_IMPLEMENTED returned from this function means that we
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index 87516e7597a..d9c7df967f8 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -26,6 +26,9 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
+
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 445c2a4324d..51f77b1015f 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -434,6 +434,9 @@ NTSTATUS WINAPI NtCreateEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_
data_size_t len;
struct object_attributes *objattr;
+ if (do_esync())
+ return esync_create_event( handle, access, attr, type, state );
+
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
SERVER_START_REQ( create_event )
diff --git a/server/esync.c b/server/esync.c
index 226e70cd1ad..b9e0a455629 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -203,6 +203,13 @@ struct semaphore
};
C_ASSERT(sizeof(struct semaphore) == 8);
+struct event
+{
+ int signaled;
+ int locked;
+};
+C_ASSERT(sizeof(struct event) == 8);
+
struct esync *create_esync( struct object *root, const struct unicode_str *name,
unsigned int attr, int initval, int max, enum esync_type type,
const struct security_descriptor *sd )
@@ -258,6 +265,14 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name,
semaphore->count = initval;
break;
}
+ case ESYNC_AUTO_EVENT:
+ case ESYNC_MANUAL_EVENT:
+ {
+ struct event *event = get_shm( esync->shm_idx );
+ event->signaled = initval ? 1 : 0;
+ event->locked = 0;
+ break;
+ }
default:
assert( 0 );
}
--
2.28.0

View File

@ -1,100 +0,0 @@
From 0ab9981b2309831fb12ee778e026cb1b4651dab6 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 15:33:46 -0500
Subject: [PATCH 08/83] ntdll: Create esync objects for events.
---
dlls/ntdll/esync.c | 34 ++++++++++++++++++++++++++++++++++
dlls/ntdll/esync.h | 2 ++
dlls/ntdll/sync.c | 3 +++
3 files changed, 39 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 0950d8b5a..ace2f4a45 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -77,6 +77,8 @@ int do_esync(void)
enum esync_type
{
ESYNC_SEMAPHORE = 1,
+ ESYNC_AUTO_EVENT,
+ ESYNC_MANUAL_EVENT,
};
struct esync
@@ -91,6 +93,11 @@ struct semaphore
int max;
};
+struct event
+{
+ struct esync obj;
+};
+
/* We'd like lookup to be fast. To that end, we use a static list indexed by handle.
* This is copied and adapted from the fd cache code. */
@@ -248,6 +255,33 @@ NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev )
return STATUS_SUCCESS;
}
+NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial )
+{
+ struct event *event;
+ NTSTATUS ret;
+ int fd;
+
+ TRACE("name %s, %s-reset, initial %d.\n",
+ attr ? debugstr_us(attr->ObjectName) : "<no name>",
+ type == NotificationEvent ? "manual" : "auto", initial);
+
+ ret = create_esync( &fd, handle, access, attr, initial, 0 );
+ if (!ret || ret == STATUS_OBJECT_NAME_EXISTS)
+ {
+ event = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*event) );
+ if (!event)
+ return STATUS_NO_MEMORY;
+
+ event->obj.type = (type == NotificationEvent ? ESYNC_MANUAL_EVENT : ESYNC_AUTO_EVENT);
+ event->obj.fd = fd;
+
+ add_to_list( *handle, &event->obj);
+ }
+
+ return ret;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index 8f7f9b030..32a259e39 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -24,6 +24,8 @@ extern NTSTATUS esync_close( HANDLE handle ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, LONG initial, LONG max) DECLSPEC_HIDDEN;
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
+ const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 40bc619a2..6f0e72125 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -365,6 +365,9 @@ NTSTATUS WINAPI NtCreateEvent( PHANDLE EventHandle, ACCESS_MASK DesiredAccess,
data_size_t len;
struct object_attributes *objattr;
+ if (do_esync())
+ return esync_create_event( EventHandle, DesiredAccess, attr, type, InitialState );
+
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
SERVER_START_REQ( create_event )
--
2.20.1

View File

@ -0,0 +1,66 @@
From cc0ae54c2b35967c6cebc1ec2f6c5058e7027185 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:46:24 -0500
Subject: [PATCH] ntdll: Implement NtSetEvent().
---
dlls/ntdll/unix/esync.c | 15 +++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 3 +++
3 files changed, 19 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index e440e9baa4a..b8fb27edf38 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -316,6 +316,21 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
return create_esync( type, handle, access, attr, initial, 0 );
}
+NTSTATUS esync_set_event( HANDLE handle )
+{
+ static const uint64_t value = 1;
+ struct esync *obj;
+
+ TRACE("%p.\n", handle);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+
+ if (write( obj->fd, &value, sizeof(value) ) == -1)
+ ERR("write: %s\n", strerror(errno));
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index d9c7df967f8..b585af047ee 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -28,6 +28,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 51f77b1015f..60be9a0885a 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -486,6 +486,9 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
{
NTSTATUS ret;
+ if (do_esync())
+ return esync_set_event( handle );
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.28.0

View File

@ -0,0 +1,66 @@
From 333c6f445c9a0c2ef8b055e970e53b6c2b160ded Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:51:21 -0500
Subject: [PATCH] ntdll: Implement NtResetEvent().
---
dlls/ntdll/unix/esync.c | 15 +++++++++++++++
dlls/ntdll/unix/esync.h | 1 +
dlls/ntdll/unix/sync.c | 3 +++
3 files changed, 19 insertions(+)
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index b8fb27edf38..97d468b2449 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -331,6 +331,21 @@ NTSTATUS esync_set_event( HANDLE handle )
return STATUS_SUCCESS;
}
+NTSTATUS esync_reset_event( HANDLE handle )
+{
+ uint64_t value;
+ struct esync *obj;
+
+ TRACE("%p.\n", handle);
+
+ if (!(obj = get_cached_object( handle ))) return STATUS_INVALID_HANDLE;
+
+ if (read( obj->fd, &value, sizeof(value) ) == -1 && errno != EWOULDBLOCK && errno != EAGAIN)
+ ERR("read: %s\n", strerror(errno));
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/unix/esync.h b/dlls/ntdll/unix/esync.h
index b585af047ee..8480a213b2a 100644
--- a/dlls/ntdll/unix/esync.h
+++ b/dlls/ntdll/unix/esync.h
@@ -28,6 +28,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_reset_event( HANDLE handle ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_set_event( HANDLE handle ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c
index 60be9a0885a..1d2e831964f 100644
--- a/dlls/ntdll/unix/sync.c
+++ b/dlls/ntdll/unix/sync.c
@@ -508,6 +508,9 @@ NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
{
NTSTATUS ret;
+ if (do_esync())
+ return esync_reset_event( handle );
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.28.0

View File

@ -1,73 +0,0 @@
From b3f22ae85154f22532b66362a2399592d755ce33 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 15:41:01 -0500
Subject: [PATCH 09/83] ntdll: Implement NtSetEvent().
---
dlls/ntdll/esync.c | 21 +++++++++++++++++++++
dlls/ntdll/esync.h | 1 +
dlls/ntdll/sync.c | 4 ++++
3 files changed, 26 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index ace2f4a45..62c56af75 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -282,6 +282,27 @@ NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
return ret;
}
+NTSTATUS esync_set_event( HANDLE handle, LONG *prev )
+{
+ struct event *event = esync_get_object( handle );
+ static const uint64_t value = 1;
+
+ TRACE("%p.\n", handle);
+
+ if (!event) return STATUS_INVALID_HANDLE;
+
+ if (prev)
+ {
+ FIXME("Can't write previous value.\n");
+ *prev = 1;
+ }
+
+ if (write( event->obj.fd, &value, sizeof(value) ) == -1)
+ return FILE_GetNtStatus();
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index 32a259e39..ba1c89665 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -26,6 +26,7 @@ extern NTSTATUS esync_create_semaphore(HANDLE *handle, ACCESS_MASK access,
extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 6f0e72125..1e1e381b4 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -417,6 +417,10 @@ NTSTATUS WINAPI NtOpenEvent( HANDLE *handle, ACCESS_MASK access, const OBJECT_AT
NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
{
NTSTATUS ret;
+
+ if (do_esync())
+ return esync_set_event( handle, prev_state );
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.20.1

View File

@ -1,73 +0,0 @@
From 022deba562034611dccefaf2af504861e391fe7c Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 15:44:49 -0500
Subject: [PATCH 10/83] ntdll: Implement NtResetEvent().
---
dlls/ntdll/esync.c | 21 +++++++++++++++++++++
dlls/ntdll/esync.h | 1 +
dlls/ntdll/sync.c | 4 ++++
3 files changed, 26 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 62c56af75..9e091819a 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -303,6 +303,27 @@ NTSTATUS esync_set_event( HANDLE handle, LONG *prev )
return STATUS_SUCCESS;
}
+NTSTATUS esync_reset_event( HANDLE handle, LONG *prev )
+{
+ struct event *event = esync_get_object( handle );
+ static uint64_t value;
+
+ TRACE("%p.\n", handle);
+
+ if (!event) return STATUS_INVALID_HANDLE;
+
+ if (prev)
+ {
+ FIXME("Can't write previous value.\n");
+ *prev = 1;
+ }
+
+ /* we don't care about the return value */
+ read( event->obj.fd, &value, sizeof(value) );
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index ba1c89665..8d2b4683e 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -27,6 +27,7 @@ extern NTSTATUS esync_release_semaphore( HANDLE handle, ULONG count, ULONG *prev
extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 1e1e381b4..4be641eb5 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -438,6 +438,10 @@ NTSTATUS WINAPI NtSetEvent( HANDLE handle, LONG *prev_state )
NTSTATUS WINAPI NtResetEvent( HANDLE handle, LONG *prev_state )
{
NTSTATUS ret;
+
+ if (do_esync())
+ return esync_reset_event( handle, prev_state );
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.20.1

View File

@ -1,27 +1,26 @@
From ba99a79e4ed4be4525e14aec71eaf52421580c32 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 15:55:39 -0500
Subject: [PATCH 12/83] ntdll: Implement waiting on events.
More specifically, implement waiting on manual-reset events. Auto-reset events already worked.
From f260254e168fbaad0321273037762e218eb6b7a6 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 14:57:42 -0500
Subject: [PATCH] ntdll: Implement waiting on manual-reset events.
---
dlls/ntdll/esync.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
dlls/ntdll/unix/esync.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 1055e11ae..7a384dc61 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -471,11 +471,23 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
diff --git a/dlls/ntdll/unix/esync.c b/dlls/ntdll/unix/esync.c
index 97d468b2449..4f993689e0d 100644
--- a/dlls/ntdll/unix/esync.c
+++ b/dlls/ntdll/unix/esync.c
@@ -483,12 +483,24 @@ NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_an
int64_t value;
ssize_t size;
- if ((size = read( fds[i].fd, &value, sizeof(value) )) == sizeof(value))
+ if (objs[i]->type == ESYNC_MANUAL_EVENT)
+ if (obj->type == ESYNC_MANUAL_EVENT)
{
- /* We found our object. */
- TRACE("Woken up by handle %p [%d].\n", handles[i], i);
- update_grabbed_object( obj );
- return i;
+ /* Don't grab the object, just check if it's signaled. */
+ if (fds[i].revents & POLLIN)
@ -36,11 +35,12 @@ index 1055e11ae..7a384dc61 100644
+ {
+ /* We found our object. */
+ TRACE("Woken up by handle %p [%d].\n", handles[i], i);
+ update_grabbed_object( obj );
+ return i;
+ }
}
}
}
--
2.20.1
2.28.0

View File

@ -1,76 +0,0 @@
From 728fb6100bab81223baad2815878fccfe7fe17a6 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 15:47:16 -0500
Subject: [PATCH 11/83] ntdll: Implement NtPulseEvent().
---
dlls/ntdll/esync.c | 25 +++++++++++++++++++++++++
dlls/ntdll/esync.h | 1 +
dlls/ntdll/sync.c | 3 +++
3 files changed, 29 insertions(+)
diff --git a/dlls/ntdll/esync.c b/dlls/ntdll/esync.c
index 9e091819a..1055e11ae 100644
--- a/dlls/ntdll/esync.c
+++ b/dlls/ntdll/esync.c
@@ -324,6 +324,31 @@ NTSTATUS esync_reset_event( HANDLE handle, LONG *prev )
return STATUS_SUCCESS;
}
+NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev )
+{
+ struct event *event = esync_get_object( handle );
+ static uint64_t value = 1;
+
+ TRACE("%p.\n", handle);
+
+ if (!event) return STATUS_INVALID_HANDLE;
+
+ if (prev)
+ {
+ FIXME("Can't write previous value.\n");
+ *prev = 1;
+ }
+
+ /* This isn't really correct; an application could miss the write.
+ * Unfortunately we can't really do much better. Fortunately this is rarely
+ * used (and publicly deprecated). */
+ if (write( event->obj.fd, &value, sizeof(value) ) == -1)
+ return FILE_GetNtStatus();
+ read( event->obj.fd, &value, sizeof(value) );
+
+ return STATUS_SUCCESS;
+}
+
#define TICKSPERSEC 10000000
#define TICKSPERMSEC 10000
diff --git a/dlls/ntdll/esync.h b/dlls/ntdll/esync.h
index 8d2b4683e..551257fbc 100644
--- a/dlls/ntdll/esync.h
+++ b/dlls/ntdll/esync.h
@@ -28,6 +28,7 @@ extern NTSTATUS esync_create_event( HANDLE *handle, ACCESS_MASK access,
const OBJECT_ATTRIBUTES *attr, EVENT_TYPE type, BOOLEAN initial ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_set_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_reset_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
+extern NTSTATUS esync_pulse_event( HANDLE handle, LONG *prev ) DECLSPEC_HIDDEN;
extern NTSTATUS esync_wait_objects( DWORD count, const HANDLE *handles, BOOLEAN wait_any,
BOOLEAN alertable, const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 4be641eb5..74b50cbc7 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -474,6 +474,9 @@ NTSTATUS WINAPI NtPulseEvent( HANDLE handle, LONG *prev_state )
{
NTSTATUS ret;
+ if (do_esync())
+ return esync_pulse_event( handle, prev_state );
+
SERVER_START_REQ( event_op )
{
req->handle = wine_server_obj_handle( handle );
--
2.20.1

View File

@ -1,19 +1,19 @@
From 74d7000943e1037303294332b415b0b4b5e8291c Mon Sep 17 00:00:00 2001
From 193c44f510beed365640159cbdaeb0cb8186a7b0 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 18:55:49 -0500
Subject: [PATCH 14/83] server: Add a request to get the eventfd file
descriptor associated with a waitable handle.
Subject: [PATCH] server: Add a request to get the eventfd file descriptor
associated with a waitable handle.
---
server/esync.c | 28 ++++++++++++++++++++++++++++
server/protocol.def | 6 ++++++
2 files changed, 34 insertions(+)
server/esync.c | 37 +++++++++++++++++++++++++++++++++++++
server/protocol.def | 8 ++++++++
2 files changed, 45 insertions(+)
diff --git a/server/esync.c b/server/esync.c
index f3a139da4..351da1a7c 100644
index d646cb52bc2..cfbbcf55c48 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -136,3 +136,31 @@ DECL_HANDLER(create_esync)
@@ -335,3 +335,40 @@ DECL_HANDLER(create_esync)
if (root) release_object( root );
}
@ -23,6 +23,7 @@ index f3a139da4..351da1a7c 100644
+DECL_HANDLER(get_esync_fd)
+{
+ struct object *obj;
+ enum esync_type type;
+ int fd;
+
+ if (!(obj = get_handle_obj( current->process, req->handle, SYNCHRONIZE, NULL )))
@ -30,7 +31,15 @@ index f3a139da4..351da1a7c 100644
+
+ if (obj->ops->get_esync_fd)
+ {
+ fd = obj->ops->get_esync_fd( obj );
+ fd = obj->ops->get_esync_fd( obj, &type );
+ reply->type = type;
+ if (obj->ops == &esync_ops)
+ {
+ struct esync *esync = (struct esync *)obj;
+ reply->shm_idx = esync->shm_idx;
+ }
+ else
+ reply->shm_idx = 0;
+ send_client_fd( current->process, fd, req->handle );
+ }
+ else
@ -46,19 +55,21 @@ index f3a139da4..351da1a7c 100644
+ release_object( obj );
+}
diff --git a/server/protocol.def b/server/protocol.def
index a56f098ab..5f2d77bc7 100644
index 552d504cc8d..9062a5020c2 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -4051,3 +4051,9 @@ struct handle_info
@REPLY
obj_handle_t handle; /* handle to the object */
@@ -3689,3 +3689,11 @@ enum esync_type
int type; /* actual type (may be different for events) */
unsigned int shm_idx;
@END
+
+/* Retrieve the esync fd for an object. */
+@REQ(get_esync_fd)
+ obj_handle_t handle; /* handle to the object */
+@REPLY
+ int type;
+ unsigned int shm_idx;
+@END
--
2.20.1
2.28.0

View File

@ -1,43 +1,20 @@
From e6e0ef574ce53d5b5e94068ae9dc137c2c7dee92 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <z.figura12@gmail.com>
Date: Fri, 8 Jun 2018 18:57:12 -0500
From 05c4a58d8cc0fbafc760d3a0d4d6c14975e33fe2 Mon Sep 17 00:00:00 2001
From: Zebediah Figura <zfigura@codeweavers.com>
Date: Mon, 6 Jul 2020 15:11:12 -0500
Subject: [PATCH] server: Create eventfd file descriptors for process objects.
---
server/esync.c | 33 +++++++++++++++++++++++++++++++++
server/esync.h | 22 ++++++++++++++++++++++
server/process.c | 17 ++++++++++++++++-
server/esync.c | 18 ++++++++++++++++++
server/esync.h | 1 +
server/process.c | 16 +++++++++++++++-
server/process.h | 1 +
4 files changed, 72 insertions(+), 1 deletion(-)
create mode 100644 server/esync.h
4 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/server/esync.c b/server/esync.c
index 351da1a7cb2..da26d27cbc8 100644
index cfbbcf55c48..61513333bfd 100644
--- a/server/esync.c
+++ b/server/esync.c
@@ -35,6 +35,21 @@
#include "handle.h"
#include "request.h"
#include "file.h"
+#include "esync.h"
+
+int do_esync(void)
+{
+#ifdef HAVE_SYS_EVENTFD_H
+ static int do_esync_cached = -1;
+
+ if (do_esync_cached == -1)
+ do_esync_cached = (getenv("WINEESYNC") != NULL);
+
+ return do_esync_cached;
+#else
+ return 0;
+#endif
+}
struct esync
{
@@ -112,6 +127,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name,
@@ -297,6 +297,24 @@ struct esync *create_esync( struct object *root, const struct unicode_str *name,
#endif
}
@ -63,38 +40,19 @@ index 351da1a7cb2..da26d27cbc8 100644
{
struct esync *esync;
diff --git a/server/esync.h b/server/esync.h
new file mode 100644
index 00000000000..f93535b7b4c
--- /dev/null
index 7ca4ca89394..6a0a367124d 100644
--- a/server/esync.h
+++ b/server/esync.h
@@ -0,0 +1,22 @@
+/*
+ * eventfd-based synchronization objects
+ *
+ * Copyright (C) 2018 Zebediah Figura
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern int do_esync(void);
@@ -20,3 +20,4 @@
extern int do_esync(void);
void esync_init(void);
+int esync_create_fd( int initval, int flags );
diff --git a/server/process.c b/server/process.c
index c4cb041f293..ed03210a5f5 100644
index 30699fbaeae..febfc0237c6 100644
--- a/server/process.c
+++ b/server/process.c
@@ -48,6 +48,7 @@
@@ -49,6 +49,7 @@
#include "request.h"
#include "user.h"
#include "security.h"
@ -102,15 +60,15 @@ index c4cb041f293..ed03210a5f5 100644
/* process structure */
@@ -67,6 +68,7 @@ static struct security_descriptor *process_get_sd( struct object *obj );
@@ -68,6 +69,7 @@ static struct security_descriptor *process_get_sd( struct object *obj );
static void process_poll_event( struct fd *fd, int event );
static struct list *process_get_kernel_obj_list( struct object *obj );
static void process_destroy( struct object *obj );
+static int process_get_esync_fd( struct object *obj );
+static int process_get_esync_fd( struct object *obj, enum esync_type *type );
static void terminate_process( struct process *process, struct thread *skip, int exit_code );
static const struct object_ops process_ops =
@@ -77,7 +79,7 @@ static const struct object_ops process_ops =
@@ -78,7 +80,7 @@ static const struct object_ops process_ops =
add_queue, /* add_queue */
remove_queue, /* remove_queue */
process_signaled, /* signaled */
@ -119,7 +77,7 @@ index c4cb041f293..ed03210a5f5 100644
no_satisfied, /* satisfied */
no_signal, /* signal */
no_get_fd, /* get_fd */
@@ -531,6 +533,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
@@ -545,6 +547,7 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
process->trace_data = 0;
process->rawinput_mouse = NULL;
process->rawinput_kbd = NULL;
@ -127,9 +85,9 @@ index c4cb041f293..ed03210a5f5 100644
list_init( &process->kernel_object );
list_init( &process->thread_list );
list_init( &process->locks );
@@ -575,6 +578,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
}
if (!process->handles || !process->token) goto error;
@@ -601,6 +604,9 @@ struct process *create_process( int fd, struct process *parent, int inherit_all,
if (!token_assign_label( process->token, security_high_label_sid ))
goto error;
+ if (do_esync())
+ process->esync_fd = esync_create_fd( 0, 0 );
@ -137,23 +95,22 @@ index c4cb041f293..ed03210a5f5 100644
set_fd_events( process->msg_fd, POLLIN ); /* start listening to events */
return process;
@@ -623,6 +629,9 @@ static void process_destroy( struct object *obj )
@@ -649,6 +655,7 @@ static void process_destroy( struct object *obj )
if (process->id) free_ptid( process->id );
if (process->token) release_object( process->token );
free( process->dir_cache );
+
+ if (do_esync())
+ close( process->esync_fd );
+ if (do_esync()) close( process->esync_fd );
}
/* dump a process on stdout for debugging purposes */
@@ -647,6 +656,12 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry
@@ -673,6 +680,13 @@ static int process_signaled( struct object *obj, struct wait_queue_entry *entry
return !process->running_threads;
}
+static int process_get_esync_fd( struct object *obj )
+static int process_get_esync_fd( struct object *obj, enum esync_type *type )
+{
+ struct process *process = (struct process *)obj;
+ *type = ESYNC_MANUAL_SERVER;
+ return process->esync_fd;
+}
+
@ -161,17 +118,17 @@ index c4cb041f293..ed03210a5f5 100644
{
if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
diff --git a/server/process.h b/server/process.h
index 41267a27df5..02765f2f122 100644
index 56092e5b1ac..eec69ddbcaf 100644
--- a/server/process.h
+++ b/server/process.h
@@ -97,6 +97,7 @@ struct process
@@ -98,6 +98,7 @@ struct process
const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */
const struct rawinput_device *rawinput_kbd; /* rawinput keyboard device, if any */
struct list kernel_object; /* list of kernel object pointers */
+ int esync_fd; /* esync file descriptor (signaled on exit) */
};
struct process_snapshot
#define CPU_FLAG(cpu) (1 << (cpu))
--
2.20.1
2.28.0

Some files were not shown because too many files have changed in this diff Show More