From: Elizabeth Figura <zfigura@codeweavers.com>
To: Arnd Bergmann <arnd@arndb.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-kernel@vger.kernel.org, linux-api@vger.kernel.org
Cc: wine-devel@winehq.org, "André Almeida" <andrealmeid@igalia.com>,
"Wolfram Sang" <wsa@kernel.org>,
"Arkadiusz Hiler" <ahiler@codeweavers.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Elizabeth Figura" <zfigura@codeweavers.com>
Subject: [RFC PATCH 9/9] ntsync: Introduce NTSYNC_IOC_KILL_OWNER.
Date: Tue, 23 Jan 2024 18:40:28 -0600 [thread overview]
Message-ID: <20240124004028.16826-10-zfigura@codeweavers.com> (raw)
In-Reply-To: <20240124004028.16826-1-zfigura@codeweavers.com>
This does not correspond to any NT syscall, but rather should be called by the
user-space NT emulator when a thread dies. It is responsible for marking any
mutexes owned by that thread as abandoned.
Signed-off-by: Elizabeth Figura <zfigura@codeweavers.com>
---
drivers/misc/ntsync.c | 80 ++++++++++++++++++++++++++++++++++++-
include/uapi/linux/ntsync.h | 1 +
2 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/drivers/misc/ntsync.c b/drivers/misc/ntsync.c
index 28f43768d1c3..1173c750c106 100644
--- a/drivers/misc/ntsync.c
+++ b/drivers/misc/ntsync.c
@@ -64,6 +64,7 @@ struct ntsync_obj {
struct {
__u32 count;
__u32 owner;
+ bool ownerdead;
} mutex;
} u;
};
@@ -87,6 +88,7 @@ struct ntsync_q {
atomic_t signaled;
bool all;
+ bool ownerdead;
__u32 count;
struct ntsync_q_entry entries[];
};
@@ -240,6 +242,9 @@ static void try_wake_all(struct ntsync_device *dev, struct ntsync_q *q,
obj->u.sem.count--;
break;
case NTSYNC_TYPE_MUTEX:
+ if (obj->u.mutex.ownerdead)
+ q->ownerdead = true;
+ obj->u.mutex.ownerdead = false;
obj->u.mutex.count++;
obj->u.mutex.owner = q->owner;
break;
@@ -299,6 +304,9 @@ static void try_wake_any_mutex(struct ntsync_obj *mutex)
continue;
if (atomic_cmpxchg(&q->signaled, -1, entry->index) == -1) {
+ if (mutex->u.mutex.ownerdead)
+ q->ownerdead = true;
+ mutex->u.mutex.ownerdead = false;
mutex->u.mutex.count++;
mutex->u.mutex.owner = q->owner;
wake_up_process(q->task);
@@ -514,6 +522,71 @@ static int ntsync_put_mutex(struct ntsync_device *dev, void __user *argp)
return ret;
}
+/*
+ * Actually change the mutex state to mark its owner as dead.
+ */
+static void put_mutex_ownerdead_state(struct ntsync_obj *mutex)
+{
+ lockdep_assert_held(&mutex->lock);
+
+ mutex->u.mutex.ownerdead = true;
+ mutex->u.mutex.owner = 0;
+ mutex->u.mutex.count = 0;
+}
+
+static int ntsync_kill_owner(struct ntsync_device *dev, void __user *argp)
+{
+ struct ntsync_obj *obj;
+ unsigned long id;
+ __u32 owner;
+
+ if (get_user(owner, (__u32 __user *)argp))
+ return -EFAULT;
+ if (!owner)
+ return -EINVAL;
+
+ rcu_read_lock();
+
+ xa_for_each(&dev->objects, id, obj) {
+ if (!kref_get_unless_zero(&obj->refcount))
+ continue;
+
+ if (obj->type != NTSYNC_TYPE_MUTEX) {
+ put_obj(obj);
+ continue;
+ }
+
+ if (atomic_read(&obj->all_hint) > 0) {
+ spin_lock(&dev->wait_all_lock);
+ spin_lock_nest_lock(&obj->lock, &dev->wait_all_lock);
+
+ if (obj->u.mutex.owner == owner) {
+ put_mutex_ownerdead_state(obj);
+ try_wake_all_obj(dev, obj);
+ try_wake_any_mutex(obj);
+ }
+
+ spin_unlock(&obj->lock);
+ spin_unlock(&dev->wait_all_lock);
+ } else {
+ spin_lock(&obj->lock);
+
+ if (obj->u.mutex.owner == owner) {
+ put_mutex_ownerdead_state(obj);
+ try_wake_any_mutex(obj);
+ }
+
+ spin_unlock(&obj->lock);
+ }
+
+ put_obj(obj);
+ }
+
+ rcu_read_unlock();
+
+ return 0;
+}
+
static int ntsync_schedule(const struct ntsync_q *q, ktime_t *timeout)
{
int ret = 0;
@@ -585,6 +658,7 @@ static int setup_wait(struct ntsync_device *dev,
q->owner = args->owner;
atomic_set(&q->signaled, -1);
q->all = all;
+ q->ownerdead = false;
q->count = count;
for (i = 0; i < count; i++) {
@@ -697,7 +771,7 @@ static int ntsync_wait_any(struct ntsync_device *dev, void __user *argp)
struct ntsync_wait_args __user *user_args = argp;
/* even if we caught a signal, we need to communicate success */
- ret = 0;
+ ret = q->ownerdead ? -EOWNERDEAD : 0;
if (put_user(signaled, &user_args->index))
ret = -EFAULT;
@@ -778,7 +852,7 @@ static int ntsync_wait_all(struct ntsync_device *dev, void __user *argp)
struct ntsync_wait_args __user *user_args = argp;
/* even if we caught a signal, we need to communicate success */
- ret = 0;
+ ret = q->ownerdead ? -EOWNERDEAD : 0;
if (put_user(signaled, &user_args->index))
ret = -EFAULT;
@@ -803,6 +877,8 @@ static long ntsync_char_ioctl(struct file *file, unsigned int cmd,
return ntsync_create_sem(dev, argp);
case NTSYNC_IOC_DELETE:
return ntsync_delete(dev, argp);
+ case NTSYNC_IOC_KILL_OWNER:
+ return ntsync_kill_owner(dev, argp);
case NTSYNC_IOC_PUT_MUTEX:
return ntsync_put_mutex(dev, argp);
case NTSYNC_IOC_PUT_SEM:
diff --git a/include/uapi/linux/ntsync.h b/include/uapi/linux/ntsync.h
index 2e44e7e77776..fec9a3993322 100644
--- a/include/uapi/linux/ntsync.h
+++ b/include/uapi/linux/ntsync.h
@@ -48,5 +48,6 @@ struct ntsync_wait_args {
struct ntsync_mutex_args)
#define NTSYNC_IOC_PUT_MUTEX _IOWR(NTSYNC_IOC_BASE, 6, \
struct ntsync_mutex_args)
+#define NTSYNC_IOC_KILL_OWNER _IOW (NTSYNC_IOC_BASE, 7, __u32)
#endif
--
2.43.0
next prev parent reply other threads:[~2024-01-24 0:58 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-24 0:40 [RFC PATCH 0/9] NT synchronization primitive driver Elizabeth Figura
2024-01-24 0:40 ` [RFC PATCH 1/9] ntsync: Introduce the ntsync driver and character device Elizabeth Figura
2024-01-24 7:38 ` Arnd Bergmann
2024-01-24 17:51 ` Elizabeth Figura
2024-01-24 21:26 ` Andy Lutomirski
2024-01-24 22:56 ` Elizabeth Figura
2024-01-25 3:42 ` Elizabeth Figura
2024-01-25 16:47 ` Arnd Bergmann
2024-01-25 18:21 ` Elizabeth Figura
2024-01-25 18:55 ` Andy Lutomirski
2024-01-25 21:45 ` Elizabeth Figura
2024-01-25 7:41 ` Alexandre Julliard
2024-01-24 0:40 ` [RFC PATCH 2/9] ntsync: Reserve a minor device number and ioctl range Elizabeth Figura
2024-01-24 0:54 ` Greg Kroah-Hartman
2024-01-24 3:43 ` Elizabeth Figura
2024-01-24 12:32 ` Greg Kroah-Hartman
2024-01-24 17:59 ` Elizabeth Figura
2024-01-24 0:40 ` [RFC PATCH 3/9] ntsync: Introduce NTSYNC_IOC_CREATE_SEM and NTSYNC_IOC_DELETE Elizabeth Figura
2024-01-24 1:14 ` Greg Kroah-Hartman
2024-01-24 3:35 ` Elizabeth Figura
2024-01-24 0:40 ` [RFC PATCH 4/9] ntsync: Introduce NTSYNC_IOC_PUT_SEM Elizabeth Figura
2024-01-25 8:59 ` Nikolay Borisov
2024-01-24 0:40 ` [RFC PATCH 5/9] ntsync: Introduce NTSYNC_IOC_WAIT_ANY Elizabeth Figura
2024-01-24 7:56 ` Arnd Bergmann
2024-01-24 18:02 ` Elizabeth Figura
2024-01-24 19:52 ` Arnd Bergmann
2024-01-24 22:28 ` Elizabeth Figura
2024-01-25 17:02 ` Arnd Bergmann
2024-01-25 18:30 ` Elizabeth Figura
2024-01-24 0:40 ` [RFC PATCH 6/9] ntsync: Introduce NTSYNC_IOC_WAIT_ALL Elizabeth Figura
2024-01-24 0:40 ` [RFC PATCH 7/9] ntsync: Introduce NTSYNC_IOC_CREATE_MUTEX Elizabeth Figura
2024-01-24 0:40 ` [RFC PATCH 8/9] ntsync: Introduce NTSYNC_IOC_PUT_MUTEX Elizabeth Figura
2024-01-24 7:42 ` Arnd Bergmann
2024-01-24 18:03 ` Elizabeth Figura
2024-01-24 19:53 ` Arnd Bergmann
2024-01-24 0:40 ` Elizabeth Figura [this message]
2024-01-24 0:59 ` [RFC PATCH 0/9] NT synchronization primitive driver Greg Kroah-Hartman
2024-01-24 1:37 ` Elizabeth Figura
2024-01-24 12:29 ` Greg Kroah-Hartman
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=20240124004028.16826-10-zfigura@codeweavers.com \
--to=zfigura@codeweavers.com \
--cc=ahiler@codeweavers.com \
--cc=andrealmeid@igalia.com \
--cc=arnd@arndb.de \
--cc=gregkh@linuxfoundation.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.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).