linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Elizabeth Figura <zfigura@codeweavers.com>
To: Arnd Bergmann <arnd@arndb.de>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jonathan Corbet <corbet@lwn.net>, Shuah Khan <shuah@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
	wine-devel@winehq.org, "André Almeida" <andrealmeid@igalia.com>,
	"Wolfram Sang" <wsa@kernel.org>,
	"Arkadiusz Hiler" <ahiler@codeweavers.com>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Andy Lutomirski" <luto@kernel.org>,
	linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Elizabeth Figura" <zfigura@codeweavers.com>
Subject: [PATCH v2 00/31] NT synchronization primitive driver
Date: Mon, 19 Feb 2024 16:38:02 -0600	[thread overview]
Message-ID: <20240219223833.95710-1-zfigura@codeweavers.com> (raw)

This patch series introduces a new char misc driver, /dev/ntsync, which is used
to implement Windows NT synchronization primitives.

This was previously submitted as an RFC [1]. Since there were no major changes
requested to the last RFC revision, I've stripped the RFC prefix.

[1] https://lore.kernel.org/lkml/20240131021356.10322-1-zfigura@codeweavers.com/

== Background ==

The Wine project emulates the Windows API in user space. One particular part of
that API, namely the NT synchronization primitives, have historically been
implemented via RPC to a dedicated "kernel" process. However, more recent
applications use these APIs more strenuously, and the overhead of RPC has become
a bottleneck.

The NT synchronization APIs are too complex to implement on top of existing
primitives without sacrificing correctness. Certain operations, such as
NtPulseEvent() or the "wait-for-all" mode of NtWaitForMultipleObjects(), require
direct control over the underlying wait queue, and implementing a wait queue
sufficiently robust for Wine in user space is not possible. This proposed
driver, therefore, implements the problematic interfaces directly in the Linux
kernel.

This driver was presented at Linux Plumbers Conference 2023. For those further
interested in the history of synchronization in Wine and past attempts to solve
this problem in user space, a recording of the presentation can be viewed here:

    https://www.youtube.com/watch?v=NjU4nyWyhU8


== Performance ==

The gain in performance varies wildly depending on the application in question
and the user's hardware. For some games NT synchronization is not a bottleneck
and no change can be observed, but for others frame rate improvements of 50 to
150 percent are not atypical. The following table lists frame rate measurements
from a variety of games on a variety of hardware, taken by users Dmitry
Skvortsov, FuzzyQuils, OnMars, and myself:

Game                            Upstream        ntsync          improvement
===========================================================================
Anger Foot                       69              99              43%
Call of Juarez                   99.8           224.1           125%
Dirt 3                          110.6           860.7           678%
Forza Horizon 5                 108             160              48%
Lara Croft: Temple of Osiris    141             326             131%
Metro 2033                      164.4           199.2            21%
Resident Evil 2                  26              77             196%
The Crew                         26              51              96%
Tiny Tina's Wonderlands         130             360             177%
Total War Saga: Troy            109             146              34%
===========================================================================


== Patches ==

The intended semantics of the patches are broadly intended to match those of the
corresponding Windows functions. For those not already familiar with the Windows
functions (or their undocumented behaviour), patch 31/31 provides a detailed
specification, and individual patches also include a brief description of the
API they are implementing.

The patches making use of this driver in Wine can be retrieved or browsed here:

    https://repo.or.cz/wine/zf.git/shortlog/refs/heads/ntsync5


== Implementation ==

Some aspects of the implementation may deserve particular comment:

* In the interest of performance, each object is governed only by a single
  spinlock. However, NTSYNC_IOC_WAIT_ALL requires that the state of multiple
  objects be changed as a single atomic operation. In order to achieve this, we
  first take a device-wide lock ("wait_all_lock") any time we are going to lock
  more than one object at a time.

  The maximum number of objects that can be used in a vectored wait, and
  therefore the maximum that can be locked simultaneously, is 64. This number is
  NT's own limit.

  The acquisition of multiple spinlocks will degrade performance. This is a
  conscious choice, however. Wait-for-all is known to be a very rare operation
  in practice, especially with counts that approach the maximum, and it is the
  intent of the ntsync driver to optimize wait-for-any at the expense of
  wait-for-all as much as possible.

* NT mutexes are tied to their threads on an OS level, and the kernel includes
  builtin support for "robust" mutexes. In order to keep the ntsync driver
  self-contained and avoid touching more code than necessary, it does not hook
  into task exit nor use pids.

  Instead, the user space emulator is expected to manage thread IDs and pass
  them as an argument to any relevant functions; this is the "owner" field of
  ntsync_wait_args and ntsync_mutex_args.

  When the emulator detects that a thread dies, it should therefore call
  NTSYNC_IOC_MUTEX_KILL on any open mutexes.

* ntsync is module-capable mostly because there was nothing preventing it, and
  because it aided development. It is not a hard requirement, though.


== Previous versions ==

Changes from v1:

* Fix a broken rebase that stole part of the Kconfig documentation from the
  neighbouring entry, per Randy Dunlap.

* Add my email address to copyright and MODULE_AUTHOR lines, per Randy Dunlap.

* Document the reference counting behaviour more clearly, per Greg
  Kroah-Hartman.

* Hopefully submit all the patches this time the right way.

* Link to v1: https://lore.kernel.org/lkml/20240214233645.9273-1-zfigura@codeweavers.com/
* Link to RFC v2: https://lore.kernel.org/lkml/20240131021356.10322-1-zfigura@codeweavers.com/
* Link to RFC v1: https://lore.kernel.org/lkml/20240124004028.16826-1-zfigura@codeweavers.com/

Elizabeth Figura (31):
  ntsync: Introduce the ntsync driver and character device.
  ntsync: Introduce NTSYNC_IOC_CREATE_SEM.
  ntsync: Introduce NTSYNC_IOC_SEM_POST.
  ntsync: Introduce NTSYNC_IOC_WAIT_ANY.
  ntsync: Introduce NTSYNC_IOC_WAIT_ALL.
  ntsync: Introduce NTSYNC_IOC_CREATE_MUTEX.
  ntsync: Introduce NTSYNC_IOC_MUTEX_UNLOCK.
  ntsync: Introduce NTSYNC_IOC_MUTEX_KILL.
  ntsync: Introduce NTSYNC_IOC_CREATE_EVENT.
  ntsync: Introduce NTSYNC_IOC_EVENT_SET.
  ntsync: Introduce NTSYNC_IOC_EVENT_RESET.
  ntsync: Introduce NTSYNC_IOC_EVENT_PULSE.
  ntsync: Introduce NTSYNC_IOC_SEM_READ.
  ntsync: Introduce NTSYNC_IOC_MUTEX_READ.
  ntsync: Introduce NTSYNC_IOC_EVENT_READ.
  ntsync: Introduce alertable waits.
  ntsync: Allow waits to use the REALTIME clock.
  selftests: ntsync: Add some tests for semaphore state.
  selftests: ntsync: Add some tests for mutex state.
  selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY.
  selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ALL.
  selftests: ntsync: Add some tests for wakeup signaling with
    WINESYNC_IOC_WAIT_ANY.
  selftests: ntsync: Add some tests for wakeup signaling with
    WINESYNC_IOC_WAIT_ALL.
  selftests: ntsync: Add some tests for manual-reset event state.
  selftests: ntsync: Add some tests for auto-reset event state.
  selftests: ntsync: Add some tests for wakeup signaling with events.
  selftests: ntsync: Add tests for alertable waits.
  selftests: ntsync: Add some tests for wakeup signaling via alerts.
  selftests: ntsync: Add a stress test for contended waits.
  maintainers: Add an entry for ntsync.
  docs: ntsync: Add documentation for the ntsync uAPI.

Elizabeth Figura (31):
  ntsync: Introduce the ntsync driver and character device.
  ntsync: Introduce NTSYNC_IOC_CREATE_SEM.
  ntsync: Introduce NTSYNC_IOC_SEM_POST.
  ntsync: Introduce NTSYNC_IOC_WAIT_ANY.
  ntsync: Introduce NTSYNC_IOC_WAIT_ALL.
  ntsync: Introduce NTSYNC_IOC_CREATE_MUTEX.
  ntsync: Introduce NTSYNC_IOC_MUTEX_UNLOCK.
  ntsync: Introduce NTSYNC_IOC_MUTEX_KILL.
  ntsync: Introduce NTSYNC_IOC_CREATE_EVENT.
  ntsync: Introduce NTSYNC_IOC_EVENT_SET.
  ntsync: Introduce NTSYNC_IOC_EVENT_RESET.
  ntsync: Introduce NTSYNC_IOC_EVENT_PULSE.
  ntsync: Introduce NTSYNC_IOC_SEM_READ.
  ntsync: Introduce NTSYNC_IOC_MUTEX_READ.
  ntsync: Introduce NTSYNC_IOC_EVENT_READ.
  ntsync: Introduce alertable waits.
  ntsync: Allow waits to use the REALTIME clock.
  selftests: ntsync: Add some tests for semaphore state.
  selftests: ntsync: Add some tests for mutex state.
  selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY.
  selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ALL.
  selftests: ntsync: Add some tests for wakeup signaling with
    WINESYNC_IOC_WAIT_ANY.
  selftests: ntsync: Add some tests for wakeup signaling with
    WINESYNC_IOC_WAIT_ALL.
  selftests: ntsync: Add some tests for manual-reset event state.
  selftests: ntsync: Add some tests for auto-reset event state.
  selftests: ntsync: Add some tests for wakeup signaling with events.
  selftests: ntsync: Add tests for alertable waits.
  selftests: ntsync: Add some tests for wakeup signaling via alerts.
  selftests: ntsync: Add a stress test for contended waits.
  maintainers: Add an entry for ntsync.
  docs: ntsync: Add documentation for the ntsync uAPI.

 Documentation/userspace-api/index.rst         |    1 +
 .../userspace-api/ioctl/ioctl-number.rst      |    2 +
 Documentation/userspace-api/ntsync.rst        |  399 +++++
 MAINTAINERS                                   |    9 +
 drivers/misc/Kconfig                          |   11 +
 drivers/misc/Makefile                         |    1 +
 drivers/misc/ntsync.c                         | 1159 ++++++++++++++
 include/uapi/linux/ntsync.h                   |   62 +
 tools/testing/selftests/Makefile              |    1 +
 .../testing/selftests/drivers/ntsync/Makefile |    8 +
 tools/testing/selftests/drivers/ntsync/config |    1 +
 .../testing/selftests/drivers/ntsync/ntsync.c | 1407 +++++++++++++++++
 12 files changed, 3061 insertions(+)
 create mode 100644 Documentation/userspace-api/ntsync.rst
 create mode 100644 drivers/misc/ntsync.c
 create mode 100644 include/uapi/linux/ntsync.h
 create mode 100644 tools/testing/selftests/drivers/ntsync/Makefile
 create mode 100644 tools/testing/selftests/drivers/ntsync/config
 create mode 100644 tools/testing/selftests/drivers/ntsync/ntsync.c


base-commit: 8d11c6d9b14f7a87f65529cb33edc5fed846ed9d
-- 
2.43.0


             reply	other threads:[~2024-02-19 22:39 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-19 22:38 Elizabeth Figura [this message]
2024-02-19 22:38 ` [PATCH v2 01/31] ntsync: Introduce the ntsync driver and character device Elizabeth Figura
2024-02-22 10:56   ` Geert Uytterhoeven
2024-02-22 20:13     ` Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 02/31] ntsync: Introduce NTSYNC_IOC_CREATE_SEM Elizabeth Figura
2024-03-07 22:12   ` Greg Kroah-Hartman
2024-02-19 22:38 ` [PATCH v2 03/31] ntsync: Introduce NTSYNC_IOC_SEM_POST Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 04/31] ntsync: Introduce NTSYNC_IOC_WAIT_ANY Elizabeth Figura
2024-03-11 18:58   ` Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 05/31] ntsync: Introduce NTSYNC_IOC_WAIT_ALL Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 06/31] ntsync: Introduce NTSYNC_IOC_CREATE_MUTEX Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 07/31] ntsync: Introduce NTSYNC_IOC_MUTEX_UNLOCK Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 08/31] ntsync: Introduce NTSYNC_IOC_MUTEX_KILL Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 09/31] ntsync: Introduce NTSYNC_IOC_CREATE_EVENT Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 10/31] ntsync: Introduce NTSYNC_IOC_EVENT_SET Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 11/31] ntsync: Introduce NTSYNC_IOC_EVENT_RESET Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 12/31] ntsync: Introduce NTSYNC_IOC_EVENT_PULSE Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 13/31] ntsync: Introduce NTSYNC_IOC_SEM_READ Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 14/31] ntsync: Introduce NTSYNC_IOC_MUTEX_READ Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 15/31] ntsync: Introduce NTSYNC_IOC_EVENT_READ Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 16/31] ntsync: Introduce alertable waits Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 17/31] ntsync: Allow waits to use the REALTIME clock Elizabeth Figura
2024-02-20  7:01   ` Arnd Bergmann
2024-02-22  0:48     ` Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 18/31] selftests: ntsync: Add some tests for semaphore state Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 19/31] selftests: ntsync: Add some tests for mutex state Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 20/31] selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ANY Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 21/31] selftests: ntsync: Add some tests for NTSYNC_IOC_WAIT_ALL Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 22/31] selftests: ntsync: Add some tests for wakeup signaling with WINESYNC_IOC_WAIT_ANY Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 23/31] selftests: ntsync: Add some tests for wakeup signaling with WINESYNC_IOC_WAIT_ALL Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 24/31] selftests: ntsync: Add some tests for manual-reset event state Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 25/31] selftests: ntsync: Add some tests for auto-reset " Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 26/31] selftests: ntsync: Add some tests for wakeup signaling with events Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 27/31] selftests: ntsync: Add tests for alertable waits Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 28/31] selftests: ntsync: Add some tests for wakeup signaling via alerts Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 29/31] selftests: ntsync: Add a stress test for contended waits Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 30/31] maintainers: Add an entry for ntsync Elizabeth Figura
2024-02-19 22:38 ` [PATCH v2 31/31] docs: ntsync: Add documentation for the ntsync uAPI Elizabeth Figura

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240219223833.95710-1-zfigura@codeweavers.com \
    --to=zfigura@codeweavers.com \
    --cc=ahiler@codeweavers.com \
    --cc=andrealmeid@igalia.com \
    --cc=arnd@arndb.de \
    --cc=corbet@lwn.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rdunlap@infradead.org \
    --cc=shuah@kernel.org \
    --cc=wine-devel@winehq.org \
    --cc=wsa@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).